Merge 3.4-rc6 into usb-next
[deliverable/linux.git] / drivers / usb / class / cdc-wdm.c
index c6f6560d436c804bba1f539a2b6cd1c12be8633d..5d151653ae432b86385d8159660200b0b0d1c7d9 100644 (file)
@@ -157,8 +157,9 @@ static void wdm_out_callback(struct urb *urb)
        spin_lock(&desc->iuspin);
        desc->werr = urb->status;
        spin_unlock(&desc->iuspin);
-       clear_bit(WDM_IN_USE, &desc->flags);
        kfree(desc->outbuf);
+       desc->outbuf = NULL;
+       clear_bit(WDM_IN_USE, &desc->flags);
        wake_up(&desc->wait);
 }
 
@@ -338,7 +339,7 @@ static ssize_t wdm_write
        if (we < 0)
                return -EIO;
 
-       desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
+       buf = kmalloc(count, GFP_KERNEL);
        if (!buf) {
                rv = -ENOMEM;
                goto outnl;
@@ -368,6 +369,7 @@ static ssize_t wdm_write
        r = usb_autopm_get_interface(desc->intf);
        if (r < 0) {
                kfree(buf);
+               rv = usb_translate_errors(r);
                goto outnp;
        }
 
@@ -383,6 +385,7 @@ static ssize_t wdm_write
 
        if (r < 0) {
                kfree(buf);
+               rv = r;
                goto out;
        }
 
@@ -406,12 +409,15 @@ static ssize_t wdm_write
        req->wIndex = desc->inum;
        req->wLength = cpu_to_le16(count);
        set_bit(WDM_IN_USE, &desc->flags);
+       desc->outbuf = buf;
 
        rv = usb_submit_urb(desc->command, GFP_KERNEL);
        if (rv < 0) {
                kfree(buf);
+               desc->outbuf = NULL;
                clear_bit(WDM_IN_USE, &desc->flags);
                dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
+               rv = usb_translate_errors(rv);
        } else {
                dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
                        req->wIndex);
@@ -531,7 +537,7 @@ static int wdm_flush(struct file *file, fl_owner_t id)
                dev_err(&desc->intf->dev, "Error in flush path: %d\n",
                        desc->werr);
 
-       return desc->werr;
+       return usb_translate_errors(desc->werr);
 }
 
 static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait)
@@ -593,6 +599,7 @@ static int wdm_open(struct inode *inode, struct file *file)
                        desc->count--;
                        dev_err(&desc->intf->dev,
                                "Error submitting int urb - %d\n", rv);
+                       rv = usb_translate_errors(rv);
                }
        } else {
                rv = 0;
@@ -620,8 +627,12 @@ static int wdm_release(struct inode *inode, struct file *file)
        if (!desc->count) {
                dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
                kill_urbs(desc);
-               if (!test_bit(WDM_DISCONNECTING, &desc->flags))
+               if (!test_bit(WDM_DISCONNECTING, &desc->flags)) {
                        desc->manage_power(desc->intf, 0);
+               } else {
+                       dev_dbg(&desc->intf->dev, "%s: device gone - cleaning up\n", __func__);
+                       cleanup(desc);
+               }
        }
        mutex_unlock(&wdm_mutex);
        return 0;
@@ -895,6 +906,8 @@ static void wdm_disconnect(struct usb_interface *intf)
        mutex_unlock(&desc->rlock);
        if (!desc->count)
                cleanup(desc);
+       else
+               dev_dbg(&intf->dev, "%s: %d open files - postponing cleanup\n", __func__, desc->count);
        mutex_unlock(&wdm_mutex);
 }
 
This page took 0.026061 seconds and 5 git commands to generate.