]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/usb/usb-skeleton.c
Merge tag 'platform-drivers-x86-v5.4-3' of git://git.infradead.org/linux-platform...
[linux.git] / drivers / usb / usb-skeleton.c
index c31d17d05810c933f3098187023627d28e2ea61d..2dc58766273a721cbedbd54fd28452f7ba1308b0 100644 (file)
@@ -61,6 +61,7 @@ struct usb_skel {
        spinlock_t              err_lock;               /* lock for errors */
        struct kref             kref;
        struct mutex            io_mutex;               /* synchronize I/O with disconnect */
+       unsigned long           disconnected:1;
        wait_queue_head_t       bulk_in_wait;           /* to wait for an ongoing read */
 };
 #define to_skel_dev(d) container_of(d, struct usb_skel, kref)
@@ -73,6 +74,7 @@ static void skel_delete(struct kref *kref)
        struct usb_skel *dev = to_skel_dev(kref);
 
        usb_free_urb(dev->bulk_in_urb);
+       usb_put_intf(dev->interface);
        usb_put_dev(dev->udev);
        kfree(dev->bulk_in_buffer);
        kfree(dev);
@@ -124,10 +126,7 @@ static int skel_release(struct inode *inode, struct file *file)
                return -ENODEV;
 
        /* allow the device to be autosuspended */
-       mutex_lock(&dev->io_mutex);
-       if (dev->interface)
-               usb_autopm_put_interface(dev->interface);
-       mutex_unlock(&dev->io_mutex);
+       usb_autopm_put_interface(dev->interface);
 
        /* decrement the count on our device */
        kref_put(&dev->kref, skel_delete);
@@ -231,8 +230,7 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count,
 
        dev = file->private_data;
 
-       /* if we cannot read at all, return EOF */
-       if (!dev->bulk_in_urb || !count)
+       if (!count)
                return 0;
 
        /* no concurrent readers */
@@ -240,7 +238,7 @@ static ssize_t skel_read(struct file *file, char *buffer, size_t count,
        if (rv < 0)
                return rv;
 
-       if (!dev->interface) {          /* disconnect() was called */
+       if (dev->disconnected) {                /* disconnect() was called */
                rv = -ENODEV;
                goto exit;
        }
@@ -422,7 +420,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer,
 
        /* this lock makes sure we don't submit URBs to gone devices */
        mutex_lock(&dev->io_mutex);
-       if (!dev->interface) {          /* disconnect() was called */
+       if (dev->disconnected) {                /* disconnect() was called */
                mutex_unlock(&dev->io_mutex);
                retval = -ENODEV;
                goto error;
@@ -507,7 +505,7 @@ static int skel_probe(struct usb_interface *interface,
        init_waitqueue_head(&dev->bulk_in_wait);
 
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
-       dev->interface = interface;
+       dev->interface = usb_get_intf(interface);
 
        /* set up the endpoint information */
        /* use only the first bulk-in and bulk-out endpoints */
@@ -573,9 +571,10 @@ static void skel_disconnect(struct usb_interface *interface)
 
        /* prevent more I/O from starting */
        mutex_lock(&dev->io_mutex);
-       dev->interface = NULL;
+       dev->disconnected = 1;
        mutex_unlock(&dev->io_mutex);
 
+       usb_kill_urb(dev->bulk_in_urb);
        usb_kill_anchored_urbs(&dev->submitted);
 
        /* decrement our usage count */