Skip to content

Commit 3dca7b7

Browse files
committed
trace: dma: Add atomic and nowait DMA tracing support.
Add support for DMA trace to run in atomic and IRQ contexts. Currently DMA trace would sleep between DMA copies and enter atomic state when inserting new tarce data into the trace buffer. This patch adds new DMA _nowait() APIs that dont sleep and _atomic() APIs for trace logging that can be safely called in atomic context. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
1 parent 1e5c559 commit 3dca7b7

File tree

6 files changed

+301
-73
lines changed

6 files changed

+301
-73
lines changed

src/audio/dma-trace.c

Lines changed: 86 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ static uint64_t trace_work(void *data, uint64_t delay)
4747
struct dma_trace_buf *buffer = &d->dmatb;
4848
struct dma_sg_config *config = &d->config;
4949
unsigned long flags;
50-
int32_t offset = 0;
5150
uint32_t avail = buffer->avail;
52-
uint32_t bytes_copied = 0;
5351
uint32_t size;
5452
uint32_t hsize;
5553
uint32_t lsize;
@@ -58,53 +56,51 @@ static uint64_t trace_work(void *data, uint64_t delay)
5856
if (avail == 0)
5957
return DMA_TRACE_US;
6058

59+
/* make sure we dont write more than buffer */
60+
if (avail > DMA_TRACE_LOCAL_SIZE)
61+
avail = DMA_TRACE_LOCAL_SIZE;
62+
6163
/* copy to host in sections if we wrap */
62-
while (avail > 0) {
63-
64-
lsize = hsize = avail;
65-
66-
/* host buffer wrap ? */
67-
if (d->host_offset + buffer->avail > d->host_size)
68-
hsize = d->host_offset + buffer->avail - d->host_size;
69-
70-
/* local buffer wrap ? */
71-
if (buffer->r_ptr > buffer->w_ptr)
72-
lsize = buffer->end_addr - buffer->r_ptr;
73-
74-
/* get smallest size */
75-
if (hsize < lsize)
76-
size = hsize;
77-
else
78-
size = lsize;
79-
80-
/* writeback trace data */
81-
dcache_writeback_region((void*)buffer->r_ptr, size);
82-
83-
/* copy this section to host */
84-
offset = dma_copy_to_host(&d->dc, config, d->host_offset,
85-
buffer->r_ptr, size);
86-
if (offset < 0) {
87-
trace_buffer_error("ebb");
88-
goto out;
89-
}
90-
91-
/* update host pointer and check for wrap */
92-
d->host_offset += size;
93-
if (d->host_offset + size >= d->host_size)
94-
d->host_offset = 0;
95-
96-
/* update local pointer and check for wrap */
97-
buffer->r_ptr += size;
98-
if (buffer->r_ptr >= buffer->end_addr)
99-
buffer->r_ptr = buffer->addr;
100-
101-
avail -= size;
102-
bytes_copied += size;
64+
lsize = hsize = avail;
65+
66+
/* host buffer wrap ? */
67+
if (d->host_offset + avail > d->host_size)
68+
hsize = d->host_size - d->host_offset;
69+
70+
/* local buffer wrap ? */
71+
if (buffer->r_ptr + avail > buffer->end_addr)
72+
lsize = buffer->end_addr - buffer->r_ptr;
73+
74+
/* get smallest size */
75+
if (hsize < lsize)
76+
size = hsize;
77+
else
78+
size = lsize;
79+
80+
/* writeback trace data */
81+
dcache_writeback_region((void*)buffer->r_ptr, size);
82+
83+
/* copy this section to host */
84+
size = dma_copy_to_host_nowait(&d->dc, config, d->host_offset,
85+
buffer->r_ptr, size);
86+
if (size < 0) {
87+
trace_buffer_error("ebb");
88+
goto out;
10389
}
10490

91+
/* update host pointer and check for wrap */
92+
d->host_offset += size;
93+
if (d->host_offset + size >= d->host_size)
94+
d->host_offset = 0;
95+
96+
/* update local pointer and check for wrap */
97+
buffer->r_ptr += size;
98+
if (buffer->r_ptr >= buffer->end_addr)
99+
buffer->r_ptr = buffer->addr;
100+
105101
out:
106102
spin_lock_irq(&d->lock, flags);
107-
buffer->avail -= bytes_copied;
103+
buffer->avail -= size;
108104
spin_unlock_irq(&d->lock, flags);
109105

110106
/* reschedule the trace copying work */
@@ -172,32 +168,28 @@ int dma_trace_enable(struct dma_trace_data *d)
172168
{
173169
/* validate DMA context */
174170
if (d->dc.dmac == NULL || d->dc.chan < 0) {
175-
trace_buffer_error("eem");
171+
trace_error_atomic(TRACE_CLASS_BUFFER, "eem");
176172
return -ENODEV;
177173
}
178174

179175
/* TODO: fix crash when enabled */
180-
//d->enabled = 1;
176+
d->enabled = 1;
181177
work_schedule_default(&d->dmat_work, DMA_TRACE_US);
182178
return 0;
183179
}
184180

185-
void dtrace_event(const char *e, uint32_t length)
181+
static void dtrace_add_event(const char *e, uint32_t length)
186182
{
187-
struct dma_trace_buf *buffer = NULL;
188-
int margin = 0;
189-
unsigned long flags;
183+
struct dma_trace_buf *buffer = &trace_data->dmatb;
184+
int margin;
190185

191-
if (trace_data == NULL || length == 0)
192-
return;
186+
margin = buffer->end_addr - buffer->w_ptr;
193187

194-
buffer = &trace_data->dmatb;
195-
if (buffer == NULL)
188+
/* validate */
189+
if (margin <= 0) {
190+
trace_buffer_error("emm");
196191
return;
197-
198-
spin_lock_irq(&trace_data->lock, flags);
199-
200-
margin = buffer->end_addr - buffer->w_ptr;
192+
}
201193

202194
/* check for buffer wrap */
203195
if (margin > length) {
@@ -216,9 +208,45 @@ void dtrace_event(const char *e, uint32_t length)
216208
}
217209

218210
buffer->avail += length;
211+
}
212+
213+
void dtrace_event(const char *e, uint32_t length)
214+
{
215+
struct dma_trace_buf *buffer = NULL;
216+
unsigned long flags;
217+
218+
if (trace_data == NULL || length == 0)
219+
return;
220+
221+
if (!trace_data->enabled)
222+
return;
223+
224+
buffer = &trace_data->dmatb;
225+
if (buffer == NULL)
226+
return;
227+
228+
spin_lock_irq(&trace_data->lock, flags);
229+
dtrace_add_event(e, length);
219230
spin_unlock_irq(&trace_data->lock, flags);
220231

221232
/* schedule copy now if buffer > 50% full */
222233
if (trace_data->enabled && buffer->avail >= (DMA_TRACE_LOCAL_SIZE / 2))
223234
work_reschedule_default(&trace_data->dmat_work, 100);
224235
}
236+
237+
void dtrace_event_atomic(const char *e, uint32_t length)
238+
{
239+
struct dma_trace_buf *buffer = NULL;
240+
241+
if (trace_data == NULL || length == 0)
242+
return;
243+
244+
if (!trace_data->enabled)
245+
return;
246+
247+
buffer = &trace_data->dmatb;
248+
if (buffer == NULL)
249+
return;
250+
251+
dtrace_add_event(e, length);
252+
}

src/include/reef/audio/dma-trace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@ int dma_trace_host_buffer(struct dma_trace_data *d, struct dma_sg_elem *elem,
6969
int dma_trace_enable(struct dma_trace_data *d);
7070

7171
void dtrace_event(const char *e, uint32_t size);
72+
void dtrace_event_atomic(const char *e, uint32_t length);
7273

7374
#endif

src/include/reef/dma.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,9 +249,13 @@ static inline void dma_copy_free(struct dma_copy *dc)
249249
/* DMA copy data from host to DSP */
250250
int dma_copy_from_host(struct dma_copy *dc, struct dma_sg_config *host_sg,
251251
int32_t host_offset, void *local_ptr, int32_t size);
252+
int dma_copy_from_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg,
253+
int32_t host_offset, void *local_ptr, int32_t size);
252254

253255
/* DMA copy data from DSP to host */
254256
int dma_copy_to_host(struct dma_copy *dc, struct dma_sg_config *host_sg,
255257
int32_t host_offset, void *local_ptr, int32_t size);
258+
int dma_copy_to_host_nowait(struct dma_copy *dc, struct dma_sg_config *host_sg,
259+
int32_t host_offset, void *local_ptr, int32_t size);
256260

257261
#endif

src/include/reef/trace.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,33 +95,45 @@
9595

9696
void _trace_event(uint32_t event);
9797
void _trace_error(uint32_t event);
98+
void _trace_event_atomic(uint32_t event);
99+
void _trace_error_atomic(uint32_t event);
98100
void trace_off(void);
99101
void trace_init(struct reef * reef);
100102

101103
#if TRACE
102104

103105
#define trace_event(__c, __e) \
104106
_trace_event(__c | (__e[0] << 16) | (__e[1] <<8) | __e[2])
107+
#define trace_event_atomic(__c, __e) \
108+
_trace_event_atomic(__c | (__e[0] << 16) | (__e[1] <<8) | __e[2])
105109

106110
#define trace_value(x) _trace_event(x)
111+
#define trace_value_atomic(x) _trace_event_atomic(x)
107112

108113
#define trace_point(x) platform_trace_point(x)
109114

110115
/* verbose tracing */
111116
#if TRACEV
112117
#define tracev_event(__c, __e) trace_event(__c, __e)
113118
#define tracev_value(x) _trace_event(x)
119+
#define tracev_event_atomic(__c, __e) trace_event_atomic(__c, __e)
120+
#define tracev_value_atomic(x) _trace_event_atomic(x)
114121
#else
115122
#define tracev_event(__c, __e)
116123
#define tracev_value(x)
124+
#define tracev_event_atomic(__c, __e)
125+
#define tracev_value_atomic(x)
117126
#endif
118127

119128
/* error tracing */
120129
#if TRACEE
121130
#define trace_error(__c, __e) \
122131
_trace_error(__c | (__e[0] << 16) | (__e[1] <<8) | __e[2])
132+
#define trace_error_atomic(__c, __e) \
133+
_trace_error_atomic(__c | (__e[0] << 16) | (__e[1] <<8) | __e[2])
123134
#else
124135
#define trace_error(__c, __e)
136+
#define trace_error_atomic(__c, __e)
125137
#endif
126138

127139
#else

0 commit comments

Comments
 (0)