diff options
author | Sarah Sharp <sarah.a.sharp@linux.intel.com> | 2009-12-09 18:59:17 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:12 -0500 |
commit | a5f0efaba4c2b644e6248648f75b0a8a522359f6 (patch) | |
tree | 62b899d29b3089dc2ce2f7037dc43cde34501b4c /drivers | |
parent | 2a8f82c4ceaffcfd64531dbdee1d1bc227387882 (diff) |
USB: Add call to notify xHC of a device reset.
Add a new host controller driver method, reset_device(), that the USB core
will use to notify the host of a successful device reset. The call may
fail due to out-of-memory errors; attempt the port reset sequence again if
that happens. Update hub_port_init() to allow resetting a configured
device.
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/hcd.h | 1 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 19 | ||||
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 1 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 1 |
4 files changed, 14 insertions, 8 deletions
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index bbe2b924aae8..70a7e490f81b 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h | |||
@@ -286,6 +286,7 @@ struct hc_driver { | |||
286 | */ | 286 | */ |
287 | int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev, | 287 | int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev, |
288 | struct usb_tt *tt, gfp_t mem_flags); | 288 | struct usb_tt *tt, gfp_t mem_flags); |
289 | int (*reset_device)(struct usb_hcd *, struct usb_device *); | ||
289 | }; | 290 | }; |
290 | 291 | ||
291 | extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); | 292 | extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); |
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 20ecb4cec8de..bb416cdee1a7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -2008,7 +2008,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2008 | struct usb_device *udev, unsigned int delay) | 2008 | struct usb_device *udev, unsigned int delay) |
2009 | { | 2009 | { |
2010 | int i, status; | 2010 | int i, status; |
2011 | struct usb_hcd *hcd; | ||
2011 | 2012 | ||
2013 | hcd = bus_to_hcd(udev->bus); | ||
2012 | /* Block EHCI CF initialization during the port reset. | 2014 | /* Block EHCI CF initialization during the port reset. |
2013 | * Some companion controllers don't like it when they mix. | 2015 | * Some companion controllers don't like it when they mix. |
2014 | */ | 2016 | */ |
@@ -2036,6 +2038,14 @@ static int hub_port_reset(struct usb_hub *hub, int port1, | |||
2036 | /* TRSTRCY = 10 ms; plus some extra */ | 2038 | /* TRSTRCY = 10 ms; plus some extra */ |
2037 | msleep(10 + 40); | 2039 | msleep(10 + 40); |
2038 | update_address(udev, 0); | 2040 | update_address(udev, 0); |
2041 | if (hcd->driver->reset_device) { | ||
2042 | status = hcd->driver->reset_device(hcd, udev); | ||
2043 | if (status < 0) { | ||
2044 | dev_err(&udev->dev, "Cannot reset " | ||
2045 | "HCD device state\n"); | ||
2046 | break; | ||
2047 | } | ||
2048 | } | ||
2039 | /* FALL THROUGH */ | 2049 | /* FALL THROUGH */ |
2040 | case -ENOTCONN: | 2050 | case -ENOTCONN: |
2041 | case -ENODEV: | 2051 | case -ENODEV: |
@@ -2645,14 +2655,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, | |||
2645 | 2655 | ||
2646 | mutex_lock(&usb_address0_mutex); | 2656 | mutex_lock(&usb_address0_mutex); |
2647 | 2657 | ||
2648 | if ((hcd->driver->flags & HCD_USB3) && udev->config) { | 2658 | if (!udev->config && oldspeed == USB_SPEED_SUPER) { |
2649 | /* FIXME this will need special handling by the xHCI driver. */ | ||
2650 | dev_dbg(&udev->dev, | ||
2651 | "xHCI reset of configured device " | ||
2652 | "not supported yet.\n"); | ||
2653 | retval = -EINVAL; | ||
2654 | goto fail; | ||
2655 | } else if (!udev->config && oldspeed == USB_SPEED_SUPER) { | ||
2656 | /* Don't reset USB 3.0 devices during an initial setup */ | 2659 | /* Don't reset USB 3.0 devices during an initial setup */ |
2657 | usb_set_device_state(udev, USB_STATE_DEFAULT); | 2660 | usb_set_device_state(udev, USB_STATE_DEFAULT); |
2658 | } else { | 2661 | } else { |
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index e097008d6fb1..417d37aff8d7 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
@@ -139,6 +139,7 @@ static const struct hc_driver xhci_pci_hc_driver = { | |||
139 | .reset_bandwidth = xhci_reset_bandwidth, | 139 | .reset_bandwidth = xhci_reset_bandwidth, |
140 | .address_device = xhci_address_device, | 140 | .address_device = xhci_address_device, |
141 | .update_hub_device = xhci_update_hub_device, | 141 | .update_hub_device = xhci_update_hub_device, |
142 | .reset_device = xhci_reset_device, | ||
142 | 143 | ||
143 | /* | 144 | /* |
144 | * scheduling support | 145 | * scheduling support |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index feb0101f91eb..741ece482e31 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -1270,6 +1270,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); | |||
1270 | int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); | 1270 | int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); |
1271 | int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); | 1271 | int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); |
1272 | void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); | 1272 | void xhci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep); |
1273 | int xhci_reset_device(struct usb_hcd *hcd, struct usb_device *udev); | ||
1273 | int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); | 1274 | int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); |
1274 | void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); | 1275 | void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); |
1275 | 1276 | ||