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 = kmemdup(sp->buffers, scnt * sizeof(*nb),
358 GFP_KERNEL);
359 if (!nb) return -ENOMEM;
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->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);
518 do {
519 spin_lock_irqsave(&sp->list_lock,irq_flags);
520 sp->callback_data = data;
521 sp->callback_func = func;
522 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
523 } while(0);
524 mutex_unlock(&sp->mutex);
525}
526
527void pvr2_stream_get_stats(struct pvr2_stream *sp,
528 struct pvr2_stream_stats *stats,
529 int zero_counts)
530{
531 unsigned long irq_flags;
532 spin_lock_irqsave(&sp->list_lock,irq_flags);
533 if (stats) {
534 stats->buffers_in_queue = sp->q_count;
535 stats->buffers_in_idle = sp->i_count;
536 stats->buffers_in_ready = sp->r_count;
537 stats->buffers_processed = sp->buffers_processed;
538 stats->buffers_failed = sp->buffers_failed;
539 stats->bytes_processed = sp->bytes_processed;
540 }
541 if (zero_counts) {
542 sp->buffers_processed = 0;
543 sp->buffers_failed = 0;
544 sp->bytes_processed = 0;
545 }
546 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
547}
548
549
550int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
551{
552 return sp->buffer_target_count;
553}
554
555int pvr2_stream_set_buffer_count(struct pvr2_stream *sp,unsigned int cnt)
556{
557 int ret;
558 if (sp->buffer_target_count == cnt) return 0;
559 mutex_lock(&sp->mutex);
560 do {
561 sp->buffer_target_count = cnt;
562 ret = pvr2_stream_achieve_buffer_count(sp);
563 } while(0);
564 mutex_unlock(&sp->mutex);
565 return ret;
566}
567
568struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
569{
570 struct list_head *lp = sp->idle_list.next;
571 if (lp == &sp->idle_list) return NULL;
572 return list_entry(lp,struct pvr2_buffer,list_overhead);
573}
574
575struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
576{
577 struct list_head *lp = sp->ready_list.next;
578 if (lp == &sp->ready_list) return NULL;
579 return list_entry(lp,struct pvr2_buffer,list_overhead);
580}
581
582struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
583{
584 if (id < 0) return NULL;
585 if (id >= sp->buffer_total_count) return NULL;
586 return sp->buffers[id];
587}
588
589int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
590{
591 return sp->r_count;
592}
593
594void pvr2_stream_kill(struct pvr2_stream *sp)
595{
596 struct pvr2_buffer *bp;
597 mutex_lock(&sp->mutex);
598 do {
599 pvr2_stream_internal_flush(sp);
600 while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
601 pvr2_buffer_set_idle(bp);
602 }
603 if (sp->buffer_total_count != sp->buffer_target_count) {
604 pvr2_stream_achieve_buffer_count(sp);
605 }
606 } while(0);
607 mutex_unlock(&sp->mutex);
608}
609
610int pvr2_buffer_queue(struct pvr2_buffer *bp)
611{
612#undef SEED_BUFFER
613#ifdef SEED_BUFFER
614 unsigned int idx;
615 unsigned int val;
616#endif
617 int ret = 0;
618 struct pvr2_stream *sp;
619 if (!bp) return -EINVAL;
620 sp = bp->stream;
621 mutex_lock(&sp->mutex);
622 do {
623 pvr2_buffer_wipe(bp);
624 if (!sp->dev) {
625 ret = -EIO;
626 break;
627 }
628 pvr2_buffer_set_queued(bp);
629#ifdef SEED_BUFFER
630 for (idx = 0; idx < (bp->max_count) / 4; idx++) {
631 val = bp->id << 24;
632 val |= idx;
633 ((unsigned int *)(bp->ptr))[idx] = val;
634 }
635#endif
636 bp->status = -EINPROGRESS;
637 usb_fill_bulk_urb(bp->purb,
638 sp->dev,
639
640 usb_rcvbulkpipe(sp->dev,sp->endpoint),
641 bp->ptr,
642 bp->max_count,
643 buffer_complete,
644 bp);
645 usb_submit_urb(bp->purb,GFP_KERNEL);
646 } while(0);
647 mutex_unlock(&sp->mutex);
648 return ret;
649}
650
651int pvr2_buffer_set_buffer(struct pvr2_buffer *bp,void *ptr,unsigned int cnt)
652{
653 int ret = 0;
654 unsigned long irq_flags;
655 struct pvr2_stream *sp;
656 if (!bp) return -EINVAL;
657 sp = bp->stream;
658 mutex_lock(&sp->mutex);
659 do {
660 spin_lock_irqsave(&sp->list_lock,irq_flags);
661 if (bp->state != pvr2_buffer_state_idle) {
662 ret = -EPERM;
663 } else {
664 bp->ptr = ptr;
665 bp->stream->i_bcount -= bp->max_count;
666 bp->max_count = cnt;
667 bp->stream->i_bcount += bp->max_count;
668 pvr2_trace(PVR2_TRACE_BUF_FLOW,
669 "/*---TRACE_FLOW---*/ bufferPool "
670 " %8s cap cap=%07d cnt=%02d",
671 pvr2_buffer_state_decode(
672 pvr2_buffer_state_idle),
673 bp->stream->i_bcount,bp->stream->i_count);
674 }
675 spin_unlock_irqrestore(&sp->list_lock,irq_flags);
676 } while(0);
677 mutex_unlock(&sp->mutex);
678 return ret;
679}
680
681unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
682{
683 return bp->used_count;
684}
685
686int pvr2_buffer_get_status(struct pvr2_buffer *bp)
687{
688 return bp->status;
689}
690
691int pvr2_buffer_get_id(struct pvr2_buffer *bp)
692{
693 return bp->id;
694}
695