usb: r8a66597-hcd: fix removed from an attached hub
fix the problem that when a USB hub is attached to the r8a66597-hcd and a device is removed from that hub, it's likely that a kernel panic follows. Reported-by: Markus Pietrek <Markus.Pietrek@emtrion.de> Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Родитель
9ce669a892
Коммит
d835933436
|
@ -418,7 +418,7 @@ static u8 alloc_usb_address(struct r8a66597 *r8a66597, struct urb *urb)
|
|||
|
||||
/* this function must be called with interrupt disabled */
|
||||
static void free_usb_address(struct r8a66597 *r8a66597,
|
||||
struct r8a66597_device *dev)
|
||||
struct r8a66597_device *dev, int reset)
|
||||
{
|
||||
int port;
|
||||
|
||||
|
@ -430,7 +430,13 @@ static void free_usb_address(struct r8a66597 *r8a66597,
|
|||
dev->state = USB_STATE_DEFAULT;
|
||||
r8a66597->address_map &= ~(1 << dev->address);
|
||||
dev->address = 0;
|
||||
dev_set_drvdata(&dev->udev->dev, NULL);
|
||||
/*
|
||||
* Only when resetting USB, it is necessary to erase drvdata. When
|
||||
* a usb device with usb hub is disconnect, "dev->udev" is already
|
||||
* freed on usb_desconnect(). So we cannot access the data.
|
||||
*/
|
||||
if (reset)
|
||||
dev_set_drvdata(&dev->udev->dev, NULL);
|
||||
list_del(&dev->device_list);
|
||||
kfree(dev);
|
||||
|
||||
|
@ -1069,7 +1075,7 @@ static void r8a66597_usb_disconnect(struct r8a66597 *r8a66597, int port)
|
|||
struct r8a66597_device *dev = r8a66597->root_hub[port].dev;
|
||||
|
||||
disable_r8a66597_pipe_all(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev, 0);
|
||||
|
||||
start_root_hub_sampling(r8a66597, port, 0);
|
||||
}
|
||||
|
@ -2085,7 +2091,7 @@ static void update_usb_address_map(struct r8a66597 *r8a66597,
|
|||
spin_lock_irqsave(&r8a66597->lock, flags);
|
||||
dev = get_r8a66597_device(r8a66597, addr);
|
||||
disable_r8a66597_pipe_all(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev, 0);
|
||||
put_child_connect_map(r8a66597, addr);
|
||||
spin_unlock_irqrestore(&r8a66597->lock, flags);
|
||||
}
|
||||
|
@ -2228,7 +2234,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
|
|||
rh->port |= (1 << USB_PORT_FEAT_RESET);
|
||||
|
||||
disable_r8a66597_pipe_all(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev);
|
||||
free_usb_address(r8a66597, dev, 1);
|
||||
|
||||
r8a66597_mdfy(r8a66597, USBRST, USBRST | UACT,
|
||||
get_dvstctr_reg(port));
|
||||
|
|
Загрузка…
Ссылка в новой задаче