Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  *  Copyright (C) 2005 Mike Isely <isely@pobox.com>
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 // #define SANITY_CHECK_BUFFERS
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     /* Buffers queued for reading */
0037     struct list_head queued_list;
0038     unsigned int q_count;
0039     unsigned int q_bcount;
0040     /* Buffers with retrieved data */
0041     struct list_head ready_list;
0042     unsigned int r_count;
0043     unsigned int r_bcount;
0044     /* Buffers available for use */
0045     struct list_head idle_list;
0046     unsigned int i_count;
0047     unsigned int i_bcount;
0048     /* Pointers to all buffers */
0049     struct pvr2_buffer **buffers;
0050     /* Array size of buffers */
0051     unsigned int buffer_slot_count;
0052     /* Total buffers actually in circulation */
0053     unsigned int buffer_total_count;
0054     /* Designed number of buffers to be in circulation */
0055     unsigned int buffer_target_count;
0056     /* Executed when ready list become non-empty */
0057     pvr2_stream_callback callback_func;
0058     void *callback_data;
0059     /* Context for transfer endpoint */
0060     struct usb_device *dev;
0061     int endpoint;
0062     /* Overhead for mutex enforcement */
0063     spinlock_t list_lock;
0064     struct mutex mutex;
0065     /* Tracking state for tolerating errors */
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;               /* Pointer to storage area */
0079     unsigned int max_count;  /* Size of storage area */
0080     unsigned int used_count; /* Amount of valid data in storage area */
0081     int status;              /* Transfer result 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  /*  SANITY_CHECK_BUFFERS  */
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     /* Allocate buffers pointer array in multiples of 32 entries */
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             /* Paranoia */
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         /* At this point, we should be guaranteed that no
0386            completion callback may happen on this buffer.  But it's
0387            possible that it might have completed after we noticed
0388            it but before we wiped it.  So double check its status
0389            here first. */
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         // We can tolerate this error, because we're below the
0443         // threshold...
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 /* Query / set the nominal buffer count */
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,      // struct urb *urb
0617                   sp->dev,       // struct usb_device *dev
0618                   // endpoint (below)
0619                   usb_rcvbulkpipe(sp->dev, sp->endpoint),
0620                   bp->ptr,       // void *transfer_buffer
0621                   bp->max_count, // int buffer_length
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 }