lkml.org 
[lkml]   [2010]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[076/156] usb: r8a66597-hcd: fix removed from an attached hub
    2.6.33-stable review patch.  If anyone has any objections, please let us know.

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

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



    \
     
     \ /
      Last update: 2010-03-31 01:45    [W:4.316 / U:0.292 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site