- urb->actual_length = 0;
- urb->dev = acm->dev;
-
- i = usb_submit_urb(urb, GFP_ATOMIC);
- if (i)
- dev_dbg(&acm->data->dev, "bulk rx resubmit %d\n", i);
+ spin_lock(&acm->read_lock);
+ list_add(&buf->list, &acm->spare_read_bufs);
+ spin_unlock(&acm->read_lock);
+ goto next_buffer;
+
+urbs:
+ while (!list_empty(&acm->spare_read_bufs)) {
+ spin_lock(&acm->read_lock);
+ if (list_empty(&acm->spare_read_urbs)) {
+ spin_unlock(&acm->read_lock);
+ return;
+ }
+ rcv = list_entry(acm->spare_read_urbs.next,
+ struct acm_ru, list);
+ list_del(&rcv->list);
+ spin_unlock(&acm->read_lock);
+
+ buf = list_entry(acm->spare_read_bufs.next,
+ struct acm_rb, list);
+ list_del(&buf->list);
+
+ rcv->buffer = buf;
+
+ usb_fill_bulk_urb(rcv->urb, acm->dev,
+ acm->rx_endpoint,
+ buf->base,
+ acm->readsize,
+ acm_read_bulk, rcv);
+ rcv->urb->transfer_dma = buf->dma;
+ rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ dbg("acm_rx_tasklet: sending urb 0x%p, rcv 0x%p, buf 0x%p\n", rcv->urb, rcv, buf);
+
+ /* This shouldn't kill the driver as unsuccessful URBs are returned to the
+ free-urbs-pool and resubmited ASAP */
+ if (usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) {
+ list_add(&buf->list, &acm->spare_read_bufs);
+ spin_lock(&acm->read_lock);
+ list_add(&rcv->list, &acm->spare_read_urbs);
+ spin_unlock(&acm->read_lock);
+ return;
+ }
+ }