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