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