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

source code of linux/drivers/media/usb/pvrusb2/pvrusb2-io.c