Am Donnerstag, 3. Mai 2007 09:05 schrieb Greg KH: > So, can everyone check their patch queues with what I have applied from > you already, and resend anything that I've missed (and I'm pretty sure > I've missed something from all of you...)
This patch fixes a problem reported with consecutive reads in the ldusb driver. Regards Oliver Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]> --- --- a/drivers/usb/misc/ldusb.c 2007-04-18 09:21:23.000000000 +0200 +++ b/drivers/usb/misc/ldusb.c 2007-04-18 09:23:02.000000000 +0200 @@ -162,6 +162,8 @@ struct ld_usb { size_t interrupt_in_endpoint_size; int interrupt_in_running; int interrupt_in_done; + int buffer_overflow; + spinlock_t rbsl; char* interrupt_out_buffer; struct usb_endpoint_descriptor* interrupt_out_endpoint; @@ -227,10 +229,12 @@ static void ld_usb_interrupt_in_callback } else { dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n", __FUNCTION__, urb->status); + spin_lock(&dev->rbsl); goto resubmit; /* maybe we can recover */ } } + spin_lock(&dev->rbsl); if (urb->actual_length > 0) { next_ring_head = (dev->ring_head+1) % ring_buffer_size; if (next_ring_head != dev->ring_tail) { @@ -241,21 +245,25 @@ static void ld_usb_interrupt_in_callback dev->ring_head = next_ring_head; dbg_info(&dev->intf->dev, "%s: received %d bytes\n", __FUNCTION__, urb->actual_length); - } else + } else { dev_warn(&dev->intf->dev, "Ring buffer overflow, %d bytes dropped\n", urb->actual_length); + dev->buffer_overflow = 1; + } } resubmit: /* resubmit if we're still running */ - if (dev->interrupt_in_running && dev->intf) { + if (dev->interrupt_in_running && !dev->buffer_overflow && dev->intf) { retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC); - if (retval) + if (retval) { dev_err(&dev->intf->dev, "usb_submit_urb failed (%d)\n", retval); + dev->buffer_overflow = 1; + } } - + spin_unlock(&dev->rbsl); exit: dev->interrupt_in_done = 1; wake_up_interruptible(&dev->read_wait); @@ -327,6 +335,7 @@ static int ld_usb_open(struct inode *ino /* initialize in direction */ dev->ring_head = 0; dev->ring_tail = 0; + dev->buffer_overflow = 0; usb_fill_int_urb(dev->interrupt_in_urb, interface_to_usbdev(interface), usb_rcvintpipe(interface_to_usbdev(interface), @@ -436,6 +445,7 @@ static ssize_t ld_usb_read(struct file * size_t *actual_buffer; size_t bytes_to_read; int retval = 0; + int rv; dev = file->private_data; @@ -457,7 +467,10 @@ static ssize_t ld_usb_read(struct file * } /* wait for data */ + spin_lock_irq(&dev->rbsl); if (dev->ring_head == dev->ring_tail) { + dev->interrupt_in_done = 0; + spin_unlock_irq(&dev->rbsl); if (file->f_flags & O_NONBLOCK) { retval = -EAGAIN; goto unlock_exit; @@ -465,6 +478,8 @@ static ssize_t ld_usb_read(struct file * retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done); if (retval < 0) goto unlock_exit; + } else { + spin_unlock_irq(&dev->rbsl); } /* actual_buffer contains actual_length + interrupt_in_buffer */ @@ -483,6 +498,17 @@ static ssize_t ld_usb_read(struct file * retval = bytes_to_read; + spin_lock_irq(&dev->rbsl); + if (dev->buffer_overflow) { + dev->buffer_overflow = 0; + spin_unlock_irq(&dev->rbsl); + rv = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL); + if (rv < 0) + dev->buffer_overflow = 1; + } else { + spin_unlock_irq(&dev->rbsl); + } + unlock_exit: /* unlock the device */ up(&dev->sem); @@ -632,6 +658,7 @@ static int ld_usb_probe(struct usb_inter goto exit; } init_MUTEX(&dev->sem); + spin_lock_init(&dev->rbsl); dev->intf = intf; init_waitqueue_head(&dev->read_wait); init_waitqueue_head(&dev->write_wait); ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel