0001
0002
0003
0004
0005
0006
0007 #include "pvrusb2-io.h"
0008 #include "pvrusb2-debug.h"
0009 #include <linux/errno.h>
0010 #include <linux/string.h>
0011 #include <linux/slab.h>
0012 #include <linux/mutex.h>
0013
0014 static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state);
0015
0016 #define BUFFER_SIG 0x47653271
0017
0018
0019
0020
0021 #ifdef SANITY_CHECK_BUFFERS
0022 #define BUFFER_CHECK(bp) do { \
0023 if ((bp)->signature != BUFFER_SIG) { \
0024 pvr2_trace(PVR2_TRACE_ERROR_LEGS, \
0025 "Buffer %p is bad at %s:%d", \
0026 (bp), __FILE__, __LINE__); \
0027 pvr2_buffer_describe(bp, "BadSig"); \
0028 BUG(); \
0029 } \
0030 } while (0)
0031 #else
0032 #define BUFFER_CHECK(bp) do {} while (0)
0033 #endif
0034
0035 struct pvr2_stream {
0036
0037 struct list_head queued_list;
0038 unsigned int q_count;
0039 unsigned int q_bcount;
0040
0041 struct list_head ready_list;
0042 unsigned int r_count;
0043 unsigned int r_bcount;
0044
0045 struct list_head idle_list;
0046 unsigned int i_count;
0047 unsigned int i_bcount;
0048
0049 struct pvr2_buffer **buffers;
0050
0051 unsigned int buffer_slot_count;
0052
0053 unsigned int buffer_total_count;
0054
0055 unsigned int buffer_target_count;
0056
0057 pvr2_stream_callback callback_func;
0058 void *callback_data;
0059
0060 struct usb_device *dev;
0061 int endpoint;
0062
0063 spinlock_t list_lock;
0064 struct mutex mutex;
0065
0066 unsigned int fail_count;
0067 unsigned int fail_tolerance;
0068
0069 unsigned int buffers_processed;
0070 unsigned int buffers_failed;
0071 unsigned int bytes_processed;
0072 };
0073
0074 struct pvr2_buffer {
0075 int id;
0076 int signature;
0077 enum pvr2_buffer_state state;
0078 void *ptr;
0079 unsigned int max_count;
0080 unsigned int used_count;
0081 int status;
0082 struct pvr2_stream *stream;
0083 struct list_head list_overhead;
0084 struct urb *purb;
0085 };
0086
0087 static const char *pvr2_buffer_state_decode(enum pvr2_buffer_state st)
0088 {
0089 switch (st) {
0090 case pvr2_buffer_state_none: return "none";
0091 case pvr2_buffer_state_idle: return "idle";
0092 case pvr2_buffer_state_queued: return "queued";
0093 case pvr2_buffer_state_ready: return "ready";
0094 }
0095 return "unknown";
0096 }
0097
0098 #ifdef SANITY_CHECK_BUFFERS
0099 static void pvr2_buffer_describe(struct pvr2_buffer *bp, const char *msg)
0100 {
0101 pvr2_trace(PVR2_TRACE_INFO,
0102 "buffer%s%s %p state=%s id=%d status=%d stream=%p purb=%p sig=0x%x",
0103 (msg ? " " : ""),
0104 (msg ? msg : ""),
0105 bp,
0106 (bp ? pvr2_buffer_state_decode(bp->state) : "(invalid)"),
0107 (bp ? bp->id : 0),
0108 (bp ? bp->status : 0),
0109 (bp ? bp->stream : NULL),
0110 (bp ? bp->purb : NULL),
0111 (bp ? bp->signature : 0));
0112 }
0113 #endif
0114
0115 static void pvr2_buffer_remove(struct pvr2_buffer *bp)
0116 {
0117 unsigned int *cnt;
0118 unsigned int *bcnt;
0119 unsigned int ccnt;
0120 struct pvr2_stream *sp = bp->stream;
0121 switch (bp->state) {
0122 case pvr2_buffer_state_idle:
0123 cnt = &sp->i_count;
0124 bcnt = &sp->i_bcount;
0125 ccnt = bp->max_count;
0126 break;
0127 case pvr2_buffer_state_queued:
0128 cnt = &sp->q_count;
0129 bcnt = &sp->q_bcount;
0130 ccnt = bp->max_count;
0131 break;
0132 case pvr2_buffer_state_ready:
0133 cnt = &sp->r_count;
0134 bcnt = &sp->r_bcount;
0135 ccnt = bp->used_count;
0136 break;
0137 default:
0138 return;
0139 }
0140 list_del_init(&bp->list_overhead);
0141 (*cnt)--;
0142 (*bcnt) -= ccnt;
0143 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0144 "/*---TRACE_FLOW---*/ bufferPool %8s dec cap=%07d cnt=%02d",
0145 pvr2_buffer_state_decode(bp->state), *bcnt, *cnt);
0146 bp->state = pvr2_buffer_state_none;
0147 }
0148
0149 static void pvr2_buffer_set_none(struct pvr2_buffer *bp)
0150 {
0151 unsigned long irq_flags;
0152 struct pvr2_stream *sp;
0153 BUFFER_CHECK(bp);
0154 sp = bp->stream;
0155 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0156 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
0157 bp,
0158 pvr2_buffer_state_decode(bp->state),
0159 pvr2_buffer_state_decode(pvr2_buffer_state_none));
0160 spin_lock_irqsave(&sp->list_lock, irq_flags);
0161 pvr2_buffer_remove(bp);
0162 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0163 }
0164
0165 static int pvr2_buffer_set_ready(struct pvr2_buffer *bp)
0166 {
0167 int fl;
0168 unsigned long irq_flags;
0169 struct pvr2_stream *sp;
0170 BUFFER_CHECK(bp);
0171 sp = bp->stream;
0172 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0173 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
0174 bp,
0175 pvr2_buffer_state_decode(bp->state),
0176 pvr2_buffer_state_decode(pvr2_buffer_state_ready));
0177 spin_lock_irqsave(&sp->list_lock, irq_flags);
0178 fl = (sp->r_count == 0);
0179 pvr2_buffer_remove(bp);
0180 list_add_tail(&bp->list_overhead, &sp->ready_list);
0181 bp->state = pvr2_buffer_state_ready;
0182 (sp->r_count)++;
0183 sp->r_bcount += bp->used_count;
0184 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0185 "/*---TRACE_FLOW---*/ bufferPool %8s inc cap=%07d cnt=%02d",
0186 pvr2_buffer_state_decode(bp->state),
0187 sp->r_bcount, sp->r_count);
0188 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0189 return fl;
0190 }
0191
0192 static void pvr2_buffer_set_idle(struct pvr2_buffer *bp)
0193 {
0194 unsigned long irq_flags;
0195 struct pvr2_stream *sp;
0196 BUFFER_CHECK(bp);
0197 sp = bp->stream;
0198 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0199 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
0200 bp,
0201 pvr2_buffer_state_decode(bp->state),
0202 pvr2_buffer_state_decode(pvr2_buffer_state_idle));
0203 spin_lock_irqsave(&sp->list_lock, irq_flags);
0204 pvr2_buffer_remove(bp);
0205 list_add_tail(&bp->list_overhead, &sp->idle_list);
0206 bp->state = pvr2_buffer_state_idle;
0207 (sp->i_count)++;
0208 sp->i_bcount += bp->max_count;
0209 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0210 "/*---TRACE_FLOW---*/ bufferPool %8s inc cap=%07d cnt=%02d",
0211 pvr2_buffer_state_decode(bp->state),
0212 sp->i_bcount, sp->i_count);
0213 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0214 }
0215
0216 static void pvr2_buffer_set_queued(struct pvr2_buffer *bp)
0217 {
0218 unsigned long irq_flags;
0219 struct pvr2_stream *sp;
0220 BUFFER_CHECK(bp);
0221 sp = bp->stream;
0222 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0223 "/*---TRACE_FLOW---*/ bufferState %p %6s --> %6s",
0224 bp,
0225 pvr2_buffer_state_decode(bp->state),
0226 pvr2_buffer_state_decode(pvr2_buffer_state_queued));
0227 spin_lock_irqsave(&sp->list_lock, irq_flags);
0228 pvr2_buffer_remove(bp);
0229 list_add_tail(&bp->list_overhead, &sp->queued_list);
0230 bp->state = pvr2_buffer_state_queued;
0231 (sp->q_count)++;
0232 sp->q_bcount += bp->max_count;
0233 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0234 "/*---TRACE_FLOW---*/ bufferPool %8s inc cap=%07d cnt=%02d",
0235 pvr2_buffer_state_decode(bp->state),
0236 sp->q_bcount, sp->q_count);
0237 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0238 }
0239
0240 static void pvr2_buffer_wipe(struct pvr2_buffer *bp)
0241 {
0242 if (bp->state == pvr2_buffer_state_queued) {
0243 usb_kill_urb(bp->purb);
0244 }
0245 }
0246
0247 static int pvr2_buffer_init(struct pvr2_buffer *bp,
0248 struct pvr2_stream *sp,
0249 unsigned int id)
0250 {
0251 memset(bp, 0, sizeof(*bp));
0252 bp->signature = BUFFER_SIG;
0253 bp->id = id;
0254 pvr2_trace(PVR2_TRACE_BUF_POOL,
0255 "/*---TRACE_FLOW---*/ bufferInit %p stream=%p", bp, sp);
0256 bp->stream = sp;
0257 bp->state = pvr2_buffer_state_none;
0258 INIT_LIST_HEAD(&bp->list_overhead);
0259 bp->purb = usb_alloc_urb(0, GFP_KERNEL);
0260 if (! bp->purb) return -ENOMEM;
0261 #ifdef SANITY_CHECK_BUFFERS
0262 pvr2_buffer_describe(bp, "create");
0263 #endif
0264 return 0;
0265 }
0266
0267 static void pvr2_buffer_done(struct pvr2_buffer *bp)
0268 {
0269 #ifdef SANITY_CHECK_BUFFERS
0270 pvr2_buffer_describe(bp, "delete");
0271 #endif
0272 pvr2_buffer_wipe(bp);
0273 pvr2_buffer_set_none(bp);
0274 bp->signature = 0;
0275 bp->stream = NULL;
0276 usb_free_urb(bp->purb);
0277 pvr2_trace(PVR2_TRACE_BUF_POOL, "/*---TRACE_FLOW---*/ bufferDone %p",
0278 bp);
0279 }
0280
0281 static int pvr2_stream_buffer_count(struct pvr2_stream *sp, unsigned int cnt)
0282 {
0283 int ret;
0284 unsigned int scnt;
0285
0286
0287 if (cnt == sp->buffer_total_count) return 0;
0288
0289 pvr2_trace(PVR2_TRACE_BUF_POOL,
0290 "/*---TRACE_FLOW---*/ poolResize stream=%p cur=%d adj=%+d",
0291 sp,
0292 sp->buffer_total_count,
0293 cnt-sp->buffer_total_count);
0294
0295 scnt = cnt & ~0x1f;
0296 if (cnt > scnt) scnt += 0x20;
0297
0298 if (cnt > sp->buffer_total_count) {
0299 if (scnt > sp->buffer_slot_count) {
0300 struct pvr2_buffer **nb;
0301
0302 nb = kmalloc_array(scnt, sizeof(*nb), GFP_KERNEL);
0303 if (!nb) return -ENOMEM;
0304 if (sp->buffer_slot_count) {
0305 memcpy(nb, sp->buffers,
0306 sp->buffer_slot_count * sizeof(*nb));
0307 kfree(sp->buffers);
0308 }
0309 sp->buffers = nb;
0310 sp->buffer_slot_count = scnt;
0311 }
0312 while (sp->buffer_total_count < cnt) {
0313 struct pvr2_buffer *bp;
0314 bp = kmalloc(sizeof(*bp), GFP_KERNEL);
0315 if (!bp) return -ENOMEM;
0316 ret = pvr2_buffer_init(bp, sp, sp->buffer_total_count);
0317 if (ret) {
0318 kfree(bp);
0319 return -ENOMEM;
0320 }
0321 sp->buffers[sp->buffer_total_count] = bp;
0322 (sp->buffer_total_count)++;
0323 pvr2_buffer_set_idle(bp);
0324 }
0325 } else {
0326 while (sp->buffer_total_count > cnt) {
0327 struct pvr2_buffer *bp;
0328 bp = sp->buffers[sp->buffer_total_count - 1];
0329
0330 sp->buffers[sp->buffer_total_count - 1] = NULL;
0331 (sp->buffer_total_count)--;
0332 pvr2_buffer_done(bp);
0333 kfree(bp);
0334 }
0335 if (scnt < sp->buffer_slot_count) {
0336 struct pvr2_buffer **nb = NULL;
0337 if (scnt) {
0338 nb = kmemdup(sp->buffers, scnt * sizeof(*nb),
0339 GFP_KERNEL);
0340 if (!nb) return -ENOMEM;
0341 }
0342 kfree(sp->buffers);
0343 sp->buffers = nb;
0344 sp->buffer_slot_count = scnt;
0345 }
0346 }
0347 return 0;
0348 }
0349
0350 static int pvr2_stream_achieve_buffer_count(struct pvr2_stream *sp)
0351 {
0352 struct pvr2_buffer *bp;
0353 unsigned int cnt;
0354
0355 if (sp->buffer_total_count == sp->buffer_target_count) return 0;
0356
0357 pvr2_trace(PVR2_TRACE_BUF_POOL,
0358 "/*---TRACE_FLOW---*/ poolCheck stream=%p cur=%d tgt=%d",
0359 sp, sp->buffer_total_count, sp->buffer_target_count);
0360
0361 if (sp->buffer_total_count < sp->buffer_target_count) {
0362 return pvr2_stream_buffer_count(sp, sp->buffer_target_count);
0363 }
0364
0365 cnt = 0;
0366 while ((sp->buffer_total_count - cnt) > sp->buffer_target_count) {
0367 bp = sp->buffers[sp->buffer_total_count - (cnt + 1)];
0368 if (bp->state != pvr2_buffer_state_idle) break;
0369 cnt++;
0370 }
0371 if (cnt) {
0372 pvr2_stream_buffer_count(sp, sp->buffer_total_count - cnt);
0373 }
0374
0375 return 0;
0376 }
0377
0378 static void pvr2_stream_internal_flush(struct pvr2_stream *sp)
0379 {
0380 struct list_head *lp;
0381 struct pvr2_buffer *bp1;
0382 while ((lp = sp->queued_list.next) != &sp->queued_list) {
0383 bp1 = list_entry(lp, struct pvr2_buffer, list_overhead);
0384 pvr2_buffer_wipe(bp1);
0385
0386
0387
0388
0389
0390 if (bp1->state != pvr2_buffer_state_queued) continue;
0391 pvr2_buffer_set_idle(bp1);
0392 }
0393 if (sp->buffer_total_count != sp->buffer_target_count) {
0394 pvr2_stream_achieve_buffer_count(sp);
0395 }
0396 }
0397
0398 static void pvr2_stream_init(struct pvr2_stream *sp)
0399 {
0400 spin_lock_init(&sp->list_lock);
0401 mutex_init(&sp->mutex);
0402 INIT_LIST_HEAD(&sp->queued_list);
0403 INIT_LIST_HEAD(&sp->ready_list);
0404 INIT_LIST_HEAD(&sp->idle_list);
0405 }
0406
0407 static void pvr2_stream_done(struct pvr2_stream *sp)
0408 {
0409 mutex_lock(&sp->mutex); do {
0410 pvr2_stream_internal_flush(sp);
0411 pvr2_stream_buffer_count(sp, 0);
0412 } while (0); mutex_unlock(&sp->mutex);
0413 }
0414
0415 static void buffer_complete(struct urb *urb)
0416 {
0417 struct pvr2_buffer *bp = urb->context;
0418 struct pvr2_stream *sp;
0419 unsigned long irq_flags;
0420 BUFFER_CHECK(bp);
0421 sp = bp->stream;
0422 bp->used_count = 0;
0423 bp->status = 0;
0424 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0425 "/*---TRACE_FLOW---*/ bufferComplete %p stat=%d cnt=%d",
0426 bp, urb->status, urb->actual_length);
0427 spin_lock_irqsave(&sp->list_lock, irq_flags);
0428 if ((!(urb->status)) ||
0429 (urb->status == -ENOENT) ||
0430 (urb->status == -ECONNRESET) ||
0431 (urb->status == -ESHUTDOWN)) {
0432 (sp->buffers_processed)++;
0433 sp->bytes_processed += urb->actual_length;
0434 bp->used_count = urb->actual_length;
0435 if (sp->fail_count) {
0436 pvr2_trace(PVR2_TRACE_TOLERANCE,
0437 "stream %p transfer ok - fail count reset",
0438 sp);
0439 sp->fail_count = 0;
0440 }
0441 } else if (sp->fail_count < sp->fail_tolerance) {
0442
0443
0444 (sp->fail_count)++;
0445 (sp->buffers_failed)++;
0446 pvr2_trace(PVR2_TRACE_TOLERANCE,
0447 "stream %p ignoring error %d - fail count increased to %u",
0448 sp, urb->status, sp->fail_count);
0449 } else {
0450 (sp->buffers_failed)++;
0451 bp->status = urb->status;
0452 }
0453 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0454 pvr2_buffer_set_ready(bp);
0455 if (sp->callback_func) {
0456 sp->callback_func(sp->callback_data);
0457 }
0458 }
0459
0460 struct pvr2_stream *pvr2_stream_create(void)
0461 {
0462 struct pvr2_stream *sp;
0463 sp = kzalloc(sizeof(*sp), GFP_KERNEL);
0464 if (!sp) return sp;
0465 pvr2_trace(PVR2_TRACE_INIT, "pvr2_stream_create: sp=%p", sp);
0466 pvr2_stream_init(sp);
0467 return sp;
0468 }
0469
0470 void pvr2_stream_destroy(struct pvr2_stream *sp)
0471 {
0472 if (!sp) return;
0473 pvr2_trace(PVR2_TRACE_INIT, "pvr2_stream_destroy: sp=%p", sp);
0474 pvr2_stream_done(sp);
0475 kfree(sp);
0476 }
0477
0478 void pvr2_stream_setup(struct pvr2_stream *sp,
0479 struct usb_device *dev,
0480 int endpoint,
0481 unsigned int tolerance)
0482 {
0483 mutex_lock(&sp->mutex); do {
0484 pvr2_stream_internal_flush(sp);
0485 sp->dev = dev;
0486 sp->endpoint = endpoint;
0487 sp->fail_tolerance = tolerance;
0488 } while (0); mutex_unlock(&sp->mutex);
0489 }
0490
0491 void pvr2_stream_set_callback(struct pvr2_stream *sp,
0492 pvr2_stream_callback func,
0493 void *data)
0494 {
0495 unsigned long irq_flags;
0496 mutex_lock(&sp->mutex);
0497 do {
0498 spin_lock_irqsave(&sp->list_lock, irq_flags);
0499 sp->callback_data = data;
0500 sp->callback_func = func;
0501 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0502 } while (0);
0503 mutex_unlock(&sp->mutex);
0504 }
0505
0506 void pvr2_stream_get_stats(struct pvr2_stream *sp,
0507 struct pvr2_stream_stats *stats,
0508 int zero_counts)
0509 {
0510 unsigned long irq_flags;
0511 spin_lock_irqsave(&sp->list_lock, irq_flags);
0512 if (stats) {
0513 stats->buffers_in_queue = sp->q_count;
0514 stats->buffers_in_idle = sp->i_count;
0515 stats->buffers_in_ready = sp->r_count;
0516 stats->buffers_processed = sp->buffers_processed;
0517 stats->buffers_failed = sp->buffers_failed;
0518 stats->bytes_processed = sp->bytes_processed;
0519 }
0520 if (zero_counts) {
0521 sp->buffers_processed = 0;
0522 sp->buffers_failed = 0;
0523 sp->bytes_processed = 0;
0524 }
0525 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0526 }
0527
0528
0529 int pvr2_stream_get_buffer_count(struct pvr2_stream *sp)
0530 {
0531 return sp->buffer_target_count;
0532 }
0533
0534 int pvr2_stream_set_buffer_count(struct pvr2_stream *sp, unsigned int cnt)
0535 {
0536 int ret;
0537 if (sp->buffer_target_count == cnt) return 0;
0538 mutex_lock(&sp->mutex);
0539 do {
0540 sp->buffer_target_count = cnt;
0541 ret = pvr2_stream_achieve_buffer_count(sp);
0542 } while (0);
0543 mutex_unlock(&sp->mutex);
0544 return ret;
0545 }
0546
0547 struct pvr2_buffer *pvr2_stream_get_idle_buffer(struct pvr2_stream *sp)
0548 {
0549 struct list_head *lp = sp->idle_list.next;
0550 if (lp == &sp->idle_list) return NULL;
0551 return list_entry(lp, struct pvr2_buffer, list_overhead);
0552 }
0553
0554 struct pvr2_buffer *pvr2_stream_get_ready_buffer(struct pvr2_stream *sp)
0555 {
0556 struct list_head *lp = sp->ready_list.next;
0557 if (lp == &sp->ready_list) return NULL;
0558 return list_entry(lp, struct pvr2_buffer, list_overhead);
0559 }
0560
0561 struct pvr2_buffer *pvr2_stream_get_buffer(struct pvr2_stream *sp, int id)
0562 {
0563 if (id < 0) return NULL;
0564 if (id >= sp->buffer_total_count) return NULL;
0565 return sp->buffers[id];
0566 }
0567
0568 int pvr2_stream_get_ready_count(struct pvr2_stream *sp)
0569 {
0570 return sp->r_count;
0571 }
0572
0573 void pvr2_stream_kill(struct pvr2_stream *sp)
0574 {
0575 struct pvr2_buffer *bp;
0576 mutex_lock(&sp->mutex);
0577 do {
0578 pvr2_stream_internal_flush(sp);
0579 while ((bp = pvr2_stream_get_ready_buffer(sp)) != NULL) {
0580 pvr2_buffer_set_idle(bp);
0581 }
0582 if (sp->buffer_total_count != sp->buffer_target_count) {
0583 pvr2_stream_achieve_buffer_count(sp);
0584 }
0585 } while (0);
0586 mutex_unlock(&sp->mutex);
0587 }
0588
0589 int pvr2_buffer_queue(struct pvr2_buffer *bp)
0590 {
0591 #undef SEED_BUFFER
0592 #ifdef SEED_BUFFER
0593 unsigned int idx;
0594 unsigned int val;
0595 #endif
0596 int ret = 0;
0597 struct pvr2_stream *sp;
0598 if (!bp) return -EINVAL;
0599 sp = bp->stream;
0600 mutex_lock(&sp->mutex);
0601 do {
0602 pvr2_buffer_wipe(bp);
0603 if (!sp->dev) {
0604 ret = -EIO;
0605 break;
0606 }
0607 pvr2_buffer_set_queued(bp);
0608 #ifdef SEED_BUFFER
0609 for (idx = 0; idx < (bp->max_count) / 4; idx++) {
0610 val = bp->id << 24;
0611 val |= idx;
0612 ((unsigned int *)(bp->ptr))[idx] = val;
0613 }
0614 #endif
0615 bp->status = -EINPROGRESS;
0616 usb_fill_bulk_urb(bp->purb,
0617 sp->dev,
0618
0619 usb_rcvbulkpipe(sp->dev, sp->endpoint),
0620 bp->ptr,
0621 bp->max_count,
0622 buffer_complete,
0623 bp);
0624 usb_submit_urb(bp->purb, GFP_KERNEL);
0625 } while (0);
0626 mutex_unlock(&sp->mutex);
0627 return ret;
0628 }
0629
0630 int pvr2_buffer_set_buffer(struct pvr2_buffer *bp, void *ptr, unsigned int cnt)
0631 {
0632 int ret = 0;
0633 unsigned long irq_flags;
0634 struct pvr2_stream *sp;
0635 if (!bp) return -EINVAL;
0636 sp = bp->stream;
0637 mutex_lock(&sp->mutex);
0638 do {
0639 spin_lock_irqsave(&sp->list_lock, irq_flags);
0640 if (bp->state != pvr2_buffer_state_idle) {
0641 ret = -EPERM;
0642 } else {
0643 bp->ptr = ptr;
0644 bp->stream->i_bcount -= bp->max_count;
0645 bp->max_count = cnt;
0646 bp->stream->i_bcount += bp->max_count;
0647 pvr2_trace(PVR2_TRACE_BUF_FLOW,
0648 "/*---TRACE_FLOW---*/ bufferPool %8s cap cap=%07d cnt=%02d",
0649 pvr2_buffer_state_decode(
0650 pvr2_buffer_state_idle),
0651 bp->stream->i_bcount, bp->stream->i_count);
0652 }
0653 spin_unlock_irqrestore(&sp->list_lock, irq_flags);
0654 } while (0);
0655 mutex_unlock(&sp->mutex);
0656 return ret;
0657 }
0658
0659 unsigned int pvr2_buffer_get_count(struct pvr2_buffer *bp)
0660 {
0661 return bp->used_count;
0662 }
0663
0664 int pvr2_buffer_get_status(struct pvr2_buffer *bp)
0665 {
0666 return bp->status;
0667 }
0668
0669 int pvr2_buffer_get_id(struct pvr2_buffer *bp)
0670 {
0671 return bp->id;
0672 }