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