1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "pvrusb2-io.h"
22#include "pvrusb2-debug.h"
23#include <linux/errno.h>
24#include <linux/string.h>
25#include <linux/slab.h>
26#include <linux/mutex.h>
27
28static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
29
30#define BUFFER_SIG 0x47653271
31
32
33
34
35#ifdef SANITY_CHECK_BUFFERS
36#define BUFFER_CHECK(bp) do { \
37 if ((bp)->signature != BUFFER_SIG) { \
38 pvr2_trace(PVR2_TRACE_ERROR_LEGS, \
39 "Buffer %p is bad at %s:%d", \
40 (bp),__FILE__,__LINE__); \
41 pvr2_buffer_describe(bp,"BadSig"); \
42 BUG(); \
43 } \
44} while (0)
45#else
46#define BUFFER_CHECK(bp) do {} while(0)
47#endif
48
49struct pvr2_stream {
50
51 struct list_head queued_list;
52 unsigned int q_count;
53 unsigned int q_bcount;
54
55 struct list_head ready_list;
56 unsigned int r_count;
57 unsigned int r_bcount;
58
59 struct list_head idle_list;
60 unsigned int i_count;
61 unsigned int i_bcount;
62
63 struct pvr2_buffer **buffers;
64
65 unsigned int buffer_slot_count;
66
67 unsigned int buffer_total_count;
68
69 unsigned int buffer_target_count;
70
71 pvr2_stream_callback callback_func;
72 void *callback_data;
73
74 struct usb_device *dev;
75 int endpoint;
76
77 spinlock_t list_lock;
78 struct mutex mutex;
79
80 unsigned int fail_count;
81 unsigned int fail_tolerance;
82
83 unsigned int buffers_processed;
84 unsigned int buffers_failed;
85 unsigned int bytes_processed;
86};
87
88struct pvr2_buffer {
89 int id;
90 int signature;
91 enum pvr2_buffer_state state;
92 void *ptr;
93 unsigned int max_count;
94 unsigned int used_count;
95 int status;
96 struct pvr2_stream *stream;
97 struct list_head list_overhead;
98 struct urb *purb;
99};
100
101static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
102{
103 switch (st) {
104 case pvr2_buffer_state_none: return "none";
105 case pvr2_buffer_state_idle: return "idle";
106 case pvr2_buffer_state_queued: return "queued";
107 case pvr2_buffer_state_ready: return "ready";
108 }
109 return "unknown";
110}
111
112#ifdef SANITY_CHECK_BUFFERS
113static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
114{
115 pvr2_trace(PVR2_TRACE_INFO,
116 "buffer%s%s %p state=%s id=%d status=%d"
117 " stream=%p purb=%p sig=0x%x",
118 (msg ? " " : ""),
119 (msg ? msg : ""),
120 bp,
121 (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
122 (bp ? bp->id : 0),
123 (bp ? bp->status : 0),
124 (bp ? bp->stream : NULL),
125 (bp ? bp->purb : NULL),
126 (bp ? bp->signature : 0));
127}
128#endif
129
130static void pvr2_buffer_remove(struct pvr2_buffer *bp)
131{
132 unsigned int *cnt;
133 unsigned int *bcnt;
134 unsigned int ccnt;
135 struct pvr2_stream *sp = bp->stream;
136 switch (bp->state) {
137 case pvr2_buffer_state_idle:
138 cnt = &sp->i_count;
139 bcnt = &sp->i_bcount;
140 ccnt = bp->max_count;
141 break;
142 case pvr2_buffer_state_queued:
143 cnt = &sp->q_count;
144 bcnt = &sp->q_bcount;
145 ccnt = bp->max_count;
146 break;
147 case pvr2_buffer_state_ready:
148 cnt = &sp->r_count;
149 bcnt = &sp->r_bcount;
150 ccnt = bp->used_count;
151 break;
152 default:
153 return;
154 }
155 list_del_init(&bp->list_overhead);
156 (*cnt)--;
157 (*bcnt) -= ccnt;
158 pvr2_trace(PVR2_TRACE_BUF_FLOW,
159 "/*---TRACE_FLOW---*/"
160 " bufferPool %8s dec cap=%07d cnt=%02d",
161 pvr2_buffer_state_decode(bp->state),*bcnt,*cnt);
162 bp->state = pvr2_buffer_state_none;
163}
164
165static void pvr2_buffer_set_none(struct pvr2_buffer *bp)
166{
167 unsigned long irq_flags;
168 struct pvr2_stream *sp;
169 BUFFER_CHECK(bp);
170 sp = bp->stream;
171 pvr2_trace(PVR2_TRACE_BUF_FLOW,
172 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
173 bp,
174 pvr2_buffer_state_decode(bp->state),
175 pvr2_buffer_state_decode(pvr2_buffer_state_none));
176 spin_lock_irqsave(&sp->list_lock,irq_flags);
177 pvr2_buffer_remove(bp);
178 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
179}
180
181static int pvr2_buffer_set_ready(struct pvr2_buffer *bp)
182{
183 int fl;
184 unsigned long irq_flags;
185 struct pvr2_stream *sp;
186 BUFFER_CHECK(bp);
187 sp = bp->stream;
188 pvr2_trace(PVR2_TRACE_BUF_FLOW,
189 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
190 bp,
191 pvr2_buffer_state_decode(bp->state),
192 pvr2_buffer_state_decode(pvr2_buffer_state_ready));
193 spin_lock_irqsave(&sp->list_lock,irq_flags);
194 fl = (sp->r_count == 0);
195 pvr2_buffer_remove(bp);
196 list_add_tail(&bp->list_overhead,&sp->ready_list);
197 bp->state = pvr2_buffer_state_ready;
198 (sp->r_count)++;
199 sp->r_bcount += bp->used_count;
200 pvr2_trace(PVR2_TRACE_BUF_FLOW,
201 "/*---TRACE_FLOW---*/"
202 " bufferPool %8s inc cap=%07d cnt=%02d",
203 pvr2_buffer_state_decode(bp->state),
204 sp->r_bcount,sp->r_count);
205 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
206 return fl;
207}
208
209static void pvr2_buffer_set_idle(struct pvr2_buffer *bp)
210{
211 unsigned long irq_flags;
212 struct pvr2_stream *sp;
213 BUFFER_CHECK(bp);
214 sp = bp->stream;
215 pvr2_trace(PVR2_TRACE_BUF_FLOW,
216 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
217 bp,
218 pvr2_buffer_state_decode(bp->state),
219 pvr2_buffer_state_decode(pvr2_buffer_state_idle));
220 spin_lock_irqsave(&sp->list_lock,irq_flags);
221 pvr2_buffer_remove(bp);
222 list_add_tail(&bp->list_overhead,&sp->idle_list);
223 bp->state = pvr2_buffer_state_idle;
224 (sp->i_count)++;
225 sp->i_bcount += bp->max_count;
226 pvr2_trace(PVR2_TRACE_BUF_FLOW,
227 "/*---TRACE_FLOW---*/"
228 " bufferPool %8s inc cap=%07d cnt=%02d",
229 pvr2_buffer_state_decode(bp->state),
230 sp->i_bcount,sp->i_count);
231 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
232}
233
234static void pvr2_buffer_set_queued(struct pvr2_buffer *bp)
235{
236 unsigned long irq_flags;
237 struct pvr2_stream *sp;
238 BUFFER_CHECK(bp);
239 sp = bp->stream;
240 pvr2_trace(PVR2_TRACE_BUF_FLOW,
241 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
242 bp,
243 pvr2_buffer_state_decode(bp->state),
244 pvr2_buffer_state_decode(pvr2_buffer_state_queued));
245 spin_lock_irqsave(&sp->list_lock,irq_flags);
246 pvr2_buffer_remove(bp);
247 list_add_tail(&bp->list_overhead,&sp->queued_list);
248 bp->state = pvr2_buffer_state_queued;
249 (sp->q_count)++;
250 sp->q_bcount += bp->max_count;
251 pvr2_trace(PVR2_TRACE_BUF_FLOW,
252 "/*---TRACE_FLOW---*/"
253 " bufferPool %8s inc cap=%07d cnt=%02d",
254 pvr2_buffer_state_decode(bp->state),
255 sp->q_bcount,sp->q_count);
256 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
257}
258
259static void pvr2_buffer_wipe(struct pvr2_buffer *bp)
260{
261 if (bp->state == pvr2_buffer_state_queued) {
262 usb_kill_urb(bp->purb);
263 }
264}
265
266static int pvr2_buffer_init(struct pvr2_buffer *bp,
267 struct pvr2_stream *sp,
268 unsigned int id)
269{
270 memset(bp,0,sizeof(*bp));
271 bp->signature = BUFFER_SIG;
272 bp->id = id;
273 pvr2_trace(PVR2_TRACE_BUF_POOL,
274 "/*---TRACE_FLOW---*/ bufferInit %p stream=%p",bp,sp);
275 bp->stream = sp;
276 bp->state = pvr2_buffer_state_none;
277 INIT_LIST_HEAD(&bp->list_overhead);
278 bp->purb = usb_alloc_urb(0,GFP_KERNEL);
279 if (! bp->purb) return -ENOMEM;
280#ifdef SANITY_CHECK_BUFFERS
281 pvr2_buffer_describe(bp,"create");
282#endif
283 return 0;
284}
285
286static void pvr2_buffer_done(struct pvr2_buffer *bp)
287{
288#ifdef SANITY_CHECK_BUFFERS
289 pvr2_buffer_describe(bp,"delete");
290#endif
291 pvr2_buffer_wipe(bp);
292 pvr2_buffer_set_none(bp);
293 bp->signature = 0;
294 bp->stream = NULL;
295 usb_free_urb(bp->purb);
296 pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
297 " bufferDone %p",bp);
298}
299
300static int pvr2_stream_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
301{
302 int ret;
303 unsigned int scnt;
304
305
306 if (cnt == sp->buffer_total_count) return 0;
307
308 pvr2_trace(PVR2_TRACE_BUF_POOL,
309 "/*---TRACE_FLOW---*/ poolResize "
310 " stream=%p cur=%d adj=%+d",
311 sp,
312 sp->buffer_total_count,
313 cnt-sp->buffer_total_count);
314
315 scnt = cnt & ~0x1f;
316 if (cnt > scnt) scnt += 0x20;
317
318 if (cnt > sp->buffer_total_count) {
319 if (scnt > sp->buffer_slot_count) {
320 struct pvr2_buffer **nb;
321 nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
322 if (!nb) return -ENOMEM;
323 if (sp->buffer_slot_count) {
324 memcpy(nb,sp->buffers,
325 sp->buffer_slot_count * sizeof(*nb));
326 kfree(sp->buffers);
327 }
328 sp->buffers = nb;
329 sp->buffer_slot_count = scnt;
330 }
331 while (sp->buffer_total_count < cnt) {
332 struct pvr2_buffer *bp;
333 bp = kmalloc(sizeof(*bp),GFP_KERNEL);
334 if (!bp) return -ENOMEM;
335 ret = pvr2_buffer_init(bp,sp,sp->buffer_total_count);
336 if (ret) {
337 kfree(bp);
338 return -ENOMEM;
339 }
340 sp->buffers[sp->buffer_total_count] = bp;
341 (sp->buffer_total_count)++;
342 pvr2_buffer_set_idle(bp);
343 }
344 } else {
345 while (sp->buffer_total_count > cnt) {
346 struct pvr2_buffer *bp;
347 bp = sp->buffers[sp->buffer_total_count - 1];
348
349 sp->buffers[sp->buffer_total_count - 1] = NULL;
350 (sp->buffer_total_count)--;
351 pvr2_buffer_done(bp);
352 kfree(bp);
353 }
354 if (scnt < sp->buffer_slot_count) {
355 struct pvr2_buffer **nb = NULL;
356 if (scnt) {
357 nb = kmalloc(scnt * sizeof(*nb),GFP_KERNEL);
358 if (!nb) return -ENOMEM;
359 memcpy(nb,sp->buffers,scnt * sizeof(*nb));
360 }
361 kfree(sp->buffers);
362 sp->buffers = nb;
363 sp->buffer_slot_count = scnt;
364 }
365 }
366 return 0;
367}
368
369static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp)
370{
371 struct pvr2_buffer *bp;
372 unsigned int cnt;
373
374 if (sp->buffer_total_count == sp->buffer_target_count) return 0;
375
376 pvr2_trace(PVR2_TRACE_BUF_POOL,
377 "/*---TRACE_FLOW---*/"
378 " poolCheck stream=%p cur=%d tgt=%d",
379 sp,sp->buffer_total_count,sp->buffer_target_count);
380
381 if (sp->buffer_total_count < sp->buffer_target_count) {
382 return pvr2_stream_buffer_count(sp,sp->buffer_target_count);
383 }
384
385 cnt = 0;
386 while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {
387 bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];
388 if (bp->state != pvr2_buffer_state_idle) break;
389 cnt++;
390 }
391 if (cnt) {
392 pvr2_stream_buffer_count(sp,sp->buffer_total_count - cnt);
393 }
394
395 return 0;
396}
397
398static void pvr2_stream_internal_flush(struct pvr2_stream *sp)
399{
400 struct list_head *lp;
401 struct pvr2_buffer *bp1;
402 while ((lp = sp->queued_list.next) != &sp->queued_list) {
403 bp1 = list_entry(lp,struct pvr2_buffer,list_overhead);
404 pvr2_buffer_wipe(bp1);
405
406
407
408
409
410 if (bp1->state != pvr2_buffer_state_queued) continue;
411 pvr2_buffer_set_idle(bp1);
412 }
413 if (sp->buffer_total_count != sp->buffer_target_count) {
414 pvr2_stream_achieve_buffer_count(sp);
415 }
416}
417
418static void pvr2_stream_init(struct pvr2_stream *sp)
419{
420 spin_lock_init(&sp->list_lock);
421 mutex_init(&sp->mutex);
422 INIT_LIST_HEAD(&sp->queued_list);
423 INIT_LIST_HEAD(&sp->ready_list);
424 INIT_LIST_HEAD(&sp->idle_list);
425}
426
427static void pvr2_stream_done(struct pvr2_stream *sp)
428{
429 mutex_lock(&sp->mutex); do {
430 pvr2_stream_internal_flush(sp);
431 pvr2_stream_buffer_count(sp,0);
432 } while (0); mutex_unlock(&sp->mutex);
433}
434
435static void buffer_complete(struct urb *urb)
436{
437 struct pvr2_buffer *bp = urb->context;
438 struct pvr2_stream *sp;
439 unsigned long irq_flags;
440 BUFFER_CHECK(bp);
441 sp = bp->stream;
442 bp->used_count = 0;
443 bp->status = 0;
444 pvr2_trace(PVR2_TRACE_BUF_FLOW,
445 "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",
446 bp,urb->status,urb->actual_length);
447 spin_lock_irqsave(&sp->list_lock,irq_flags);
448 if ((!(urb->status)) ||
449 (urb->status == -ENOENT) ||
450 (urb->status == -ECONNRESET) ||
451 (urb->status == -ESHUTDOWN)) {
452 (sp->buffers_processed)++;
453 sp->bytes_processed += urb->actual_length;
454 bp->used_count = urb->actual_length;
455 if (sp->fail_count) {
456 pvr2_trace(PVR2_TRACE_TOLERANCE,
457 "stream %p transfer ok"
458 " - fail count reset",sp);
459 sp->fail_count = 0;
460 }
461 } else if (sp->fail_count < sp->fail_tolerance) {
462
463
464 (sp->fail_count)++;
465 (sp->buffers_failed)++;
466 pvr2_trace(PVR2_TRACE_TOLERANCE,
467 "stream %p ignoring error %d"
468 " - fail count increased to %u",
469 sp,urb->status,sp->fail_count);
470 } else {
471 (sp->buffers_failed)++;
472 bp->status = urb->status;
473 }
474 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
475 pvr2_buffer_set_ready(bp);
476 if (sp && sp->callback_func) {
477 sp->callback_func(sp->callback_data);
478 }
479}
480
481struct pvr2_stream *pvr2_stream_create(void)
482{
483 struct pvr2_stream *sp;
484 sp = kzalloc(sizeof(*sp),GFP_KERNEL);
485 if (!sp) return sp;
486 pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_create: sp=%p",sp);
487 pvr2_stream_init(sp);
488 return sp;
489}
490
491void pvr2_stream_destroy(struct pvr2_stream *sp)
492{
493 if (!sp) return;
494 pvr2_trace(PVR2_TRACE_INIT,"pvr2_stream_destroy: sp=%p",sp);
495 pvr2_stream_done(sp);
496 kfree(sp);
497}
498
499void pvr2_stream_setup(struct pvr2_stream *sp,
500 struct usb_device *dev,
501 int endpoint,
502 unsigned int tolerance)
503{
504 mutex_lock(&sp->mutex); do {
505 pvr2_stream_internal_flush(sp);
506 sp->dev = dev;
507 sp->endpoint = endpoint;
508 sp->fail_tolerance = tolerance;
509 } while(0); mutex_unlock(&sp->mutex);
510}
511
512void pvr2_stream_set_callback(struct pvr2_stream *sp,
513 pvr2_stream_callback func,
514 void *data)
515{
516 unsigned long irq_flags;
517 mutex_lock(&sp->mutex); do {
518 spin_lock_irqsave(&sp->list_lock,irq_flags);
519 sp->callback_data = data;
520 sp->callback_func = func;
521 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
522 } while(0); mutex_unlock(&sp->mutex);
523}
524
525void pvr2_stream_get_stats(struct pvr2_stream *sp,
526 struct pvr2_stream_stats *stats,
527 int zero_counts)
528{
529 unsigned long irq_flags;
530 spin_lock_irqsave(&sp->list_lock,irq_flags);
531 if (stats) {
532 stats->buffers_in_queue = sp->q_count;
533 stats->buffers_in_idle = sp->i_count;
534 stats->buffers_in_ready = sp->r_count;
535 stats->buffers_processed = sp->buffers_processed;
536 stats->buffers_failed = sp->buffers_failed;
537 stats->bytes_processed = sp->bytes_processed;
538 }
539 if (zero_counts) {
540 sp->buffers_processed = 0;
541 sp->buffers_failed = 0;
542 sp->bytes_processed = 0;
543 }
544 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
545}
546
547
548int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
549{
550 return sp->buffer_target_count;
551}
552
553int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
554{
555 int ret;
556 if (sp->buffer_target_count == cnt) return 0;
557 mutex_lock(&sp->mutex); do {
558 sp->buffer_target_count = cnt;
559 ret = pvr2_stream_achieve_buffer_count(sp);
560 } while(0); mutex_unlock(&sp->mutex);
561 return ret;
562}
563
564struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
565{
566 struct list_head *lp = sp->idle_list.next;
567 if (lp == &sp->idle_list) return NULL;
568 return list_entry(lp,struct pvr2_buffer,list_overhead);
569}
570
571struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
572{
573 struct list_head *lp = sp->ready_list.next;
574 if (lp == &sp->ready_list) return NULL;
575 return list_entry(lp,struct pvr2_buffer,list_overhead);
576}
577
578struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
579{
580 if (id < 0) return NULL;
581 if (id >= sp->buffer_total_count) return NULL;
582 return sp->buffers[id];
583}
584
585int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
586{
587 return sp->r_count;
588}
589
590void pvr2_stream_kill(struct pvr2_stream *sp)
591{
592 struct pvr2_buffer *bp;
593 mutex_lock(&sp->mutex); do {
594 pvr2_stream_internal_flush(sp);
595 while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
596 pvr2_buffer_set_idle(bp);
597 }
598 if (sp->buffer_total_count != sp->buffer_target_count) {
599 pvr2_stream_achieve_buffer_count(sp);
600 }
601 } while(0); mutex_unlock(&sp->mutex);
602}
603
604int pvr2_buffer_queue(struct pvr2_buffer *bp)
605{
606#undef SEED_BUFFER
607#ifdef SEED_BUFFER
608 unsigned int idx;
609 unsigned int val;
610#endif
611 int ret = 0;
612 struct pvr2_stream *sp;
613 if (!bp) return -EINVAL;
614 sp = bp->stream;
615 mutex_lock(&sp->mutex); do {
616 pvr2_buffer_wipe(bp);
617 if (!sp->dev) {
618 ret = -EIO;
619 break;
620 }
621 pvr2_buffer_set_queued(bp);
622#ifdef SEED_BUFFER
623 for (idx = 0; idx < (bp->max_count) / 4; idx++) {
624 val = bp->id << 24;
625 val |= idx;
626 ((unsigned int *)(bp->ptr))[idx] = val;
627 }
628#endif
629 bp->status = -EINPROGRESS;
630 usb_fill_bulk_urb(bp->purb,
631 sp->dev,
632
633 usb_rcvbulkpipe(sp->dev,sp->endpoint),
634 bp->ptr,
635 bp->max_count,
636 buffer_complete,
637 bp);
638 usb_submit_urb(bp->purb,GFP_KERNEL);
639 } while(0); mutex_unlock(&sp->mutex);
640 return ret;
641}
642
643int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
644{
645 int ret = 0;
646 unsigned long irq_flags;
647 struct pvr2_stream *sp;
648 if (!bp) return -EINVAL;
649 sp = bp->stream;
650 mutex_lock(&sp->mutex); do {
651 spin_lock_irqsave(&sp->list_lock,irq_flags);
652 if (bp->state != pvr2_buffer_state_idle) {
653 ret = -EPERM;
654 } else {
655 bp->ptr = ptr;
656 bp->stream->i_bcount -= bp->max_count;
657 bp->max_count = cnt;
658 bp->stream->i_bcount += bp->max_count;
659 pvr2_trace(PVR2_TRACE_BUF_FLOW,
660 "/*---TRACE_FLOW---*/ bufferPool "
661 " %8s cap cap=%07d cnt=%02d",
662 pvr2_buffer_state_decode(
663 pvr2_buffer_state_idle),
664 bp->stream->i_bcount,bp->stream->i_count);
665 }
666 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
667 } while(0); mutex_unlock(&sp->mutex);
668 return ret;
669}
670
671unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
672{
673 return bp->used_count;
674}
675
676int pvr2_buffer_get_status(struct pvr2_buffer *bp)
677{
678 return bp->status;
679}
680
681int pvr2_buffer_get_id(struct pvr2_buffer *bp)
682{
683 return bp->id;
684}
685
686
687
688
689
690
691
692
693
694
695
696