diff options
author | Oliver Neukum <oliver@neukum.org> | 2009-08-04 23:52:09 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-08-07 16:05:14 -0700 |
commit | cf7fdd57f978d40ceb9a0f58a25f5cf9c84d6f33 (patch) | |
tree | 17de519a492c4353dc65111bec683bd4f038a311 /drivers/usb | |
parent | c15e3ca1d822abba78c00b1ffc3e7b382a50396e (diff) | |
download | op-kernel-dev-cf7fdd57f978d40ceb9a0f58a25f5cf9c84d6f33.zip op-kernel-dev-cf7fdd57f978d40ceb9a0f58a25f5cf9c84d6f33.tar.gz |
USB: fix oops on disconnect in cdc-acm
This patch fixes an oops caused when during an unplug a device's table
of endpoints is zeroed before the driver is notified. A pointer to
the endpoint must be cached.
this fixes a regression caused by commit
5186ffee2320942c3dc9745f7930e0eb15329ca6
Therefore it should go into 2.6.31
Signed-off-by: Oliver Neukum <oliver@neukum.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/class/cdc-acm.c | 10 | ||||
-rw-r--r-- | drivers/usb/class/cdc-acm.h | 2 |
2 files changed, 7 insertions, 5 deletions
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e1f8941..2bfc41e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -387,7 +387,6 @@ static void acm_rx_tasklet(unsigned long _acm) struct acm_ru *rcv; unsigned long flags; unsigned char throttled; - struct usb_host_endpoint *ep; dbg("Entering acm_rx_tasklet"); @@ -463,14 +462,12 @@ urbs: rcv->buffer = buf; - ep = (usb_pipein(acm->rx_endpoint) ? acm->dev->ep_in : acm->dev->ep_out) - [usb_pipeendpoint(acm->rx_endpoint)]; - if (usb_endpoint_xfer_int(&ep->desc)) + if (acm->is_int_ep) usb_fill_int_urb(rcv->urb, acm->dev, acm->rx_endpoint, buf->base, acm->readsize, - acm_read_bulk, rcv, ep->desc.bInterval); + acm_read_bulk, rcv, acm->bInterval); else usb_fill_bulk_urb(rcv->urb, acm->dev, acm->rx_endpoint, @@ -1183,6 +1180,9 @@ made_compressed_probe: spin_lock_init(&acm->read_lock); mutex_init(&acm->mutex); acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); + acm->is_int_ep = usb_endpoint_xfer_int(epread); + if (acm->is_int_ep) + acm->bInterval = epread->bInterval; tty_port_init(&acm->port); acm->port.ops = &acm_port_ops; diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 1602324..c4a0ee8 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -126,6 +126,8 @@ struct acm { unsigned int ctrl_caps; /* control capabilities from the class specific header */ unsigned int susp_count; /* number of suspended interfaces */ int combined_interfaces:1; /* control and data collapsed */ + int is_int_ep:1; /* interrupt endpoints contrary to spec used */ + u8 bInterval; struct acm_wb *delayed_wb; /* write queued for a device about to be woken */ }; |