Commit cf7fdd57 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

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
5186ffee
Therefore it should go into 2.6.31
Signed-off-by: default avatarOliver Neukum <oliver@neukum.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c15e3ca1
...@@ -387,7 +387,6 @@ static void acm_rx_tasklet(unsigned long _acm) ...@@ -387,7 +387,6 @@ static void acm_rx_tasklet(unsigned long _acm)
struct acm_ru *rcv; struct acm_ru *rcv;
unsigned long flags; unsigned long flags;
unsigned char throttled; unsigned char throttled;
struct usb_host_endpoint *ep;
dbg("Entering acm_rx_tasklet"); dbg("Entering acm_rx_tasklet");
...@@ -463,14 +462,12 @@ static void acm_rx_tasklet(unsigned long _acm) ...@@ -463,14 +462,12 @@ static void acm_rx_tasklet(unsigned long _acm)
rcv->buffer = buf; rcv->buffer = buf;
ep = (usb_pipein(acm->rx_endpoint) ? acm->dev->ep_in : acm->dev->ep_out) if (acm->is_int_ep)
[usb_pipeendpoint(acm->rx_endpoint)];
if (usb_endpoint_xfer_int(&ep->desc))
usb_fill_int_urb(rcv->urb, acm->dev, usb_fill_int_urb(rcv->urb, acm->dev,
acm->rx_endpoint, acm->rx_endpoint,
buf->base, buf->base,
acm->readsize, acm->readsize,
acm_read_bulk, rcv, ep->desc.bInterval); acm_read_bulk, rcv, acm->bInterval);
else else
usb_fill_bulk_urb(rcv->urb, acm->dev, usb_fill_bulk_urb(rcv->urb, acm->dev,
acm->rx_endpoint, acm->rx_endpoint,
...@@ -1183,6 +1180,9 @@ static int acm_probe(struct usb_interface *intf, ...@@ -1183,6 +1180,9 @@ static int acm_probe(struct usb_interface *intf,
spin_lock_init(&acm->read_lock); spin_lock_init(&acm->read_lock);
mutex_init(&acm->mutex); mutex_init(&acm->mutex);
acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); 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); tty_port_init(&acm->port);
acm->port.ops = &acm_port_ops; acm->port.ops = &acm_port_ops;
......
...@@ -126,6 +126,8 @@ struct acm { ...@@ -126,6 +126,8 @@ struct acm {
unsigned int ctrl_caps; /* control capabilities from the class specific header */ unsigned int ctrl_caps; /* control capabilities from the class specific header */
unsigned int susp_count; /* number of suspended interfaces */ unsigned int susp_count; /* number of suspended interfaces */
int combined_interfaces:1; /* control and data collapsed */ 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 */ struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment