[libata] ahci: add SiS PCI IDs
[pandora-kernel.git] / drivers / media / video / pvrusb2 / pvrusb2-io.c
1 /*
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
48 struct 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
83 struct 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
96 static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
97 {
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
107 #ifdef SANITY_CHECK_BUFFERS
108 static void pvr2_buffer_describe(struct pvr2_buffer *bp,const char *msg)
109 {
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 : NULL),
120                    (bp ? bp->purb : NULL),
121                    (bp ? bp->signature : 0));
122 }
123 #endif  /*  SANITY_CHECK_BUFFERS  */
124
125 static 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
160 static 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
176 static 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
204 static 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
229 static 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
254 static 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
261 static 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
281 static 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 = NULL;
290         if (bp->purb) usb_free_urb(bp->purb);
291         pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
292                    " bufferDone     %p",bp);
293 }
294
295 static 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] = NULL;
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 = NULL;
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
364 static 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
393 static 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
413 static 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
422 static 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
430 static 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
472 struct 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
483 void 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
491 void 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
504 void 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 */
518
519 int 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
530 struct 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 NULL;
534         return list_entry(lp,struct pvr2_buffer,list_overhead);
535 }
536
537 struct 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 NULL;
541         return list_entry(lp,struct pvr2_buffer,list_overhead);
542 }
543
544 struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp,int id)
545 {
546         if (id < 0) return NULL;
547         if (id >= sp->buffer_total_count) return NULL;
548         return sp->buffers[id];
549 }
550
551 int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
552 {
553         return sp->r_count;
554 }
555
556
557 void 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
571 int 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
610
611 int 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
639 unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
640 {
641         return bp->used_count;
642 }
643
644 int pvr2_buffer_get_status(struct pvr2_buffer *bp)
645 {
646         return bp->status;
647 }
648
649
650 int 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   */