summaryrefslogtreecommitdiffstats
path: root/drivers/usb/class
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/class')
-rw-r--r--drivers/usb/class/cdc-acm.c1
-rw-r--r--drivers/usb/class/cdc-wdm.c38
-rw-r--r--drivers/usb/class/usblp.c82
3 files changed, 77 insertions, 44 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index b32ccb461019..f2a120eea9d4 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1664,6 +1664,7 @@ static struct usb_driver acm_driver = {
#ifdef CONFIG_PM
.supports_autosuspend = 1,
#endif
+ .disable_hub_initiated_lpm = 1,
};
/*
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 0bb2b3248dad..ea8b304f0e85 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -309,9 +309,6 @@ static void free_urbs(struct wdm_device *desc)
static void cleanup(struct wdm_device *desc)
{
- spin_lock(&wdm_device_list_lock);
- list_del(&desc->device_list);
- spin_unlock(&wdm_device_list_lock);
kfree(desc->sbuf);
kfree(desc->inbuf);
kfree(desc->orq);
@@ -369,6 +366,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;
}
@@ -384,6 +382,7 @@ static ssize_t wdm_write
if (r < 0) {
kfree(buf);
+ rv = r;
goto out;
}
@@ -415,6 +414,7 @@ static ssize_t wdm_write
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);
@@ -530,11 +530,13 @@ static int wdm_flush(struct file *file, fl_owner_t id)
struct wdm_device *desc = file->private_data;
wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags));
- if (desc->werr < 0)
+
+ /* cannot dereference desc->intf if WDM_DISCONNECTING */
+ if (desc->werr < 0 && !test_bit(WDM_DISCONNECTING, &desc->flags))
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)
@@ -545,7 +547,7 @@ static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait)
spin_lock_irqsave(&desc->iuspin, flags);
if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
- mask = POLLERR;
+ mask = POLLHUP | POLLERR;
spin_unlock_irqrestore(&desc->iuspin, flags);
goto desc_out;
}
@@ -596,6 +598,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;
@@ -621,10 +624,15 @@ static int wdm_release(struct inode *inode, struct file *file)
mutex_unlock(&desc->wlock);
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)) {
+ dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
+ kill_urbs(desc);
desc->manage_power(desc->intf, 0);
+ } else {
+ /* must avoid dev_printk here as desc->intf is invalid */
+ pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__);
+ cleanup(desc);
+ }
}
mutex_unlock(&wdm_mutex);
return 0;
@@ -771,6 +779,9 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor
out:
return rv;
err:
+ spin_lock(&wdm_device_list_lock);
+ list_del(&desc->device_list);
+ spin_unlock(&wdm_device_list_lock);
cleanup(desc);
return rv;
}
@@ -896,8 +907,16 @@ static void wdm_disconnect(struct usb_interface *intf)
cancel_work_sync(&desc->rxwork);
mutex_unlock(&desc->wlock);
mutex_unlock(&desc->rlock);
+
+ /* the desc->intf pointer used as list key is now invalid */
+ spin_lock(&wdm_device_list_lock);
+ list_del(&desc->device_list);
+ spin_unlock(&wdm_device_list_lock);
+
if (!desc->count)
cleanup(desc);
+ else
+ dev_dbg(&intf->dev, "%s: %d open files - postponing cleanup\n", __func__, desc->count);
mutex_unlock(&wdm_mutex);
}
@@ -1015,6 +1034,7 @@ static struct usb_driver wdm_driver = {
.post_reset = wdm_post_reset,
.id_table = wdm_ids,
.supports_autosuspend = 1,
+ .disable_hub_initiated_lpm = 1,
};
module_usb_driver(wdm_driver);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index a68c1a63dc65..d4c47d5d7625 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -172,27 +172,31 @@ struct usblp {
#ifdef DEBUG
static void usblp_dump(struct usblp *usblp)
{
+ struct device *dev = &usblp->intf->dev;
int p;
- dbg("usblp=0x%p", usblp);
- dbg("dev=0x%p", usblp->dev);
- dbg("present=%d", usblp->present);
- dbg("readbuf=0x%p", usblp->readbuf);
- dbg("readcount=%d", usblp->readcount);
- dbg("ifnum=%d", usblp->ifnum);
- for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
- dbg("protocol[%d].alt_setting=%d", p, usblp->protocol[p].alt_setting);
- dbg("protocol[%d].epwrite=%p", p, usblp->protocol[p].epwrite);
- dbg("protocol[%d].epread=%p", p, usblp->protocol[p].epread);
- }
- dbg("current_protocol=%d", usblp->current_protocol);
- dbg("minor=%d", usblp->minor);
- dbg("wstatus=%d", usblp->wstatus);
- dbg("rstatus=%d", usblp->rstatus);
- dbg("quirks=%d", usblp->quirks);
- dbg("used=%d", usblp->used);
- dbg("bidir=%d", usblp->bidir);
- dbg("device_id_string=\"%s\"",
+ dev_dbg(dev, "usblp=0x%p\n", usblp);
+ dev_dbg(dev, "dev=0x%p\n", usblp->dev);
+ dev_dbg(dev, "present=%d\n", usblp->present);
+ dev_dbg(dev, "readbuf=0x%p\n", usblp->readbuf);
+ dev_dbg(dev, "readcount=%d\n", usblp->readcount);
+ dev_dbg(dev, "ifnum=%d\n", usblp->ifnum);
+ for (p = USBLP_FIRST_PROTOCOL; p <= USBLP_LAST_PROTOCOL; p++) {
+ dev_dbg(dev, "protocol[%d].alt_setting=%d\n", p,
+ usblp->protocol[p].alt_setting);
+ dev_dbg(dev, "protocol[%d].epwrite=%p\n", p,
+ usblp->protocol[p].epwrite);
+ dev_dbg(dev, "protocol[%d].epread=%p\n", p,
+ usblp->protocol[p].epread);
+ }
+ dev_dbg(dev, "current_protocol=%d\n", usblp->current_protocol);
+ dev_dbg(dev, "minor=%d\n", usblp->minor);
+ dev_dbg(dev, "wstatus=%d\n", usblp->wstatus);
+ dev_dbg(dev, "rstatus=%d\n", usblp->rstatus);
+ dev_dbg(dev, "quirks=%d\n", usblp->quirks);
+ dev_dbg(dev, "used=%d\n", usblp->used);
+ dev_dbg(dev, "bidir=%d\n", usblp->bidir);
+ dev_dbg(dev, "device_id_string=\"%s\"\n",
usblp->device_id_string ?
usblp->device_id_string + 2 :
(unsigned char *)"(null)");
@@ -262,7 +266,8 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i
retval = usb_control_msg(usblp->dev,
dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0),
request, type | dir | recip, value, index, buf, len, USBLP_CTL_TIMEOUT);
- dbg("usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d",
+ dev_dbg(&usblp->intf->dev,
+ "usblp_control_msg: rq: 0x%02x dir: %d recip: %d value: %d idx: %d len: %#x result: %d\n",
request, !!dir, recip, value, index, len, retval);
return retval < 0 ? retval : 0;
}
@@ -500,8 +505,9 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd),
- _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd));
+ dev_dbg(&usblp->intf->dev,
+ "usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)\n", cmd,
+ _IOC_TYPE(cmd), _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd));
if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */
@@ -594,7 +600,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp%d requested/got HP channel %ld/%d",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d requested/got HP channel %ld/%d\n",
usblp->minor, arg, newChannel);
break;
@@ -614,7 +621,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp%d is bus=%d, device=%d",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d is bus=%d, device=%d\n",
usblp->minor, twoints[0], twoints[1]);
break;
@@ -634,7 +642,8 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto done;
}
- dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d is VID=0x%4.4X, PID=0x%4.4X\n",
usblp->minor, twoints[0], twoints[1]);
break;
@@ -987,7 +996,7 @@ static int usblp_submit_read(struct usblp *usblp)
usblp->rcomplete = 0;
spin_unlock_irqrestore(&usblp->lock, flags);
if ((rc = usb_submit_urb(urb, GFP_KERNEL)) < 0) {
- dbg("error submitting urb (%d)", rc);
+ dev_dbg(&usblp->intf->dev, "error submitting urb (%d)\n", rc);
spin_lock_irqsave(&usblp->lock, flags);
usblp->rstatus = rc;
usblp->rcomplete = 1;
@@ -1129,7 +1138,8 @@ static int usblp_probe(struct usb_interface *intf,
/* Analyze and pick initial alternate settings and endpoints. */
protocol = usblp_select_alts(usblp);
if (protocol < 0) {
- dbg("incompatible printer-class device 0x%4.4X/0x%4.4X",
+ dev_dbg(&intf->dev,
+ "incompatible printer-class device 0x%4.4X/0x%4.4X\n",
le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
retval = -ENODEV;
@@ -1158,14 +1168,14 @@ static int usblp_probe(struct usb_interface *intf,
retval = usb_register_dev(intf, &usblp_class);
if (retval) {
- printk(KERN_ERR "usblp: Not able to get a minor"
- " (base %u, slice default): %d\n",
- USBLP_MINOR_BASE, retval);
+ dev_err(&intf->dev,
+ "usblp: Not able to get a minor (base %u, slice default): %d\n",
+ USBLP_MINOR_BASE, retval);
goto abort_intfdata;
}
usblp->minor = intf->minor;
- printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d "
- "if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n",
+ dev_info(&intf->dev,
+ "usblp%d: USB %sdirectional printer dev %d if %d alt %d proto %d vid 0x%4.4X pid 0x%4.4X\n",
usblp->minor, usblp->bidir ? "Bi" : "Uni", dev->devnum,
usblp->ifnum,
usblp->protocol[usblp->current_protocol].alt_setting,
@@ -1302,7 +1312,8 @@ static int usblp_set_protocol(struct usblp *usblp, int protocol)
usblp->bidir = (usblp->protocol[protocol].epread != NULL);
usblp->current_protocol = protocol;
- dbg("usblp%d set protocol %d", usblp->minor, protocol);
+ dev_dbg(&usblp->intf->dev, "usblp%d set protocol %d\n",
+ usblp->minor, protocol);
return 0;
}
@@ -1315,7 +1326,8 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
err = usblp_get_id(usblp, 0, usblp->device_id_string, USBLP_DEVICE_ID_SIZE - 1);
if (err < 0) {
- dbg("usblp%d: error = %d reading IEEE-1284 Device ID string",
+ dev_dbg(&usblp->intf->dev,
+ "usblp%d: error = %d reading IEEE-1284 Device ID string\n",
usblp->minor, err);
usblp->device_id_string[0] = usblp->device_id_string[1] = '\0';
return -EIO;
@@ -1331,7 +1343,7 @@ static int usblp_cache_device_id_string(struct usblp *usblp)
length = USBLP_DEVICE_ID_SIZE - 1;
usblp->device_id_string[length] = '\0';
- dbg("usblp%d Device ID string [len=%d]=\"%s\"",
+ dev_dbg(&usblp->intf->dev, "usblp%d Device ID string [len=%d]=\"%s\"\n",
usblp->minor, length, &usblp->device_id_string[2]);
return length;