Merge branch 'drm-ttm-unmappable' into drm-core-next
[pandora-kernel.git] / drivers / usb / host / r8a66597-hcd.c
index bee558a..d478ffa 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/irq.h>
+#include <linux/slab.h>
 #include <asm/cacheflush.h>
 
 #include "../core/hcd.h"
@@ -418,7 +419,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 +431,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 +1076,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 +2092,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 +2235,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));