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