--- usb-skeleton.c.alt Sun Jan 13 12:35:11 2002 +++ usb-skeleton.c Sun Jan 13 18:48:08 2002 @@ -112,6 +112,7 @@ struct tq_struct tqueue; /* task queue for line discipline waking up */ int open_count; /* number of times this port has been opened */ struct semaphore sem; /* locks this structure */ + int writing; /* write in progress */ }; @@ -253,7 +254,7 @@ /* lock our minor table and get our local data for this minor */ down (&minor_table_mutex); dev = minor_table[subminor]; - if (dev == NULL) { + if (unlikely(dev == NULL)) { up (&minor_table_mutex); MOD_DEC_USE_COUNT; return -ENODEV; @@ -266,7 +267,10 @@ up (&minor_table_mutex); /* increment our usage count for the driver */ + /* make sure there's only one increment. release is called once */ ++dev->open_count; + if (dev->open_count > 1) + MOD_DEC_USE_COUNT; /* save our object in the file's private structure */ file->private_data = dev; @@ -287,7 +291,7 @@ int retval = 0; dev = (struct usb_skel *)file->private_data; - if (dev == NULL) { + if (unlikely(dev == NULL)) { dbg (__FUNCTION__ " - object is NULL"); return -ENODEV; } @@ -300,7 +304,7 @@ /* lock our device */ down (&dev->sem); - if (dev->open_count <= 0) { + if (unlikely(dev->open_count <= 0)) { dbg (__FUNCTION__ " - device not opened"); retval = -ENODEV; goto exit_not_opened; @@ -350,7 +354,7 @@ down (&dev->sem); /* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (unlikely(dev->udev == NULL)) { up (&dev->sem); return -ENODEV; } @@ -363,8 +367,8 @@ &count, HZ*10); /* if the read was successful, copy the data to userspace */ - if (!retval) { - if (copy_to_user (buffer, dev->bulk_in_buffer, count)) + if (likely(!retval)) { + if (unlikely(copy_to_user (buffer, dev->bulk_in_buffer, count))) retval = -EFAULT; else retval = count; @@ -393,30 +397,33 @@ down (&dev->sem); /* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (unlikely(dev->udev == NULL)) { retval = -ENODEV; goto exit; } /* verify that we actually have some data to write */ - if (count == 0) { + if (unlikely(count == 0)) { dbg(__FUNCTION__ " - write request of 0 bytes"); goto exit; } /* see if we are already in the middle of a write */ - if (dev->write_urb->status == -EINPROGRESS) { + if (dev->writing) { dbg (__FUNCTION__ " - already writing"); goto exit; } + /* We need to make sure that we are known to write */ + dev->writing = 1; + /* we can only write as much as 1 urb will hold */ bytes_written = (count > dev->bulk_out_size) ? dev->bulk_out_size : count; /* copy the data from userspace into our urb */ - if (copy_from_user(dev->write_urb->transfer_buffer, buffer, - bytes_written)) { + if (unlikely(copy_from_user(dev->write_urb->transfer_buffer, + buffer, bytes_written))) { retval = -EFAULT; goto exit; } @@ -432,7 +439,7 @@ /* send the data out the bulk port */ retval = usb_submit_urb(dev->write_urb); - if (retval) { + if (unlikely(retval)) { err(__FUNCTION__ " - failed submitting write urb, error %d", retval); } else { @@ -453,6 +460,7 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct usb_skel *dev; + int retval = -ENOTTY; /* Unsupported ioctl */ dev = (struct usb_skel *)file->private_data; @@ -460,7 +468,7 @@ down (&dev->sem); /* verify that the device wasn't unplugged */ - if (dev->udev == NULL) { + if (unlikely(dev->udev == NULL)) { up (&dev->sem); return -ENODEV; } @@ -474,8 +482,7 @@ /* unlock the device */ up (&dev->sem); - /* return that we did not understand this ioctl call */ - return -ENOTTY; + return retval; } @@ -488,13 +495,18 @@ dbg(__FUNCTION__ " - minor %d", dev->minor); - if ((urb->status != -ENOENT) && - (urb->status != -ECONNRESET)) { + /* We check for errors and report them + unless the URB was unlinked */ + if (unlikely((urb->status != 0) && + (urb->status != -ENOENT) && + (urb->status != -ECONNRESET))) { dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); + dev->writing = 0; return; } + dev->writing = 0; return; } @@ -536,7 +548,7 @@ /* allocate memory for our device state and intialize it */ dev = kmalloc (sizeof(struct usb_skel), GFP_KERNEL); - if (dev == NULL) { + if (unlikely(dev == NULL)) { err ("Out of memory"); goto exit; } @@ -687,4 +699,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); + + Hi,
this patch fixes a) the error test in the callback b) a race condition on write c) module usage count bug d) adds likely/unlikely Regards Oliver _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel