From: Greg KH on
2.6.33-stable review patch. If anyone has any objections, please let us know.

------------------

From: Yoshihiro Shimoda <shimoda.yoshihiro(a)renesas.com>

commit d835933436ac0d1e8f5b35fe809fd4e767e55d6e upstream.

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(a)emtrion.de>
Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro(a)renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)suse.de>

---
drivers/usb/host/r8a66597-hcd.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)

--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -418,7 +418,7 @@ static u8 alloc_usb_address(struct r8a66

/* 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 r8a6
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(stru
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(struc
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 u
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));


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/