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>
This commit is contained in:
parent
c15e3ca1d8
commit
cf7fdd57f9
@ -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 @@ urbs:
|
|||||||
|
|
||||||
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 @@ made_compressed_probe:
|
|||||||
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 {
|
|||||||
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user