@@ -66,6 +66,7 @@ static int dma_trace_new_buffer(struct dma_trace_data *d, uint32_t buffer_size)
6666 buffer -> size = buffer_size ;
6767 buffer -> w_ptr = buffer -> r_ptr = buffer -> addr ;
6868 buffer -> end_addr = buffer -> addr + buffer -> size ;
69+ buffer -> avail = 0 ;
6970
7071 return 0 ;
7172}
@@ -74,25 +75,61 @@ static void trace_send(struct dma_trace_data *d)
7475{
7576 struct dma_trace_buf * buffer = & d -> dmatb ;
7677 struct dma_sg_config * config = & d -> config ;
77- uint32_t size = 0 ;
78+ unsigned long flags ;
7879 int32_t offset = 0 ;
79-
80- if (buffer -> w_ptr == buffer -> r_ptr )
80+ uint32_t avail = buffer -> avail ;
81+ uint32_t bytes_copied = avail ;
82+ uint32_t size ;
83+ uint32_t hsize ;
84+ uint32_t lsize ;
85+
86+ /* any data to copy ? */
87+ if (avail == 0 )
8188 return ;
8289
83- size = buffer -> w_ptr - buffer -> r_ptr ;
84- if (d -> host_offset + size > d -> host_size )
85- d -> host_offset = 0 ;
90+ /* copy to host in sections if we wrap */
91+ while (avail > 0 ) {
8692
87- offset = dma_copy_to_host (config , d -> host_offset ,
88- buffer -> r_ptr , size );
89- if (offset < 0 ) {
90- trace_buffer_error ("ebb" );
91- return ;
93+ lsize = hsize = avail ;
94+
95+ /* host buffer wrap ? */
96+ if (d -> host_offset + buffer -> avail > d -> host_size )
97+ hsize = d -> host_offset + buffer -> avail - d -> host_size ;
98+
99+ /* local buffer wrap ? */
100+ if (buffer -> r_ptr > buffer -> w_ptr )
101+ lsize = buffer -> end_addr - buffer -> r_ptr ;
102+
103+ /* get smallest size */
104+ if (hsize < lsize )
105+ size = hsize ;
106+ else
107+ size = lsize ;
108+
109+ /* copy this section to host */
110+ offset = dma_copy_to_host (config , d -> host_offset ,
111+ buffer -> r_ptr , size );
112+ if (offset < 0 ) {
113+ trace_buffer_error ("ebb" );
114+ return ;
115+ }
116+
117+ /* update host pointer and check for wrap */
118+ d -> host_offset += size ;
119+ if (d -> host_offset + size >= d -> host_size )
120+ d -> host_offset = 0 ;
121+
122+ /* update local pointer and check for wrap */
123+ buffer -> r_ptr += size ;
124+ if (buffer -> r_ptr >= buffer -> end_addr )
125+ buffer -> r_ptr = buffer -> addr ;
126+
127+ avail -= size ;
92128 }
93129
94- d -> host_offset += size ;
95- buffer -> r_ptr += size ;
130+ spin_lock_irq (& d -> lock , flags );
131+ buffer -> avail -= bytes_copied ;
132+ spin_unlock_irq (& d -> lock , flags );
96133}
97134
98135static uint64_t trace_work (void * data , uint64_t delay )
@@ -125,6 +162,7 @@ int dma_trace_init(struct dma_trace_data *d)
125162 trace_data = d ;
126163
127164 work_init (& d -> dmat_work , trace_work , d , WORK_ASYNC );
165+ spinlock_init (& d -> lock );
128166 return 0 ;
129167}
130168
@@ -155,34 +193,39 @@ void dtrace_event(const char *e, uint32_t length)
155193{
156194 struct dma_trace_buf * buffer = NULL ;
157195 int margin = 0 ;
196+ unsigned long flags ;
158197
159- if (trace_data == NULL || length < 1 )
198+ if (trace_data == NULL || length == 0 )
160199 return ;
161200
162201 buffer = & trace_data -> dmatb ;
163202 if (buffer == NULL )
164203 return ;
165204
205+ spin_lock_irq (& trace_data -> lock , flags );
206+
166207 margin = buffer -> end_addr - buffer -> w_ptr ;
167208
209+ /* check for buffer wrap */
168210 if (margin > length ) {
211+
212+ /* no wrap */
169213 memcpy (buffer -> w_ptr , e , length );
170214 buffer -> w_ptr += length ;
171215 } else {
172- memcpy (buffer -> w_ptr , e , margin );
173- buffer -> w_ptr += margin ;
174216
175- if (trace_data -> ready )
176- trace_send (trace_data );
177-
178- buffer -> w_ptr = buffer -> r_ptr = buffer -> addr ;
179- bzero (buffer -> addr , buffer -> size );
217+ /* data is bigger than remaining margin so we wrap */
218+ memcpy (buffer -> w_ptr , e , margin );
219+ buffer -> w_ptr = buffer -> addr ;
180220
181221 memcpy (buffer -> w_ptr , e + margin , length - margin );
182- buffer -> w_ptr += length - margin ;
222+ buffer -> w_ptr += length - margin ;
183223 }
184224
185- length = buffer -> w_ptr - buffer -> r_ptr ;
186- if (trace_data -> ready && length >= (DMA_TRACE_LOCAL_SIZE / 2 ))
187- trace_send (trace_data );
225+ buffer -> avail += length ;
226+ spin_unlock_irq (& trace_data -> lock , flags );
227+
228+ /* schedule copy now if buffer > 50% full */
229+ if (trace_data -> ready && buffer -> avail >= (DMA_TRACE_LOCAL_SIZE / 2 ))
230+ work_reschedule_default (& trace_data -> dmat_work , 100 );
188231}
0 commit comments