diff options
Diffstat (limited to 'drivers/usb/core/hub.c')
| -rw-r--r-- | drivers/usb/core/hub.c | 4487 |
1 files changed, 3484 insertions, 1003 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 68fc5219ca1..0e950ad8cb2 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -19,74 +19,22 @@ #include <linux/ioctl.h> #include <linux/usb.h> #include <linux/usbdevice_fs.h> +#include <linux/usb/hcd.h> +#include <linux/usb/otg.h> +#include <linux/usb/quirks.h> #include <linux/kthread.h> #include <linux/mutex.h> #include <linux/freezer.h> +#include <linux/random.h> +#include <linux/pm_qos.h> -#include <asm/semaphore.h> #include <asm/uaccess.h> #include <asm/byteorder.h> -#include "usb.h" -#include "hcd.h" #include "hub.h" -#ifdef CONFIG_USB_PERSIST -#define USB_PERSIST 1 -#else -#define USB_PERSIST 0 -#endif - -/* if we are in debug mode, always announce new devices */ -#ifdef DEBUG -#ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES -#define CONFIG_USB_ANNOUNCE_NEW_DEVICES -#endif -#endif - -struct usb_hub { - struct device *intfdev; /* the "interface" device */ - struct usb_device *hdev; - struct kref kref; - struct urb *urb; /* for interrupt polling pipe */ - - /* buffer for urb ... with extra space in case of babble */ - char (*buffer)[8]; - dma_addr_t buffer_dma; /* DMA address for buffer */ - union { - struct usb_hub_status hub; - struct usb_port_status port; - } *status; /* buffer for status reports */ - struct mutex status_mutex; /* for the status buffer */ - - int error; /* last reported error */ - int nerrors; /* track consecutive errors */ - - struct list_head event_list; /* hubs w/data or errs ready */ - unsigned long event_bits[1]; /* status change bitmask */ - unsigned long change_bits[1]; /* ports with logical connect - status change */ - unsigned long busy_bits[1]; /* ports being reset or - resumed */ -#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ -#error event_bits[] is too short! -#endif - - struct usb_hub_descriptor *descriptor; /* class descriptor */ - struct usb_tt tt; /* Transaction Translator */ - - unsigned mA_per_port; /* current for each child */ - - unsigned limited_power:1; - unsigned quiescing:1; - unsigned activating:1; - unsigned disconnected:1; - - unsigned has_indicators:1; - u8 indicator[USB_MAXCHILDREN]; - struct delayed_work leds; -}; - +#define USB_VENDOR_GENESYS_LOGIC 0x05e3 +#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01 /* Protect struct usb_device->state and ->children members * Note: Both are also protected by ->dev.sem, except that ->state can @@ -102,12 +50,26 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); static struct task_struct *khubd_task; +/* synchronize hub-port add/remove and peering operations */ +DEFINE_MUTEX(usb_port_peer_mutex); + /* cycle leds on hubs that aren't blinking for attention */ -static int blinkenlights = 0; +static bool blinkenlights = 0; module_param (blinkenlights, bool, S_IRUGO); MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs"); /* + * Device SATA8000 FW1.0 from DATAST0R Technology Corp requires about + * 10 seconds to send reply for the initial 64-byte descriptor request. + */ +/* define initial 64-byte descriptor request timeout in milliseconds */ +static int initial_descriptor_timeout = USB_CTRL_GET_TIMEOUT; +module_param(initial_descriptor_timeout, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(initial_descriptor_timeout, + "initial 64-byte descriptor request timeout in milliseconds " + "(default 5000 - 5.0 seconds)"); + +/* * As of 2.6.10 we introduce a new USB device initialization scheme which * closely resembles the way Windows works. Hopefully it will be compatible * with a wider range of devices than the old scheme. However some previously @@ -121,12 +83,12 @@ MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs"); * otherwise the new scheme is used. If that fails and "use_both_schemes" * is set, then the driver will make another attempt, using the other scheme. */ -static int old_scheme_first = 0; +static bool old_scheme_first = 0; module_param(old_scheme_first, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(old_scheme_first, "start with the old device initialization scheme"); -static int use_both_schemes = 1; +static bool use_both_schemes = 1; module_param(use_both_schemes, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(use_both_schemes, "try the other device initialization scheme if the " @@ -138,32 +100,280 @@ MODULE_PARM_DESC(use_both_schemes, DECLARE_RWSEM(ehci_cf_port_reset_rwsem); EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); +#define HUB_DEBOUNCE_TIMEOUT 2000 +#define HUB_DEBOUNCE_STEP 25 +#define HUB_DEBOUNCE_STABLE 100 + +static int usb_reset_and_verify_device(struct usb_device *udev); -static inline char *portspeed(int portstatus) +static inline char *portspeed(struct usb_hub *hub, int portstatus) { - if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) - return "480 Mb/s"; - else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) + if (hub_is_superspeed(hub->hdev)) + return "5.0 Gb/s"; + if (portstatus & USB_PORT_STAT_HIGH_SPEED) + return "480 Mb/s"; + else if (portstatus & USB_PORT_STAT_LOW_SPEED) return "1.5 Mb/s"; else return "12 Mb/s"; } /* Note that hdev or one of its children must be locked! */ -static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev) +struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) { + if (!hdev || !hdev->actconfig || !hdev->maxchild) + return NULL; return usb_get_intfdata(hdev->actconfig->interface[0]); } +static int usb_device_supports_lpm(struct usb_device *udev) +{ + /* USB 2.1 (and greater) devices indicate LPM support through + * their USB 2.0 Extended Capabilities BOS descriptor. + */ + if (udev->speed == USB_SPEED_HIGH) { + if (udev->bos->ext_cap && + (USB_LPM_SUPPORT & + le32_to_cpu(udev->bos->ext_cap->bmAttributes))) + return 1; + return 0; + } + + /* + * According to the USB 3.0 spec, all USB 3.0 devices must support LPM. + * However, there are some that don't, and they set the U1/U2 exit + * latencies to zero. + */ + if (!udev->bos->ss_cap) { + dev_info(&udev->dev, "No LPM exit latency info found, disabling LPM.\n"); + return 0; + } + + if (udev->bos->ss_cap->bU1devExitLat == 0 && + udev->bos->ss_cap->bU2DevExitLat == 0) { + if (udev->parent) + dev_info(&udev->dev, "LPM exit latency is zeroed, disabling LPM.\n"); + else + dev_info(&udev->dev, "We don't know the algorithms for LPM for this host, disabling LPM.\n"); + return 0; + } + + if (!udev->parent || udev->parent->lpm_capable) + return 1; + return 0; +} + +/* + * Set the Maximum Exit Latency (MEL) for the host to initiate a transition from + * either U1 or U2. + */ +static void usb_set_lpm_mel(struct usb_device *udev, + struct usb3_lpm_parameters *udev_lpm_params, + unsigned int udev_exit_latency, + struct usb_hub *hub, + struct usb3_lpm_parameters *hub_lpm_params, + unsigned int hub_exit_latency) +{ + unsigned int total_mel; + unsigned int device_mel; + unsigned int hub_mel; + + /* + * Calculate the time it takes to transition all links from the roothub + * to the parent hub into U0. The parent hub must then decode the + * packet (hub header decode latency) to figure out which port it was + * bound for. + * + * The Hub Header decode latency is expressed in 0.1us intervals (0x1 + * means 0.1us). Multiply that by 100 to get nanoseconds. + */ + total_mel = hub_lpm_params->mel + + (hub->descriptor->u.ss.bHubHdrDecLat * 100); + + /* + * How long will it take to transition the downstream hub's port into + * U0? The greater of either the hub exit latency or the device exit + * latency. + * + * The BOS U1/U2 exit latencies are expressed in 1us intervals. + * Multiply that by 1000 to get nanoseconds. + */ + device_mel = udev_exit_latency * 1000; + hub_mel = hub_exit_latency * 1000; + if (device_mel > hub_mel) + total_mel += device_mel; + else + total_mel += hub_mel; + + udev_lpm_params->mel = total_mel; +} + +/* + * Set the maximum Device to Host Exit Latency (PEL) for the device to initiate + * a transition from either U1 or U2. + */ +static void usb_set_lpm_pel(struct usb_device *udev, + struct usb3_lpm_parameters *udev_lpm_params, + unsigned int udev_exit_latency, + struct usb_hub *hub, + struct usb3_lpm_parameters *hub_lpm_params, + unsigned int hub_exit_latency, + unsigned int port_to_port_exit_latency) +{ + unsigned int first_link_pel; + unsigned int hub_pel; + + /* + * First, the device sends an LFPS to transition the link between the + * device and the parent hub into U0. The exit latency is the bigger of + * the device exit latency or the hub exit latency. + */ + if (udev_exit_latency > hub_exit_latency) + first_link_pel = udev_exit_latency * 1000; + else + first_link_pel = hub_exit_latency * 1000; + + /* + * When the hub starts to receive the LFPS, there is a slight delay for + * it to figure out that one of the ports is sending an LFPS. Then it + * will forward the LFPS to its upstream link. The exit latency is the + * delay, plus the PEL that we calculated for this hub. + */ + hub_pel = port_to_port_exit_latency * 1000 + hub_lpm_params->pel; + + /* + * According to figure C-7 in the USB 3.0 spec, the PEL for this device + * is the greater of the two exit latencies. + */ + if (first_link_pel > hub_pel) + udev_lpm_params->pel = first_link_pel; + else + udev_lpm_params->pel = hub_pel; +} + +/* + * Set the System Exit Latency (SEL) to indicate the total worst-case time from + * when a device initiates a transition to U0, until when it will receive the + * first packet from the host controller. + * + * Section C.1.5.1 describes the four components to this: + * - t1: device PEL + * - t2: time for the ERDY to make it from the device to the host. + * - t3: a host-specific delay to process the ERDY. + * - t4: time for the packet to make it from the host to the device. + * + * t3 is specific to both the xHCI host and the platform the host is integrated + * into. The Intel HW folks have said it's negligible, FIXME if a different + * vendor says otherwise. + */ +static void usb_set_lpm_sel(struct usb_device *udev, + struct usb3_lpm_parameters *udev_lpm_params) +{ + struct usb_device *parent; + unsigned int num_hubs; + unsigned int total_sel; + + /* t1 = device PEL */ + total_sel = udev_lpm_params->pel; + /* How many external hubs are in between the device & the root port. */ + for (parent = udev->parent, num_hubs = 0; parent->parent; + parent = parent->parent) + num_hubs++; + /* t2 = 2.1us + 250ns * (num_hubs - 1) */ + if (num_hubs > 0) + total_sel += 2100 + 250 * (num_hubs - 1); + + /* t4 = 250ns * num_hubs */ + total_sel += 250 * num_hubs; + + udev_lpm_params->sel = total_sel; +} + +static void usb_set_lpm_parameters(struct usb_device *udev) +{ + struct usb_hub *hub; + unsigned int port_to_port_delay; + unsigned int udev_u1_del; + unsigned int udev_u2_del; + unsigned int hub_u1_del; + unsigned int hub_u2_del; + + if (!udev->lpm_capable || udev->speed != USB_SPEED_SUPER) + return; + + hub = usb_hub_to_struct_hub(udev->parent); + /* It doesn't take time to transition the roothub into U0, since it + * doesn't have an upstream link. + */ + if (!hub) + return; + + udev_u1_del = udev->bos->ss_cap->bU1devExitLat; + udev_u2_del = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat); + hub_u1_del = udev->parent->bos->ss_cap->bU1devExitLat; + hub_u2_del = le16_to_cpu(udev->parent->bos->ss_cap->bU2DevExitLat); + + usb_set_lpm_mel(udev, &udev->u1_params, udev_u1_del, + hub, &udev->parent->u1_params, hub_u1_del); + + usb_set_lpm_mel(udev, &udev->u2_params, udev_u2_del, + hub, &udev->parent->u2_params, hub_u2_del); + + /* + * Appendix C, section C.2.2.2, says that there is a slight delay from + * when the parent hub notices the downstream port is trying to + * transition to U0 to when the hub initiates a U0 transition on its + * upstream port. The section says the delays are tPort2PortU1EL and + * tPort2PortU2EL, but it doesn't define what they are. + * + * The hub chapter, sections 10.4.2.4 and 10.4.2.5 seem to be talking + * about the same delays. Use the maximum delay calculations from those + * sections. For U1, it's tHubPort2PortExitLat, which is 1us max. For + * U2, it's tHubPort2PortExitLat + U2DevExitLat - U1DevExitLat. I + * assume the device exit latencies they are talking about are the hub + * exit latencies. + * + * What do we do if the U2 exit latency is less than the U1 exit + * latency? It's possible, although not likely... + */ + port_to_port_delay = 1; + + usb_set_lpm_pel(udev, &udev->u1_params, udev_u1_del, + hub, &udev->parent->u1_params, hub_u1_del, + port_to_port_delay); + + if (hub_u2_del > hub_u1_del) + port_to_port_delay = 1 + hub_u2_del - hub_u1_del; + else + port_to_port_delay = 1 + hub_u1_del; + + usb_set_lpm_pel(udev, &udev->u2_params, udev_u2_del, + hub, &udev->parent->u2_params, hub_u2_del, + port_to_port_delay); + + /* Now that we've got PEL, calculate SEL. */ + usb_set_lpm_sel(udev, &udev->u1_params); + usb_set_lpm_sel(udev, &udev->u2_params); +} + /* USB 2.0 spec Section 11.24.4.5 */ -static int get_hub_descriptor(struct usb_device *hdev, void *data, int size) +static int get_hub_descriptor(struct usb_device *hdev, void *data) { - int i, ret; + int i, ret, size; + unsigned dtype; + + if (hub_is_superspeed(hdev)) { + dtype = USB_DT_SS_HUB; + size = USB_DT_SS_HUB_SIZE; + } else { + dtype = USB_DT_HUB; + size = sizeof(struct usb_hub_descriptor); + } for (i = 0; i < 3; i++) { ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB, - USB_DT_HUB << 8, 0, data, size, + dtype << 8, 0, data, size, USB_CTRL_GET_TIMEOUT); if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2)) return ret; @@ -183,7 +393,7 @@ static int clear_hub_feature(struct usb_device *hdev, int feature) /* * USB 2.0 spec Section 11.24.2.2 */ -static int clear_port_feature(struct usb_device *hdev, int port1, int feature) +int usb_clear_port_feature(struct usb_device *hdev, int port1, int feature) { return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1, @@ -200,30 +410,35 @@ static int set_port_feature(struct usb_device *hdev, int port1, int feature) NULL, 0, 1000); } +static char *to_led_name(int selector) +{ + switch (selector) { + case HUB_LED_AMBER: + return "amber"; + case HUB_LED_GREEN: + return "green"; + case HUB_LED_OFF: + return "off"; + case HUB_LED_AUTO: + return "auto"; + default: + return "??"; + } +} + /* * USB 2.0 spec Section 11.24.2.7.1.10 and table 11-7 * for info about using port indicators */ -static void set_port_led( - struct usb_hub *hub, - int port1, - int selector -) +static void set_port_led(struct usb_hub *hub, int port1, int selector) { - int status = set_port_feature(hub->hdev, (selector << 8) | port1, + struct usb_port *port_dev = hub->ports[port1 - 1]; + int status; + + status = set_port_feature(hub->hdev, (selector << 8) | port1, USB_PORT_FEAT_INDICATOR); - if (status < 0) - dev_dbg (hub->intfdev, - "port %d indicator %s status %d\n", - port1, - ({ char *s; switch (selector) { - case HUB_LED_AMBER: s = "amber"; break; - case HUB_LED_GREEN: s = "green"; break; - case HUB_LED_OFF: s = "off"; break; - case HUB_LED_AUTO: s = "auto"; break; - default: s = "??"; break; - }; s; }), - status); + dev_dbg(&port_dev->dev, "indicator %s status %d\n", + to_led_name(selector), status); } #define LED_CYCLE_PERIOD ((2*HZ)/3) @@ -240,7 +455,7 @@ static void led_work (struct work_struct *work) if (hdev->state != USB_STATE_CONFIGURED || hub->quiescing) return; - for (i = 0; i < hub->descriptor->bNbrPorts; i++) { + for (i = 0; i < hdev->maxchild; i++) { unsigned selector, mode; /* 30%-50% duty cycle */ @@ -289,13 +504,14 @@ static void led_work (struct work_struct *work) } if (!changed && blinkenlights) { cursor++; - cursor %= hub->descriptor->bNbrPorts; + cursor %= hdev->maxchild; set_port_led(hub, cursor + 1, HUB_LED_GREEN); hub->indicator[cursor] = INDICATOR_CYCLE; changed++; } if (changed) - schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); + queue_delayed_work(system_power_efficient_wq, + &hub->leds, LED_CYCLE_PERIOD); } /* use a short timeout for hub/port status fetches */ @@ -310,7 +526,8 @@ static int get_hub_status(struct usb_device *hdev, { int i, status = -ETIMEDOUT; - for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { + for (i = 0; i < USB_STS_RETRIES && + (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0, data, sizeof(*data), USB_STS_TIMEOUT); @@ -326,7 +543,8 @@ static int get_port_status(struct usb_device *hdev, int port1, { int i, status = -ETIMEDOUT; - for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) { + for (i = 0; i < USB_STS_RETRIES && + (status == -ETIMEDOUT || status == -EPIPE); i++) { status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1, data, sizeof(*data), USB_STS_TIMEOUT); @@ -334,16 +552,40 @@ static int get_port_status(struct usb_device *hdev, int port1, return status; } +static int hub_port_status(struct usb_hub *hub, int port1, + u16 *status, u16 *change) +{ + int ret; + + mutex_lock(&hub->status_mutex); + ret = get_port_status(hub->hdev, port1, &hub->status->port); + if (ret < 4) { + if (ret != -ENODEV) + dev_err(hub->intfdev, + "%s failed (err = %d)\n", __func__, ret); + if (ret >= 0) + ret = -EIO; + } else { + *status = le16_to_cpu(hub->status->port.wPortStatus); + *change = le16_to_cpu(hub->status->port.wPortChange); + + ret = 0; + } + mutex_unlock(&hub->status_mutex); + return ret; +} + static void kick_khubd(struct usb_hub *hub) { unsigned long flags; - /* Suppress autosuspend until khubd runs */ - to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; - spin_lock_irqsave(&hub_event_lock, flags); if (!hub->disconnected && list_empty(&hub->event_list)) { list_add_tail(&hub->event_list, &hub_event_list); + + /* Suppress autosuspend until khubd runs */ + usb_autopm_get_interface_no_resume( + to_usb_interface(hub->intfdev)); wake_up(&khubd_wait); } spin_unlock_irqrestore(&hub_event_lock, flags); @@ -351,17 +593,42 @@ static void kick_khubd(struct usb_hub *hub) void usb_kick_khubd(struct usb_device *hdev) { - /* FIXME: What if hdev isn't bound to the hub driver? */ - kick_khubd(hdev_to_hub(hdev)); + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + + if (hub) + kick_khubd(hub); } +/* + * Let the USB core know that a USB 3.0 device has sent a Function Wake Device + * Notification, which indicates it had initiated remote wakeup. + * + * USB 3.0 hubs do not report the port link state change from U3 to U0 when the + * device initiates resume, so the USB core will not receive notice of the + * resume through the normal hub interrupt URB. + */ +void usb_wakeup_notification(struct usb_device *hdev, + unsigned int portnum) +{ + struct usb_hub *hub; + + if (!hdev) + return; + + hub = usb_hub_to_struct_hub(hdev); + if (hub) { + set_bit(portnum, hub->wakeup_bits); + kick_khubd(hub); + } +} +EXPORT_SYMBOL_GPL(usb_wakeup_notification); /* completion function, fires on port status changes and various faults */ static void hub_irq(struct urb *urb) { struct usb_hub *hub = urb->context; int status = urb->status; - int i; + unsigned i; unsigned long bits; switch (status) { @@ -406,7 +673,16 @@ resubmit: static inline int hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) { - return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0), + /* Need to clear both directions for control ep */ + if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) { + int status = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), + HUB_CLEAR_TT_BUFFER, USB_RT_PORT, + devinfo ^ 0x8000, tt, NULL, 0, 1000); + if (status) + return status; + } + return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, tt, NULL, 0, 1000); } @@ -417,42 +693,78 @@ hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) * talking to TTs must queue control transfers (not just bulk and iso), so * both can talk to the same hub concurrently. */ -static void hub_tt_kevent (struct work_struct *work) +static void hub_tt_work(struct work_struct *work) { struct usb_hub *hub = - container_of(work, struct usb_hub, tt.kevent); + container_of(work, struct usb_hub, tt.clear_work); unsigned long flags; - int limit = 100; spin_lock_irqsave (&hub->tt.lock, flags); - while (--limit && !list_empty (&hub->tt.clear_list)) { - struct list_head *temp; + while (!list_empty(&hub->tt.clear_list)) { + struct list_head *next; struct usb_tt_clear *clear; struct usb_device *hdev = hub->hdev; + const struct hc_driver *drv; int status; - temp = hub->tt.clear_list.next; - clear = list_entry (temp, struct usb_tt_clear, clear_list); + next = hub->tt.clear_list.next; + clear = list_entry (next, struct usb_tt_clear, clear_list); list_del (&clear->clear_list); /* drop lock so HCD can concurrently report other TT errors */ spin_unlock_irqrestore (&hub->tt.lock, flags); status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt); - spin_lock_irqsave (&hub->tt.lock, flags); - - if (status) + if (status && status != -ENODEV) dev_err (&hdev->dev, "clear tt %d (%04x) error %d\n", clear->tt, clear->devinfo, status); + + /* Tell the HCD, even if the operation failed */ + drv = clear->hcd->driver; + if (drv->clear_tt_buffer_complete) + (drv->clear_tt_buffer_complete)(clear->hcd, clear->ep); + kfree(clear); + spin_lock_irqsave(&hub->tt.lock, flags); } spin_unlock_irqrestore (&hub->tt.lock, flags); } /** - * usb_hub_tt_clear_buffer - clear control/bulk TT state in high speed hub - * @udev: the device whose split transaction failed - * @pipe: identifies the endpoint of the failed transaction + * usb_hub_set_port_power - control hub port's power state + * @hdev: USB device belonging to the usb hub + * @hub: target hub + * @port1: port index + * @set: expected status + * + * call this function to control port's power via setting or + * clearing the port's PORT_POWER feature. + * + * Return: 0 if successful. A negative error code otherwise. + */ +int usb_hub_set_port_power(struct usb_device *hdev, struct usb_hub *hub, + int port1, bool set) +{ + int ret; + + if (set) + ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + else + ret = usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + + if (ret) + return ret; + + if (set) + set_bit(port1, hub->power_bits); + else + clear_bit(port1, hub->power_bits); + return 0; +} + +/** + * usb_hub_clear_tt_buffer - clear control/bulk TT state in high speed hub + * @urb: an URB associated with the failed or incomplete split transaction * * High speed HCDs use this to tell the hub driver that some split control or * bulk transaction failed in a way that requires clearing internal state of @@ -461,9 +773,13 @@ static void hub_tt_kevent (struct work_struct *work) * * It may not be possible for that hub to handle additional full (or low) * speed transactions until that state is fully cleared out. + * + * Return: 0 if successful. A negative error code otherwise. */ -void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) +int usb_hub_clear_tt_buffer(struct urb *urb) { + struct usb_device *udev = urb->dev; + int pipe = urb->pipe; struct usb_tt *tt = udev->tt; unsigned long flags; struct usb_tt_clear *clear; @@ -475,7 +791,7 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) if ((clear = kmalloc (sizeof *clear, GFP_ATOMIC)) == NULL) { dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n"); /* FIXME recover somehow ... RESET_TT? */ - return; + return -ENOMEM; } /* info that CLEAR_TT_BUFFER needs */ @@ -487,21 +803,23 @@ void usb_hub_tt_clear_buffer (struct usb_device *udev, int pipe) : (USB_ENDPOINT_XFER_BULK << 11); if (usb_pipein (pipe)) clear->devinfo |= 1 << 15; - + + /* info for completion callback */ + clear->hcd = bus_to_hcd(udev->bus); + clear->ep = urb->ep; + /* tell keventd to clear state for this TT */ spin_lock_irqsave (&tt->lock, flags); list_add_tail (&clear->clear_list, &tt->clear_list); - schedule_work (&tt->kevent); + schedule_work(&tt->clear_work); spin_unlock_irqrestore (&tt->lock, flags); + return 0; } -EXPORT_SYMBOL_GPL(usb_hub_tt_clear_buffer); +EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer); -static void hub_power_on(struct usb_hub *hub) +static void hub_power_on(struct usb_hub *hub, bool do_delay) { int port1; - unsigned pgood_delay = hub->descriptor->bPwrOn2PwrGood * 2; - u16 wHubCharacteristics = - le16_to_cpu(hub->descriptor->wHubCharacteristics); /* Enable power on each port. Some hubs have reserved values * of LPSM (> 2) in their descriptors, even though they are @@ -509,47 +827,19 @@ static void hub_power_on(struct usb_hub *hub) * but only emulate it. In all cases, the ports won't work * unless we send these messages to the hub. */ - if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2) + if (hub_is_port_power_switchable(hub)) dev_dbg(hub->intfdev, "enabling power on all ports\n"); else dev_dbg(hub->intfdev, "trying to enable port power on " "non-switchable hub\n"); - for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) - set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); - - /* Wait at least 100 msec for power to become stable */ - msleep(max(pgood_delay, (unsigned) 100)); -} - -static void hub_quiesce(struct usb_hub *hub) -{ - /* (nonblocking) khubd and related activity won't re-trigger */ - hub->quiescing = 1; - hub->activating = 0; - - /* (blocking) stop khubd and related activity */ - usb_kill_urb(hub->urb); - if (hub->has_indicators) - cancel_delayed_work_sync(&hub->leds); - if (hub->tt.hub) - cancel_work_sync(&hub->tt.kevent); -} - -static void hub_activate(struct usb_hub *hub) -{ - int status; - - hub->quiescing = 0; - hub->activating = 1; - - status = usb_submit_urb(hub->urb, GFP_NOIO); - if (status < 0) - dev_err(hub->intfdev, "activate --> %d\n", status); - if (hub->has_indicators && blinkenlights) - schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD); - - /* scan all ports ASAP */ - kick_khubd(hub); + for (port1 = 1; port1 <= hub->hdev->maxchild; port1++) + if (test_bit(port1, hub->power_bits)) + set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); + else + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_POWER); + if (do_delay) + msleep(hub_power_on_good_delay(hub)); } static int hub_hub_status(struct usb_hub *hub, @@ -559,42 +849,117 @@ static int hub_hub_status(struct usb_hub *hub, mutex_lock(&hub->status_mutex); ret = get_hub_status(hub->hdev, &hub->status->hub); - if (ret < 0) - dev_err (hub->intfdev, - "%s failed (err = %d)\n", __FUNCTION__, ret); - else { + if (ret < 0) { + if (ret != -ENODEV) + dev_err(hub->intfdev, + "%s failed (err = %d)\n", __func__, ret); + } else { *status = le16_to_cpu(hub->status->hub.wHubStatus); - *change = le16_to_cpu(hub->status->hub.wHubChange); + *change = le16_to_cpu(hub->status->hub.wHubChange); ret = 0; } mutex_unlock(&hub->status_mutex); return ret; } +static int hub_set_port_link_state(struct usb_hub *hub, int port1, + unsigned int link_status) +{ + return set_port_feature(hub->hdev, + port1 | (link_status << 3), + USB_PORT_FEAT_LINK_STATE); +} + +/* + * If USB 3.0 ports are placed into the Disabled state, they will no longer + * detect any device connects or disconnects. This is generally not what the + * USB core wants, since it expects a disabled port to produce a port status + * change event when a new device connects. + * + * Instead, set the link state to Disabled, wait for the link to settle into + * that state, clear any change bits, and then put the port into the RxDetect + * state. + */ +static int hub_usb3_port_disable(struct usb_hub *hub, int port1) +{ + int ret; + int total_time; + u16 portchange, portstatus; + + if (!hub_is_superspeed(hub->hdev)) + return -EINVAL; + + ret = hub_port_status(hub, port1, &portstatus, &portchange); + if (ret < 0) + return ret; + + /* + * USB controller Advanced Micro Devices, Inc. [AMD] FCH USB XHCI + * Controller [1022:7814] will have spurious result making the following + * usb 3.0 device hotplugging route to the 2.0 root hub and recognized + * as high-speed device if we set the usb 3.0 port link state to + * Disabled. Since it's already in USB_SS_PORT_LS_RX_DETECT state, we + * check the state here to avoid the bug. + */ + if ((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_RX_DETECT) { + dev_dbg(&hub->ports[port1 - 1]->dev, + "Not disabling port; link state is RxDetect\n"); + return ret; + } + + ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); + if (ret) + return ret; + + /* Wait for the link to enter the disabled state. */ + for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { + ret = hub_port_status(hub, port1, &portstatus, &portchange); + if (ret < 0) + return ret; + + if ((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_SS_DISABLED) + break; + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + break; + msleep(HUB_DEBOUNCE_STEP); + } + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + dev_warn(&hub->ports[port1 - 1]->dev, + "Could not disable after %d ms\n", total_time); + + return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); +} + static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) { + struct usb_port *port_dev = hub->ports[port1 - 1]; struct usb_device *hdev = hub->hdev; int ret = 0; - if (hdev->children[port1-1] && set_state) - usb_set_device_state(hdev->children[port1-1], - USB_STATE_NOTATTACHED); - if (!hub->error) - ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); - if (ret) - dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", - port1, ret); + if (port_dev->child && set_state) + usb_set_device_state(port_dev->child, USB_STATE_NOTATTACHED); + if (!hub->error) { + if (hub_is_superspeed(hub->hdev)) + ret = hub_usb3_port_disable(hub, port1); + else + ret = usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_ENABLE); + } + if (ret && ret != -ENODEV) + dev_err(&port_dev->dev, "cannot disable (err = %d)\n", ret); return ret; } /* - * Disable a port and mark a logical connnect-change event, so that some + * Disable a port and mark a logical connect-change event, so that some * time later khubd will disconnect() any existing usb_device on the port * and will re-enumerate if there actually is a device attached. */ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) { - dev_dbg(hub->intfdev, "logical disconnect on port %d\n", port1); + dev_dbg(&hub->ports[port1 - 1]->dev, "logical disconnect\n"); hub_port_disable(hub, port1, 1); /* FIXME let caller ask to power down the port: @@ -607,22 +972,342 @@ static void hub_port_logical_disconnect(struct usb_hub *hub, int port1) */ set_bit(port1, hub->change_bits); - kick_khubd(hub); + kick_khubd(hub); } -/* caller has locked the hub device */ -static int hub_pre_reset(struct usb_interface *intf) +/** + * usb_remove_device - disable a device's port on its parent hub + * @udev: device to be disabled and removed + * Context: @udev locked, must be able to sleep. + * + * After @udev's port has been disabled, khubd is notified and it will + * see that the device has been disconnected. When the device is + * physically unplugged and something is plugged in, the events will + * be received and processed normally. + * + * Return: 0 if successful. A negative error code otherwise. + */ +int usb_remove_device(struct usb_device *udev) +{ + struct usb_hub *hub; + struct usb_interface *intf; + + if (!udev->parent) /* Can't remove a root hub */ + return -EINVAL; + hub = usb_hub_to_struct_hub(udev->parent); + intf = to_usb_interface(hub->intfdev); + + usb_autopm_get_interface(intf); + set_bit(udev->portnum, hub->removed_bits); + hub_port_logical_disconnect(hub, udev->portnum); + usb_autopm_put_interface(intf); + return 0; +} + +enum hub_activation_type { + HUB_INIT, HUB_INIT2, HUB_INIT3, /* INITs must come first */ + HUB_POST_RESET, HUB_RESUME, HUB_RESET_RESUME, +}; + +static void hub_init_func2(struct work_struct *ws); +static void hub_init_func3(struct work_struct *ws); + +static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) +{ + struct usb_device *hdev = hub->hdev; + struct usb_hcd *hcd; + int ret; + int port1; + int status; + bool need_debounce_delay = false; + unsigned delay; + + /* Continue a partial initialization */ + if (type == HUB_INIT2) + goto init2; + if (type == HUB_INIT3) + goto init3; + + /* The superspeed hub except for root hub has to use Hub Depth + * value as an offset into the route string to locate the bits + * it uses to determine the downstream port number. So hub driver + * should send a set hub depth request to superspeed hub after + * the superspeed hub is set configuration in initialization or + * reset procedure. + * + * After a resume, port power should still be on. + * For any other type of activation, turn it on. + */ + if (type != HUB_RESUME) { + if (hdev->parent && hub_is_superspeed(hdev)) { + ret = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), + HUB_SET_DEPTH, USB_RT_HUB, + hdev->level - 1, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + if (ret < 0) + dev_err(hub->intfdev, + "set hub depth failed\n"); + } + + /* Speed up system boot by using a delayed_work for the + * hub's initial power-up delays. This is pretty awkward + * and the implementation looks like a home-brewed sort of + * setjmp/longjmp, but it saves at least 100 ms for each + * root hub (assuming usbcore is compiled into the kernel + * rather than as a module). It adds up. + * + * This can't be done for HUB_RESUME or HUB_RESET_RESUME + * because for those activation types the ports have to be + * operational when we return. In theory this could be done + * for HUB_POST_RESET, but it's easier not to. + */ + if (type == HUB_INIT) { + unsigned delay = hub_power_on_good_delay(hub); + + hub_power_on(hub, false); + INIT_DELAYED_WORK(&hub->init_work, hub_init_func2); + queue_delayed_work(system_power_efficient_wq, + &hub->init_work, + msecs_to_jiffies(delay)); + + /* Suppress autosuspend until init is done */ + usb_autopm_get_interface_no_resume( + to_usb_interface(hub->intfdev)); + return; /* Continues at init2: below */ + } else if (type == HUB_RESET_RESUME) { + /* The internal host controller state for the hub device + * may be gone after a host power loss on system resume. + * Update the device's info so the HW knows it's a hub. + */ + hcd = bus_to_hcd(hdev->bus); + if (hcd->driver->update_hub_device) { + ret = hcd->driver->update_hub_device(hcd, hdev, + &hub->tt, GFP_NOIO); + if (ret < 0) { + dev_err(hub->intfdev, "Host not " + "accepting hub info " + "update.\n"); + dev_err(hub->intfdev, "LS/FS devices " + "and hubs may not work " + "under this hub\n."); + } + } + hub_power_on(hub, true); + } else { + hub_power_on(hub, true); + } + } + init2: + + /* + * Check each port and set hub->change_bits to let khubd know + * which ports need attention. + */ + for (port1 = 1; port1 <= hdev->maxchild; ++port1) { + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; + u16 portstatus, portchange; + + portstatus = portchange = 0; + status = hub_port_status(hub, port1, &portstatus, &portchange); + if (udev || (portstatus & USB_PORT_STAT_CONNECTION)) + dev_dbg(&port_dev->dev, "status %04x change %04x\n", + portstatus, portchange); + + /* + * After anything other than HUB_RESUME (i.e., initialization + * or any sort of reset), every port should be disabled. + * Unconnected ports should likewise be disabled (paranoia), + * and so should ports for which we have no usb_device. + */ + if ((portstatus & USB_PORT_STAT_ENABLE) && ( + type != HUB_RESUME || + !(portstatus & USB_PORT_STAT_CONNECTION) || + !udev || + udev->state == USB_STATE_NOTATTACHED)) { + /* + * USB3 protocol ports will automatically transition + * to Enabled state when detect an USB3.0 device attach. + * Do not disable USB3 protocol ports, just pretend + * power was lost + */ + portstatus &= ~USB_PORT_STAT_ENABLE; + if (!hub_is_superspeed(hdev)) + usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_ENABLE); + } + + /* Clear status-change flags; we'll debounce later */ + if (portchange & USB_PORT_STAT_C_CONNECTION) { + need_debounce_delay = true; + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + } + if (portchange & USB_PORT_STAT_C_ENABLE) { + need_debounce_delay = true; + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_ENABLE); + } + if (portchange & USB_PORT_STAT_C_RESET) { + need_debounce_delay = true; + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_RESET); + } + if ((portchange & USB_PORT_STAT_C_BH_RESET) && + hub_is_superspeed(hub->hdev)) { + need_debounce_delay = true; + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_BH_PORT_RESET); + } + /* We can forget about a "removed" device when there's a + * physical disconnect or the connect status changes. + */ + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + (portchange & USB_PORT_STAT_C_CONNECTION)) + clear_bit(port1, hub->removed_bits); + + if (!udev || udev->state == USB_STATE_NOTATTACHED) { + /* Tell khubd to disconnect the device or + * check for a new connection + */ + if (udev || (portstatus & USB_PORT_STAT_CONNECTION) || + (portstatus & USB_PORT_STAT_OVERCURRENT)) + set_bit(port1, hub->change_bits); + + } else if (portstatus & USB_PORT_STAT_ENABLE) { + bool port_resumed = (portstatus & + USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_U0; + /* The power session apparently survived the resume. + * If there was an overcurrent or suspend change + * (i.e., remote wakeup request), have khubd + * take care of it. Look at the port link state + * for USB 3.0 hubs, since they don't have a suspend + * change bit, and they don't set the port link change + * bit on device-initiated resume. + */ + if (portchange || (hub_is_superspeed(hub->hdev) && + port_resumed)) + set_bit(port1, hub->change_bits); + + } else if (udev->persist_enabled) { +#ifdef CONFIG_PM + udev->reset_resume = 1; +#endif + /* Don't set the change_bits when the device + * was powered off. + */ + if (test_bit(port1, hub->power_bits)) + set_bit(port1, hub->change_bits); + + } else { + /* The power session is gone; tell khubd */ + usb_set_device_state(udev, USB_STATE_NOTATTACHED); + set_bit(port1, hub->change_bits); + } + } + + /* If no port-status-change flags were set, we don't need any + * debouncing. If flags were set we can try to debounce the + * ports all at once right now, instead of letting khubd do them + * one at a time later on. + * + * If any port-status changes do occur during this delay, khubd + * will see them later and handle them normally. + */ + if (need_debounce_delay) { + delay = HUB_DEBOUNCE_STABLE; + + /* Don't do a long sleep inside a workqueue routine */ + if (type == HUB_INIT2) { + INIT_DELAYED_WORK(&hub->init_work, hub_init_func3); + queue_delayed_work(system_power_efficient_wq, + &hub->init_work, + msecs_to_jiffies(delay)); + return; /* Continues at init3: below */ + } else { + msleep(delay); + } + } + init3: + hub->quiescing = 0; + + status = usb_submit_urb(hub->urb, GFP_NOIO); + if (status < 0) + dev_err(hub->intfdev, "activate --> %d\n", status); + if (hub->has_indicators && blinkenlights) + queue_delayed_work(system_power_efficient_wq, + &hub->leds, LED_CYCLE_PERIOD); + + /* Scan all ports that need attention */ + kick_khubd(hub); + + /* Allow autosuspend if it was suppressed */ + if (type <= HUB_INIT3) + usb_autopm_put_interface_async(to_usb_interface(hub->intfdev)); +} + +/* Implement the continuations for the delays above */ +static void hub_init_func2(struct work_struct *ws) +{ + struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work); + + hub_activate(hub, HUB_INIT2); +} + +static void hub_init_func3(struct work_struct *ws) +{ + struct usb_hub *hub = container_of(ws, struct usb_hub, init_work.work); + + hub_activate(hub, HUB_INIT3); +} + +enum hub_quiescing_type { + HUB_DISCONNECT, HUB_PRE_RESET, HUB_SUSPEND +}; + +static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) { - struct usb_hub *hub = usb_get_intfdata(intf); struct usb_device *hdev = hub->hdev; int i; - /* Disconnect all the children */ - for (i = 0; i < hdev->maxchild; ++i) { - if (hdev->children[i]) - usb_disconnect(&hdev->children[i]); + cancel_delayed_work_sync(&hub->init_work); + + /* khubd and related activity won't re-trigger */ + hub->quiescing = 1; + + if (type != HUB_SUSPEND) { + /* Disconnect all the children */ + for (i = 0; i < hdev->maxchild; ++i) { + if (hub->ports[i]->child) + usb_disconnect(&hub->ports[i]->child); + } } - hub_quiesce(hub); + + /* Stop khubd and related activity */ + usb_kill_urb(hub->urb); + if (hub->has_indicators) + cancel_delayed_work_sync(&hub->leds); + if (hub->tt.hub) + flush_work(&hub->tt.clear_work); +} + +static void hub_pm_barrier_for_all_ports(struct usb_hub *hub) +{ + int i; + + for (i = 0; i < hub->hdev->maxchild; ++i) + pm_runtime_barrier(&hub->ports[i]->dev); +} + +/* caller has locked the hub device */ +static int hub_pre_reset(struct usb_interface *intf) +{ + struct usb_hub *hub = usb_get_intfdata(intf); + + hub_quiesce(hub, HUB_PRE_RESET); + hub->in_reset = 1; + hub_pm_barrier_for_all_ports(hub); return 0; } @@ -631,33 +1316,35 @@ static int hub_post_reset(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata(intf); - hub_power_on(hub); - hub_activate(hub); + hub->in_reset = 0; + hub_pm_barrier_for_all_ports(hub); + hub_activate(hub, HUB_POST_RESET); return 0; } static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { + struct usb_hcd *hcd; struct usb_device *hdev = hub->hdev; struct device *hub_dev = hub->intfdev; u16 hubstatus, hubchange; u16 wHubCharacteristics; unsigned int pipe; - int maxp, ret; - char *message; + int maxp, ret, i; + char *message = "out of memory"; + unsigned unit_load; + unsigned full_load; + unsigned maxchild; - hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL, - &hub->buffer_dma); + hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); if (!hub->buffer) { - message = "can't allocate hub irq buffer"; ret = -ENOMEM; goto fail; } hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL); if (!hub->status) { - message = "can't kmalloc hub status buffer"; ret = -ENOMEM; goto fail; } @@ -665,7 +1352,6 @@ static int hub_configure(struct usb_hub *hub, hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { - message = "can't kmalloc hub descriptor"; ret = -ENOMEM; goto fail; } @@ -674,8 +1360,7 @@ static int hub_configure(struct usb_hub *hub, * hub->descriptor can handle USB_MAXCHILDREN ports, * but the hub can/will return fewer bytes here. */ - ret = get_hub_descriptor(hdev, hub->descriptor, - sizeof(*hub->descriptor)); + ret = get_hub_descriptor(hdev, hub->descriptor); if (ret < 0) { message = "can't read hub descriptor"; goto fail; @@ -683,107 +1368,129 @@ static int hub_configure(struct usb_hub *hub, message = "hub has too many ports!"; ret = -ENODEV; goto fail; + } else if (hub->descriptor->bNbrPorts == 0) { + message = "hub doesn't have any ports!"; + ret = -ENODEV; + goto fail; } - hdev->maxchild = hub->descriptor->bNbrPorts; - dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, - (hdev->maxchild == 1) ? "" : "s"); + maxchild = hub->descriptor->bNbrPorts; + dev_info(hub_dev, "%d port%s detected\n", maxchild, + (maxchild == 1) ? "" : "s"); + + hub->ports = kzalloc(maxchild * sizeof(struct usb_port *), GFP_KERNEL); + if (!hub->ports) { + ret = -ENOMEM; + goto fail; + } wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); + if (hub_is_superspeed(hdev)) { + unit_load = 150; + full_load = 900; + } else { + unit_load = 100; + full_load = 500; + } - if (wHubCharacteristics & HUB_CHAR_COMPOUND) { + /* FIXME for USB 3.0, skip for now */ + if ((wHubCharacteristics & HUB_CHAR_COMPOUND) && + !(hub_is_superspeed(hdev))) { int i; - char portstr [USB_MAXCHILDREN + 1]; + char portstr[USB_MAXCHILDREN + 1]; - for (i = 0; i < hdev->maxchild; i++) - portstr[i] = hub->descriptor->DeviceRemovable + for (i = 0; i < maxchild; i++) + portstr[i] = hub->descriptor->u.hs.DeviceRemovable [((i + 1) / 8)] & (1 << ((i + 1) % 8)) ? 'F' : 'R'; - portstr[hdev->maxchild] = 0; + portstr[maxchild] = 0; dev_dbg(hub_dev, "compound device; port removable status: %s\n", portstr); } else dev_dbg(hub_dev, "standalone hub\n"); switch (wHubCharacteristics & HUB_CHAR_LPSM) { - case 0x00: - dev_dbg(hub_dev, "ganged power switching\n"); - break; - case 0x01: - dev_dbg(hub_dev, "individual port power switching\n"); - break; - case 0x02: - case 0x03: - dev_dbg(hub_dev, "no power switching (usb 1.0)\n"); - break; + case HUB_CHAR_COMMON_LPSM: + dev_dbg(hub_dev, "ganged power switching\n"); + break; + case HUB_CHAR_INDV_PORT_LPSM: + dev_dbg(hub_dev, "individual port power switching\n"); + break; + case HUB_CHAR_NO_LPSM: + case HUB_CHAR_LPSM: + dev_dbg(hub_dev, "no power switching (usb 1.0)\n"); + break; } switch (wHubCharacteristics & HUB_CHAR_OCPM) { - case 0x00: - dev_dbg(hub_dev, "global over-current protection\n"); - break; - case 0x08: - dev_dbg(hub_dev, "individual port over-current protection\n"); - break; - case 0x10: - case 0x18: - dev_dbg(hub_dev, "no over-current protection\n"); - break; + case HUB_CHAR_COMMON_OCPM: + dev_dbg(hub_dev, "global over-current protection\n"); + break; + case HUB_CHAR_INDV_PORT_OCPM: + dev_dbg(hub_dev, "individual port over-current protection\n"); + break; + case HUB_CHAR_NO_OCPM: + case HUB_CHAR_OCPM: + dev_dbg(hub_dev, "no over-current protection\n"); + break; } spin_lock_init (&hub->tt.lock); INIT_LIST_HEAD (&hub->tt.clear_list); - INIT_WORK (&hub->tt.kevent, hub_tt_kevent); + INIT_WORK(&hub->tt.clear_work, hub_tt_work); switch (hdev->descriptor.bDeviceProtocol) { - case 0: - break; - case 1: - dev_dbg(hub_dev, "Single TT\n"); - hub->tt.hub = hdev; - break; - case 2: - ret = usb_set_interface(hdev, 0, 1); - if (ret == 0) { - dev_dbg(hub_dev, "TT per port\n"); - hub->tt.multi = 1; - } else - dev_err(hub_dev, "Using single TT (err %d)\n", - ret); - hub->tt.hub = hdev; - break; - default: - dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", - hdev->descriptor.bDeviceProtocol); - break; + case USB_HUB_PR_FS: + break; + case USB_HUB_PR_HS_SINGLE_TT: + dev_dbg(hub_dev, "Single TT\n"); + hub->tt.hub = hdev; + break; + case USB_HUB_PR_HS_MULTI_TT: + ret = usb_set_interface(hdev, 0, 1); + if (ret == 0) { + dev_dbg(hub_dev, "TT per port\n"); + hub->tt.multi = 1; + } else + dev_err(hub_dev, "Using single TT (err %d)\n", + ret); + hub->tt.hub = hdev; + break; + case USB_HUB_PR_SS: + /* USB 3.0 hubs don't have a TT */ + break; + default: + dev_dbg(hub_dev, "Unrecognized hub protocol %d\n", + hdev->descriptor.bDeviceProtocol); + break; } /* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */ switch (wHubCharacteristics & HUB_CHAR_TTTT) { - case HUB_TTTT_8_BITS: - if (hdev->descriptor.bDeviceProtocol != 0) { - hub->tt.think_time = 666; - dev_dbg(hub_dev, "TT requires at most %d " - "FS bit times (%d ns)\n", - 8, hub->tt.think_time); - } - break; - case HUB_TTTT_16_BITS: - hub->tt.think_time = 666 * 2; - dev_dbg(hub_dev, "TT requires at most %d " - "FS bit times (%d ns)\n", - 16, hub->tt.think_time); - break; - case HUB_TTTT_24_BITS: - hub->tt.think_time = 666 * 3; + case HUB_TTTT_8_BITS: + if (hdev->descriptor.bDeviceProtocol != 0) { + hub->tt.think_time = 666; dev_dbg(hub_dev, "TT requires at most %d " "FS bit times (%d ns)\n", - 24, hub->tt.think_time); - break; - case HUB_TTTT_32_BITS: - hub->tt.think_time = 666 * 4; - dev_dbg(hub_dev, "TT requires at most %d " - "FS bit times (%d ns)\n", - 32, hub->tt.think_time); - break; + 8, hub->tt.think_time); + } + break; + case HUB_TTTT_16_BITS: + hub->tt.think_time = 666 * 2; + dev_dbg(hub_dev, "TT requires at most %d " + "FS bit times (%d ns)\n", + 16, hub->tt.think_time); + break; + case HUB_TTTT_24_BITS: + hub->tt.think_time = 666 * 3; + dev_dbg(hub_dev, "TT requires at most %d " + "FS bit times (%d ns)\n", + 24, hub->tt.think_time); + break; + case HUB_TTTT_32_BITS: + hub->tt.think_time = 666 * 4; + dev_dbg(hub_dev, "TT requires at most %d " + "FS bit times (%d ns)\n", + 32, hub->tt.think_time); + break; } /* probe() zeroes hub->indicator[] */ @@ -799,38 +1506,42 @@ static int hub_configure(struct usb_hub *hub, * and battery-powered root hubs (may provide just 8 mA). */ ret = usb_get_status(hdev, USB_RECIP_DEVICE, 0, &hubstatus); - if (ret < 2) { + if (ret) { message = "can't get hub status"; goto fail; } - le16_to_cpus(&hubstatus); + hcd = bus_to_hcd(hdev->bus); if (hdev == hdev->bus->root_hub) { - if (hdev->bus_mA == 0 || hdev->bus_mA >= 500) - hub->mA_per_port = 500; + if (hcd->power_budget > 0) + hdev->bus_mA = hcd->power_budget; + else + hdev->bus_mA = full_load * maxchild; + if (hdev->bus_mA >= full_load) + hub->mA_per_port = full_load; else { hub->mA_per_port = hdev->bus_mA; hub->limited_power = 1; } } else if ((hubstatus & (1 << USB_DEVICE_SELF_POWERED)) == 0) { + int remaining = hdev->bus_mA - + hub->descriptor->bHubContrCurrent; + dev_dbg(hub_dev, "hub controller current requirement: %dmA\n", hub->descriptor->bHubContrCurrent); hub->limited_power = 1; - if (hdev->maxchild > 0) { - int remaining = hdev->bus_mA - - hub->descriptor->bHubContrCurrent; - if (remaining < hdev->maxchild * 100) - dev_warn(hub_dev, + if (remaining < maxchild * unit_load) + dev_warn(hub_dev, "insufficient power available " "to use all downstream ports\n"); - hub->mA_per_port = 100; /* 7.2.1.1 */ - } + hub->mA_per_port = unit_load; /* 7.2.1 */ + } else { /* Self-powered external hub */ /* FIXME: What about battery-powered external hubs that * provide less current per port? */ - hub->mA_per_port = 500; + hub->mA_per_port = full_load; } - if (hub->mA_per_port < 500) + if (hub->mA_per_port < full_load) dev_dbg(hub_dev, "%umA bus power budget for each child\n", hub->mA_per_port); @@ -864,22 +1575,52 @@ static int hub_configure(struct usb_hub *hub, hub->urb = usb_alloc_urb(0, GFP_KERNEL); if (!hub->urb) { - message = "couldn't allocate interrupt urb"; ret = -ENOMEM; goto fail; } usb_fill_int_urb(hub->urb, hdev, pipe, *hub->buffer, maxp, hub_irq, hub, endpoint->bInterval); - hub->urb->transfer_dma = hub->buffer_dma; - hub->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* maybe cycle the hub leds */ if (hub->has_indicators && blinkenlights) - hub->indicator [0] = INDICATOR_CYCLE; + hub->indicator[0] = INDICATOR_CYCLE; - hub_power_on(hub); - hub_activate(hub); + mutex_lock(&usb_port_peer_mutex); + for (i = 0; i < maxchild; i++) { + ret = usb_hub_create_port_device(hub, i + 1); + if (ret < 0) { + dev_err(hub->intfdev, + "couldn't create port%d device.\n", i + 1); + break; + } + } + hdev->maxchild = i; + for (i = 0; i < hdev->maxchild; i++) { + struct usb_port *port_dev = hub->ports[i]; + + pm_runtime_put(&port_dev->dev); + } + + mutex_unlock(&usb_port_peer_mutex); + if (ret < 0) + goto fail; + + /* Update the HCD's internal representation of this hub before khubd + * starts getting port status changes for devices under the hub. + */ + if (hcd->driver->update_hub_device) { + ret = hcd->driver->update_hub_device(hcd, hdev, + &hub->tt, GFP_KERNEL); + if (ret < 0) { + message = "can't update HCD hub info"; + goto fail; + } + } + + usb_hub_adjust_deviceremovable(hdev, hub->descriptor); + + hub_activate(hub, HUB_INIT); return 0; fail: @@ -901,29 +1642,47 @@ static unsigned highspeed_hubs; static void hub_disconnect(struct usb_interface *intf) { - struct usb_hub *hub = usb_get_intfdata (intf); + struct usb_hub *hub = usb_get_intfdata(intf); + struct usb_device *hdev = interface_to_usbdev(intf); + int port1; /* Take the hub off the event list and don't let it be added again */ spin_lock_irq(&hub_event_lock); - list_del_init(&hub->event_list); + if (!list_empty(&hub->event_list)) { + list_del_init(&hub->event_list); + usb_autopm_put_interface_no_suspend(intf); + } hub->disconnected = 1; spin_unlock_irq(&hub_event_lock); /* Disconnect all children and quiesce the hub */ hub->error = 0; - hub_pre_reset(intf); + hub_quiesce(hub, HUB_DISCONNECT); + + mutex_lock(&usb_port_peer_mutex); + + /* Avoid races with recursively_mark_NOTATTACHED() */ + spin_lock_irq(&device_state_lock); + port1 = hdev->maxchild; + hdev->maxchild = 0; + usb_set_intfdata(intf, NULL); + spin_unlock_irq(&device_state_lock); + + for (; port1 > 0; --port1) + usb_hub_remove_port_device(hub, port1); - usb_set_intfdata (intf, NULL); + mutex_unlock(&usb_port_peer_mutex); if (hub->hdev->speed == USB_SPEED_HIGH) highspeed_hubs--; usb_free_urb(hub->urb); + kfree(hub->ports); kfree(hub->descriptor); kfree(hub->status); - usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer, - hub->buffer_dma); + kfree(hub->buffer); + pm_suspend_ignore_children(&intf->dev, false); kref_put(&hub->kref, hub_release); } @@ -937,6 +1696,61 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) desc = intf->cur_altsetting; hdev = interface_to_usbdev(intf); + /* + * Set default autosuspend delay as 0 to speedup bus suspend, + * based on the below considerations: + * + * - Unlike other drivers, the hub driver does not rely on the + * autosuspend delay to provide enough time to handle a wakeup + * event, and the submitted status URB is just to check future + * change on hub downstream ports, so it is safe to do it. + * + * - The patch might cause one or more auto supend/resume for + * below very rare devices when they are plugged into hub + * first time: + * + * devices having trouble initializing, and disconnect + * themselves from the bus and then reconnect a second + * or so later + * + * devices just for downloading firmware, and disconnects + * themselves after completing it + * + * For these quite rare devices, their drivers may change the + * autosuspend delay of their parent hub in the probe() to one + * appropriate value to avoid the subtle problem if someone + * does care it. + * + * - The patch may cause one or more auto suspend/resume on + * hub during running 'lsusb', but it is probably too + * infrequent to worry about. + * + * - Change autosuspend delay of hub can avoid unnecessary auto + * suspend timer for hub, also may decrease power consumption + * of USB bus. + */ + pm_runtime_set_autosuspend_delay(&hdev->dev, 0); + + /* + * Hubs have proper suspend/resume support, except for root hubs + * where the controller driver doesn't have bus_suspend and + * bus_resume methods. + */ + if (hdev->parent) { /* normal device */ + usb_enable_autosuspend(hdev); + } else { /* root hub */ + const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver; + + if (drv->bus_suspend && drv->bus_resume) + usb_enable_autosuspend(hdev); + } + + if (hdev->level == MAX_TOPO_LEVEL) { + dev_err(&intf->dev, + "Unsupported bus topology: hub nested too deep\n"); + return -E2BIG; + } + #ifdef CONFIG_USB_OTG_BLACKLIST_HUB if (hdev->parent) { dev_warn(&intf->dev, "ignoring external hub\n"); @@ -977,14 +1791,19 @@ descriptor_error: hub->intfdev = &intf->dev; hub->hdev = hdev; INIT_DELAYED_WORK(&hub->leds, led_work); + INIT_DELAYED_WORK(&hub->init_work, NULL); usb_get_intf(intf); usb_set_intfdata (intf, hub); intf->needs_remote_wakeup = 1; + pm_suspend_ignore_children(&intf->dev, true); if (hdev->speed == USB_SPEED_HIGH) highspeed_hubs++; + if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND) + hub->quirk_check_port_auto_suspend = 1; + if (hub_configure(hub, endpoint) >= 0) return 0; @@ -996,6 +1815,7 @@ static int hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) { struct usb_device *hdev = interface_to_usbdev (intf); + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); /* assert ifno == 0 (part of hub spec) */ switch (code) { @@ -1009,11 +1829,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) else { info->nports = hdev->maxchild; for (i = 0; i < info->nports; i++) { - if (hdev->children[i] == NULL) + if (hub->ports[i]->child == NULL) info->port[i] = 0; else info->port[i] = - hdev->children[i]->devnum; + hub->ports[i]->child->devnum; } } spin_unlock_irq(&device_state_lock); @@ -1026,19 +1846,94 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) } } +/* + * Allow user programs to claim ports on a hub. When a device is attached + * to one of these "claimed" ports, the program will "own" the device. + */ +static int find_port_owner(struct usb_device *hdev, unsigned port1, + struct usb_dev_state ***ppowner) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + + if (hdev->state == USB_STATE_NOTATTACHED) + return -ENODEV; + if (port1 == 0 || port1 > hdev->maxchild) + return -EINVAL; + + /* Devices not managed by the hub driver + * will always have maxchild equal to 0. + */ + *ppowner = &(hub->ports[port1 - 1]->port_owner); + return 0; +} + +/* In the following three functions, the caller must hold hdev's lock */ +int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, + struct usb_dev_state *owner) +{ + int rc; + struct usb_dev_state **powner; + + rc = find_port_owner(hdev, port1, &powner); + if (rc) + return rc; + if (*powner) + return -EBUSY; + *powner = owner; + return rc; +} +EXPORT_SYMBOL_GPL(usb_hub_claim_port); + +int usb_hub_release_port(struct usb_device *hdev, unsigned port1, + struct usb_dev_state *owner) +{ + int rc; + struct usb_dev_state **powner; + + rc = find_port_owner(hdev, port1, &powner); + if (rc) + return rc; + if (*powner != owner) + return -ENOENT; + *powner = NULL; + return rc; +} +EXPORT_SYMBOL_GPL(usb_hub_release_port); + +void usb_hub_release_all_ports(struct usb_device *hdev, struct usb_dev_state *owner) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + int n; + + for (n = 0; n < hdev->maxchild; n++) { + if (hub->ports[n]->port_owner == owner) + hub->ports[n]->port_owner = NULL; + } + +} + +/* The caller must hold udev's lock */ +bool usb_device_is_owned(struct usb_device *udev) +{ + struct usb_hub *hub; + + if (udev->state == USB_STATE_NOTATTACHED || !udev->parent) + return false; + hub = usb_hub_to_struct_hub(udev->parent); + return !!hub->ports[udev->portnum - 1]->port_owner; +} static void recursively_mark_NOTATTACHED(struct usb_device *udev) { + struct usb_hub *hub = usb_hub_to_struct_hub(udev); int i; for (i = 0; i < udev->maxchild; ++i) { - if (udev->children[i]) - recursively_mark_NOTATTACHED(udev->children[i]); + if (hub->ports[i]->child) + recursively_mark_NOTATTACHED(hub->ports[i]->child); } - if (udev->state == USB_STATE_SUSPENDED) { - udev->discon_suspended = 1; + if (udev->state == USB_STATE_SUSPENDED) udev->active_duration -= jiffies; - } udev->state = USB_STATE_NOTATTACHED; } @@ -1067,6 +1962,7 @@ void usb_set_device_state(struct usb_device *udev, enum usb_device_state new_state) { unsigned long flags; + int wakeup = -1; spin_lock_irqsave(&device_state_lock, flags); if (udev->state == USB_STATE_NOTATTACHED) @@ -1081,11 +1977,10 @@ void usb_set_device_state(struct usb_device *udev, || new_state == USB_STATE_SUSPENDED) ; /* No change to wakeup settings */ else if (new_state == USB_STATE_CONFIGURED) - device_init_wakeup(&udev->dev, - (udev->actconfig->desc.bmAttributes - & USB_CONFIG_ATT_WAKEUP)); + wakeup = udev->actconfig->desc.bmAttributes + & USB_CONFIG_ATT_WAKEUP; else - device_init_wakeup(&udev->dev, 0); + wakeup = 0; } if (udev->state == USB_STATE_SUSPENDED && new_state != USB_STATE_SUSPENDED) @@ -1097,30 +1992,66 @@ void usb_set_device_state(struct usb_device *udev, } else recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); + if (wakeup >= 0) + device_set_wakeup_capable(&udev->dev, wakeup); } +EXPORT_SYMBOL_GPL(usb_set_device_state); -static void choose_address(struct usb_device *udev) +/* + * Choose a device number. + * + * Device numbers are used as filenames in usbfs. On USB-1.1 and + * USB-2.0 buses they are also used as device addresses, however on + * USB-3.0 buses the address is assigned by the controller hardware + * and it usually is not the same as the device number. + * + * WUSB devices are simple: they have no hubs behind, so the mapping + * device <-> virtual port number becomes 1:1. Why? to simplify the + * life of the device connection logic in + * drivers/usb/wusbcore/devconnect.c. When we do the initial secret + * handshake we need to assign a temporary address in the unauthorized + * space. For simplicity we use the first virtual port number found to + * be free [drivers/usb/wusbcore/devconnect.c:wusbhc_devconnect_ack()] + * and that becomes it's address [X < 128] or its unauthorized address + * [X | 0x80]. + * + * We add 1 as an offset to the one-based USB-stack port number + * (zero-based wusb virtual port index) for two reasons: (a) dev addr + * 0 is reserved by USB for default address; (b) Linux's USB stack + * uses always #1 for the root hub of the controller. So USB stack's + * port #1, which is wusb virtual-port #0 has address #2. + * + * Devices connected under xHCI are not as simple. The host controller + * supports virtualization, so the hardware assigns device addresses and + * the HCD must setup data structures before issuing a set address + * command to the hardware. + */ +static void choose_devnum(struct usb_device *udev) { int devnum; struct usb_bus *bus = udev->bus; /* If khubd ever becomes multithreaded, this will need a lock */ - - /* Try to allocate the next devnum beginning at bus->devnum_next. */ - devnum = find_next_zero_bit(bus->devmap.devicemap, 128, - bus->devnum_next); - if (devnum >= 128) - devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1); - - bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1); - + if (udev->wusb) { + devnum = udev->portnum + 1; + BUG_ON(test_bit(devnum, bus->devmap.devicemap)); + } else { + /* Try to allocate the next devnum beginning at + * bus->devnum_next. */ + devnum = find_next_zero_bit(bus->devmap.devicemap, 128, + bus->devnum_next); + if (devnum >= 128) + devnum = find_next_zero_bit(bus->devmap.devicemap, + 128, 1); + bus->devnum_next = (devnum >= 127 ? 1 : devnum + 1); + } if (devnum < 128) { set_bit(devnum, bus->devmap.devicemap); udev->devnum = devnum; } } -static void release_address(struct usb_device *udev) +static void release_devnum(struct usb_device *udev) { if (udev->devnum > 0) { clear_bit(udev->devnum, udev->bus->devmap.devicemap); @@ -1128,29 +2059,33 @@ static void release_address(struct usb_device *udev) } } -#ifdef CONFIG_USB_SUSPEND +static void update_devnum(struct usb_device *udev, int devnum) +{ + /* The address for a WUSB device is managed by wusbcore. */ + if (!udev->wusb) + udev->devnum = devnum; +} -static void usb_stop_pm(struct usb_device *udev) +static void hub_free_dev(struct usb_device *udev) { - /* Synchronize with the ksuspend thread to prevent any more - * autosuspend requests from being submitted, and decrement - * the parent's count of unsuspended children. - */ - usb_pm_lock(udev); - if (udev->parent && !udev->discon_suspended) - usb_autosuspend_device(udev->parent); - usb_pm_unlock(udev); + struct usb_hcd *hcd = bus_to_hcd(udev->bus); - /* Stop any autosuspend requests already submitted */ - cancel_rearming_delayed_work(&udev->autosuspend); + /* Root hubs aren't real devices, so don't free HCD resources */ + if (hcd->driver->free_dev && udev->parent) + hcd->driver->free_dev(hcd, udev); } -#else - -static inline void usb_stop_pm(struct usb_device *udev) -{ } +static void hub_disconnect_children(struct usb_device *udev) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(udev); + int i; -#endif + /* Free up all the children before we remove this device */ + for (i = 0; i < udev->maxchild; i++) { + if (hub->ports[i]->child) + usb_disconnect(&hub->ports[i]->child); + } +} /** * usb_disconnect - disconnect a device (usbcore-internal) @@ -1160,8 +2095,8 @@ static inline void usb_stop_pm(struct usb_device *udev) * Something got disconnected. Get rid of it and all of its children. * * If *pdev is a normal device then the parent hub must already be locked. - * If *pdev is a root hub then this routine will acquire the - * usb_bus_list_lock on behalf of the caller. + * If *pdev is a root hub then the caller must hold the usb_bus_list_lock, + * which protects the set of root hubs as well as the list of buses. * * Only hub drivers (including virtual root hub drivers for host * controllers) should ever call this. @@ -1170,28 +2105,22 @@ static inline void usb_stop_pm(struct usb_device *udev) */ void usb_disconnect(struct usb_device **pdev) { - struct usb_device *udev = *pdev; - int i; - - if (!udev) { - pr_debug ("%s nodev\n", __FUNCTION__); - return; - } + struct usb_port *port_dev = NULL; + struct usb_device *udev = *pdev; + struct usb_hub *hub; + int port1; /* mark the device as inactive, so any further urb submissions for * this device (and any of its children) will fail immediately. - * this quiesces everyting except pending urbs. + * this quiesces everything except pending urbs. */ usb_set_device_state(udev, USB_STATE_NOTATTACHED); - dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum); + dev_info(&udev->dev, "USB disconnect, device number %d\n", + udev->devnum); usb_lock_device(udev); - /* Free up all the children before we remove this device */ - for (i = 0; i < USB_MAXCHILDREN; i++) { - if (udev->children[i]) - usb_disconnect(&udev->children[i]); - } + hub_disconnect_children(udev); /* deallocate hcd/hardware state ... nuking all pending urbs and * cleaning up all state associated with the current configuration @@ -1199,26 +2128,47 @@ void usb_disconnect(struct usb_device **pdev) */ dev_dbg (&udev->dev, "unregistering device\n"); usb_disable_device(udev, 0); + usb_hcd_synchronize_unlinks(udev); + + if (udev->parent) { + port1 = udev->portnum; + hub = usb_hub_to_struct_hub(udev->parent); + port_dev = hub->ports[port1 - 1]; + + sysfs_remove_link(&udev->dev.kobj, "port"); + sysfs_remove_link(&port_dev->dev.kobj, "device"); + /* + * As usb_port_runtime_resume() de-references udev, make + * sure no resumes occur during removal + */ + if (!test_and_set_bit(port1, hub->child_usage_bits)) + pm_runtime_get_sync(&port_dev->dev); + } + + usb_remove_ep_devs(&udev->ep0); usb_unlock_device(udev); /* Unregister the device. The device driver is responsible - * for removing the device files from usbfs and sysfs and for - * de-configuring the device. + * for de-configuring the device and invoking the remove-device + * notifier chain (used by usbfs and possibly others). */ device_del(&udev->dev); /* Free the device number and delete the parent's children[] * (or root_hub) pointer. */ - release_address(udev); + release_devnum(udev); /* Avoid races with recursively_mark_NOTATTACHED() */ spin_lock_irq(&device_state_lock); *pdev = NULL; spin_unlock_irq(&device_state_lock); - usb_stop_pm(udev); + if (port_dev && test_and_clear_bit(port1, hub->child_usage_bits)) + pm_runtime_put(&port_dev->dev); + + hub_free_dev(udev); put_device(&udev->dev); } @@ -1228,7 +2178,7 @@ static void show_string(struct usb_device *udev, char *id, char *string) { if (!string) return; - dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string); + dev_info(&udev->dev, "%s: %s\n", id, string); } static void announce_device(struct usb_device *udev) @@ -1236,8 +2186,8 @@ static void announce_device(struct usb_device *udev) dev_info(&udev->dev, "New USB device found, idVendor=%04x, idProduct=%04x\n", le16_to_cpu(udev->descriptor.idVendor), le16_to_cpu(udev->descriptor.idProduct)); - dev_info(&udev->dev, "New USB device strings: Mfr=%d, Product=%d, " - "SerialNumber=%d\n", + dev_info(&udev->dev, + "New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", udev->descriptor.iManufacturer, udev->descriptor.iProduct, udev->descriptor.iSerialNumber); @@ -1254,12 +2204,14 @@ static inline void announce_device(struct usb_device *udev) { } #endif /** - * usb_configure_device_otg - FIXME (usbcore-internal) + * usb_enumerate_device_otg - FIXME (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * - * Do configuration for On-The-Go devices + * Finish enumeration for On-The-Go devices + * + * Return: 0 if successful. A negative error code otherwise. */ -static int usb_configure_device_otg(struct usb_device *udev) +static int usb_enumerate_device_otg(struct usb_device *udev) { int err = 0; @@ -1272,7 +2224,7 @@ static int usb_configure_device_otg(struct usb_device *udev) if (!udev->bus->is_b_host && udev->config && udev->parent == udev->bus->root_hub) { - struct usb_otg_descriptor *desc = 0; + struct usb_otg_descriptor *desc = NULL; struct usb_bus *bus = udev->bus; /* descriptor may appear anywhere in config */ @@ -1302,7 +2254,7 @@ static int usb_configure_device_otg(struct usb_device *udev) * customize to match your product. */ dev_info(&udev->dev, - "can't set HNP mode; %d\n", + "can't set HNP mode: %d\n", err); bus->b_hnp_enable = 0; } @@ -1316,7 +2268,7 @@ static int usb_configure_device_otg(struct usb_device *udev) * (Includes HNP test device.) */ if (udev->bus->b_hnp_enable || udev->bus->is_b_host) { - err = usb_port_suspend(udev); + err = usb_port_suspend(udev, PMSG_SUSPEND); if (err < 0) dev_dbg(&udev->dev, "HNP fail, %d\n", err); } @@ -1330,7 +2282,7 @@ fail: /** - * usb_configure_device - Detect and probe device intfs/otg (usbcore-internal) + * usb_enumerate_device - Read device configs/intfs/otg (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * * This is only called by usb_new_device() and usb_authorize_device() @@ -1340,76 +2292,161 @@ fail: * If the device is WUSB and not authorized, we don't attempt to read * the string descriptors, as they will be errored out by the device * until it has been authorized. + * + * Return: 0 if successful. A negative error code otherwise. */ -static int usb_configure_device(struct usb_device *udev) +static int usb_enumerate_device(struct usb_device *udev) { int err; if (udev->config == NULL) { err = usb_get_configuration(udev); if (err < 0) { - dev_err(&udev->dev, "can't read configurations, error %d\n", - err); - goto fail; + if (err != -ENODEV) + dev_err(&udev->dev, "can't read configurations, error %d\n", + err); + return err; } } - if (udev->wusb == 1 && udev->authorized == 0) { - udev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); - udev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); - udev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); + + /* read the standard strings and cache them if present */ + udev->product = usb_cache_string(udev, udev->descriptor.iProduct); + udev->manufacturer = usb_cache_string(udev, + udev->descriptor.iManufacturer); + udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); + + err = usb_enumerate_device_otg(udev); + if (err < 0) + return err; + + usb_detect_interface_quirks(udev); + + return 0; +} + +static void set_usb_port_removable(struct usb_device *udev) +{ + struct usb_device *hdev = udev->parent; + struct usb_hub *hub; + u8 port = udev->portnum; + u16 wHubCharacteristics; + bool removable = true; + + if (!hdev) + return; + + hub = usb_hub_to_struct_hub(udev->parent); + + wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); + + if (!(wHubCharacteristics & HUB_CHAR_COMPOUND)) + return; + + if (hub_is_superspeed(hdev)) { + if (le16_to_cpu(hub->descriptor->u.ss.DeviceRemovable) + & (1 << port)) + removable = false; + } else { + if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8))) + removable = false; } - else { - /* read the standard strings and cache them if present */ - udev->product = usb_cache_string(udev, udev->descriptor.iProduct); - udev->manufacturer = usb_cache_string(udev, - udev->descriptor.iManufacturer); - udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); + + if (removable) + udev->removable = USB_DEVICE_REMOVABLE; + else + udev->removable = USB_DEVICE_FIXED; + + /* + * Platform firmware may have populated an alternative value for + * removable. If the parent port has a known connect_type use + * that instead. + */ + switch (hub->ports[udev->portnum - 1]->connect_type) { + case USB_PORT_CONNECT_TYPE_HOT_PLUG: + udev->removable = USB_DEVICE_REMOVABLE; + break; + case USB_PORT_CONNECT_TYPE_HARD_WIRED: + udev->removable = USB_DEVICE_FIXED; + break; + default: /* use what was set above */ + break; } - err = usb_configure_device_otg(udev); -fail: - return err; } - /** * usb_new_device - perform initial device setup (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * - * This is called with devices which have been enumerated, but not yet - * configured. The device descriptor is available, but not descriptors + * This is called with devices which have been detected but not fully + * enumerated. The device descriptor is available, but not descriptors * for any device configuration. The caller must have locked either * the parent hub (if udev is a normal device) or else the * usb_bus_list_lock (if udev is a root hub). The parent's pointer to * udev has already been installed, but udev is not yet visible through * sysfs or other filesystem code. * - * It will return if the device is configured properly or not. Zero if - * the interface was registered with the driver core; else a negative - * errno value. - * * This call is synchronous, and may not be used in an interrupt context. * * Only the hub driver or root-hub registrar should ever call this. + * + * Return: Whether the device is configured properly or not. Zero if the + * interface was registered with the driver core; else a negative errno + * value. + * */ int usb_new_device(struct usb_device *udev) { int err; - usb_detect_quirks(udev); /* Determine quirks */ - err = usb_configure_device(udev); /* detect & probe dev/intfs */ + if (udev->parent) { + /* Initialize non-root-hub device wakeup to disabled; + * device (un)configuration controls wakeup capable + * sysfs power/wakeup controls wakeup enabled/disabled + */ + device_init_wakeup(&udev->dev, 0); + } + + /* Tell the runtime-PM framework the device is active */ + pm_runtime_set_active(&udev->dev); + pm_runtime_get_noresume(&udev->dev); + pm_runtime_use_autosuspend(&udev->dev); + pm_runtime_enable(&udev->dev); + + /* By default, forbid autosuspend for all devices. It will be + * allowed for hubs during binding. + */ + usb_disable_autosuspend(udev); + + err = usb_enumerate_device(udev); /* Read descriptors */ if (err < 0) goto fail; + dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n", + udev->devnum, udev->bus->busnum, + (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); /* export the usbdev device-node for libusb */ udev->dev.devt = MKDEV(USB_DEVICE_MAJOR, (((udev->bus->busnum-1) * 128) + (udev->devnum-1))); - /* Increment the parent's count of unsuspended children */ + /* Tell the world! */ + announce_device(udev); + + if (udev->serial) + add_device_randomness(udev->serial, strlen(udev->serial)); + if (udev->product) + add_device_randomness(udev->product, strlen(udev->product)); + if (udev->manufacturer) + add_device_randomness(udev->manufacturer, + strlen(udev->manufacturer)); + + device_enable_async_suspend(&udev->dev); + + /* check whether the hub or firmware marks this port as non-removable */ if (udev->parent) - usb_autoresume_device(udev->parent); + set_usb_port_removable(udev); /* Register the device. The device driver is responsible - * for adding the device files to sysfs and for configuring - * the device. + * for configuring the device and invoking the add-device + * notifier chain (used by usbfs and possibly others). */ err = device_add(&udev->dev); if (err) { @@ -1417,12 +2454,37 @@ int usb_new_device(struct usb_device *udev) goto fail; } - /* Tell the world! */ - announce_device(udev); + /* Create link files between child device and usb port device. */ + if (udev->parent) { + struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); + int port1 = udev->portnum; + struct usb_port *port_dev = hub->ports[port1 - 1]; + + err = sysfs_create_link(&udev->dev.kobj, + &port_dev->dev.kobj, "port"); + if (err) + goto fail; + + err = sysfs_create_link(&port_dev->dev.kobj, + &udev->dev.kobj, "device"); + if (err) { + sysfs_remove_link(&udev->dev.kobj, "port"); + goto fail; + } + + if (!test_and_set_bit(port1, hub->child_usage_bits)) + pm_runtime_get_sync(&port_dev->dev); + } + + (void) usb_create_ep_devs(&udev->dev, &udev->ep0, udev); + usb_mark_last_busy(udev); + pm_runtime_put_sync_autosuspend(&udev->dev); return err; fail: usb_set_device_state(udev, USB_STATE_NOTATTACHED); + pm_runtime_disable(&udev->dev); + pm_runtime_set_suspended(&udev->dev); return err; } @@ -1436,24 +2498,18 @@ fail: * * We share a lock (that we have) with device_del(), so we need to * defer its call. + * + * Return: 0. */ int usb_deauthorize_device(struct usb_device *usb_dev) { - unsigned cnt; usb_lock_device(usb_dev); if (usb_dev->authorized == 0) goto out_unauthorized; + usb_dev->authorized = 0; usb_set_configuration(usb_dev, -1); - usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); - usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); - usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->config); - usb_dev->config = NULL; - for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++) - kfree(usb_dev->rawdescriptors[cnt]); - usb_dev->descriptor.bNumConfigurations = 0; - kfree(usb_dev->rawdescriptors); + out_unauthorized: usb_unlock_device(usb_dev); return 0; @@ -1463,15 +2519,11 @@ out_unauthorized: int usb_authorize_device(struct usb_device *usb_dev) { int result = 0, c; + usb_lock_device(usb_dev); if (usb_dev->authorized == 1) goto out_authorized; - kfree(usb_dev->product); - usb_dev->product = NULL; - kfree(usb_dev->manufacturer); - usb_dev->manufacturer = NULL; - kfree(usb_dev->serial); - usb_dev->serial = NULL; + result = usb_autoresume_device(usb_dev); if (result < 0) { dev_err(&usb_dev->dev, @@ -1484,10 +2536,8 @@ int usb_authorize_device(struct usb_device *usb_dev) "authorization: %d\n", result); goto error_device_descriptor; } + usb_dev->authorized = 1; - result = usb_configure_device(usb_dev); - if (result < 0) - goto error_configure; /* Choose and set the configuration. This registers the interfaces * with the driver core and lets interface drivers bind to them. */ @@ -1502,37 +2552,16 @@ int usb_authorize_device(struct usb_device *usb_dev) } } dev_info(&usb_dev->dev, "authorized to connect\n"); -error_configure: + error_device_descriptor: + usb_autosuspend_device(usb_dev); error_autoresume: out_authorized: - usb_unlock_device(usb_dev); // complements locktree + usb_unlock_device(usb_dev); /* complements locktree */ return result; } -static int hub_port_status(struct usb_hub *hub, int port1, - u16 *status, u16 *change) -{ - int ret; - - mutex_lock(&hub->status_mutex); - ret = get_port_status(hub->hdev, port1, &hub->status->port); - if (ret < 4) { - dev_err (hub->intfdev, - "%s failed (err = %d)\n", __FUNCTION__, ret); - if (ret >= 0) - ret = -EIO; - } else { - *status = le16_to_cpu(hub->status->port.wPortStatus); - *change = le16_to_cpu(hub->status->port.wPortChange); - ret = 0; - } - mutex_unlock(&hub->status_mutex); - return ret; -} - - /* Returns 1 if @hub is a WUSB root hub, 0 otherwise */ static unsigned hub_is_wusb(struct usb_hub *hub) { @@ -1548,15 +2577,46 @@ static unsigned hub_is_wusb(struct usb_hub *hub) #define SET_ADDRESS_TRIES 2 #define GET_DESCRIPTOR_TRIES 2 #define SET_CONFIG_TRIES (2 * (use_both_schemes + 1)) -#define USE_NEW_SCHEME(i) ((i) / 2 == old_scheme_first) +#define USE_NEW_SCHEME(i) ((i) / 2 == (int)old_scheme_first) #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ #define HUB_SHORT_RESET_TIME 10 +#define HUB_BH_RESET_TIME 50 #define HUB_LONG_RESET_TIME 200 -#define HUB_RESET_TIMEOUT 500 +#define HUB_RESET_TIMEOUT 800 + +/* + * "New scheme" enumeration causes an extra state transition to be + * exposed to an xhci host and causes USB3 devices to receive control + * commands in the default state. This has been seen to cause + * enumeration failures, so disable this enumeration scheme for USB3 + * devices. + */ +static bool use_new_scheme(struct usb_device *udev, int retry) +{ + if (udev->speed == USB_SPEED_SUPER) + return false; + + return USE_NEW_SCHEME(retry); +} + +static int hub_port_reset(struct usb_hub *hub, int port1, + struct usb_device *udev, unsigned int delay, bool warm); + +/* Is a USB 3.0 port in the Inactive or Compliance Mode state? + * Port worm reset is required to recover + */ +static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus) +{ + return hub_is_superspeed(hub->hdev) && + (((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_SS_INACTIVE) || + ((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_COMP_MOD)) ; +} static int hub_port_wait_reset(struct usb_hub *hub, int port1, - struct usb_device *udev, unsigned int delay) + struct usb_device *udev, unsigned int delay, bool warm) { int delay_time, ret; u16 portstatus; @@ -1573,102 +2633,385 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if (ret < 0) return ret; - /* Device went away? */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return -ENOTCONN; - - /* bomb out completely if the connection bounced */ - if ((portchange & USB_PORT_STAT_C_CONNECTION)) - return -ENOTCONN; - - /* if we`ve finished resetting, then break out of the loop */ - if (!(portstatus & USB_PORT_STAT_RESET) && - (portstatus & USB_PORT_STAT_ENABLE)) { - if (hub_is_wusb(hub)) - udev->speed = USB_SPEED_VARIABLE; - else if (portstatus & USB_PORT_STAT_HIGH_SPEED) - udev->speed = USB_SPEED_HIGH; - else if (portstatus & USB_PORT_STAT_LOW_SPEED) - udev->speed = USB_SPEED_LOW; - else - udev->speed = USB_SPEED_FULL; - return 0; - } + /* The port state is unknown until the reset completes. */ + if (!(portstatus & USB_PORT_STAT_RESET)) + break; /* switch to the long delay after two short delay failures */ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; - dev_dbg (hub->intfdev, - "port %d not reset yet, waiting %dms\n", - port1, delay); + dev_dbg(&hub->ports[port1 - 1]->dev, + "not %sreset yet, waiting %dms\n", + warm ? "warm " : "", delay); } - return -EBUSY; + if ((portstatus & USB_PORT_STAT_RESET)) + return -EBUSY; + + if (hub_port_warm_reset_required(hub, portstatus)) + return -ENOTCONN; + + /* Device went away? */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return -ENOTCONN; + + /* bomb out completely if the connection bounced. A USB 3.0 + * connection may bounce if multiple warm resets were issued, + * but the device may have successfully re-connected. Ignore it. + */ + if (!hub_is_superspeed(hub->hdev) && + (portchange & USB_PORT_STAT_C_CONNECTION)) + return -ENOTCONN; + + if (!(portstatus & USB_PORT_STAT_ENABLE)) + return -EBUSY; + + if (!udev) + return 0; + + if (hub_is_wusb(hub)) + udev->speed = USB_SPEED_WIRELESS; + else if (hub_is_superspeed(hub->hdev)) + udev->speed = USB_SPEED_SUPER; + else if (portstatus & USB_PORT_STAT_HIGH_SPEED) + udev->speed = USB_SPEED_HIGH; + else if (portstatus & USB_PORT_STAT_LOW_SPEED) + udev->speed = USB_SPEED_LOW; + else + udev->speed = USB_SPEED_FULL; + return 0; } +static void hub_port_finish_reset(struct usb_hub *hub, int port1, + struct usb_device *udev, int *status) +{ + switch (*status) { + case 0: + /* TRSTRCY = 10 ms; plus some extra */ + msleep(10 + 40); + if (udev) { + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + update_devnum(udev, 0); + /* The xHC may think the device is already reset, + * so ignore the status. + */ + if (hcd->driver->reset_device) + hcd->driver->reset_device(hcd, udev); + } + /* FALL THROUGH */ + case -ENOTCONN: + case -ENODEV: + usb_clear_port_feature(hub->hdev, + port1, USB_PORT_FEAT_C_RESET); + if (hub_is_superspeed(hub->hdev)) { + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_BH_PORT_RESET); + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_PORT_LINK_STATE); + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + } + if (udev) + usb_set_device_state(udev, *status + ? USB_STATE_NOTATTACHED + : USB_STATE_DEFAULT); + break; + } +} + +/* Handle port reset and port warm(BH) reset (for USB3 protocol ports) */ static int hub_port_reset(struct usb_hub *hub, int port1, - struct usb_device *udev, unsigned int delay) + struct usb_device *udev, unsigned int delay, bool warm) { int i, status; + u16 portchange, portstatus; + struct usb_port *port_dev = hub->ports[port1 - 1]; - /* Block EHCI CF initialization during the port reset. - * Some companion controllers don't like it when they mix. - */ - down_read(&ehci_cf_port_reset_rwsem); + if (!hub_is_superspeed(hub->hdev)) { + if (warm) { + dev_err(hub->intfdev, "only USB3 hub support " + "warm reset\n"); + return -EINVAL; + } + /* Block EHCI CF initialization during the port reset. + * Some companion controllers don't like it when they mix. + */ + down_read(&ehci_cf_port_reset_rwsem); + } else if (!warm) { + /* + * If the caller hasn't explicitly requested a warm reset, + * double check and see if one is needed. + */ + status = hub_port_status(hub, port1, + &portstatus, &portchange); + if (status < 0) + goto done; + + if (hub_port_warm_reset_required(hub, portstatus)) + warm = true; + } /* Reset the port */ for (i = 0; i < PORT_RESET_TRIES; i++) { - status = set_port_feature(hub->hdev, - port1, USB_PORT_FEAT_RESET); - if (status) - dev_err(hub->intfdev, - "cannot reset port %d (err = %d)\n", - port1, status); - else { - status = hub_port_wait_reset(hub, port1, udev, delay); - if (status && status != -ENOTCONN) + status = set_port_feature(hub->hdev, port1, (warm ? + USB_PORT_FEAT_BH_PORT_RESET : + USB_PORT_FEAT_RESET)); + if (status == -ENODEV) { + ; /* The hub is gone */ + } else if (status) { + dev_err(&port_dev->dev, + "cannot %sreset (err = %d)\n", + warm ? "warm " : "", status); + } else { + status = hub_port_wait_reset(hub, port1, udev, delay, + warm); + if (status && status != -ENOTCONN && status != -ENODEV) dev_dbg(hub->intfdev, "port_wait_reset: err = %d\n", status); } - /* return on disconnect or reset */ - switch (status) { - case 0: - /* TRSTRCY = 10 ms; plus some extra */ - msleep(10 + 40); - udev->devnum = 0; /* Device now at address 0 */ - /* FALL THROUGH */ - case -ENOTCONN: - case -ENODEV: - clear_port_feature(hub->hdev, - port1, USB_PORT_FEAT_C_RESET); - /* FIXME need disconnect() for NOTATTACHED device */ - usb_set_device_state(udev, status - ? USB_STATE_NOTATTACHED - : USB_STATE_DEFAULT); - goto done; + /* Check for disconnect or reset */ + if (status == 0 || status == -ENOTCONN || status == -ENODEV) { + hub_port_finish_reset(hub, port1, udev, &status); + + if (!hub_is_superspeed(hub->hdev)) + goto done; + + /* + * If a USB 3.0 device migrates from reset to an error + * state, re-issue the warm reset. + */ + if (hub_port_status(hub, port1, + &portstatus, &portchange) < 0) + goto done; + + if (!hub_port_warm_reset_required(hub, portstatus)) + goto done; + + /* + * If the port is in SS.Inactive or Compliance Mode, the + * hot or warm reset failed. Try another warm reset. + */ + if (!warm) { + dev_dbg(&port_dev->dev, + "hot reset failed, warm reset\n"); + warm = true; + } } - dev_dbg (hub->intfdev, - "port %d not enabled, trying reset again...\n", - port1); + dev_dbg(&port_dev->dev, + "not enabled, trying %sreset again...\n", + warm ? "warm " : ""); delay = HUB_LONG_RESET_TIME; } - dev_err (hub->intfdev, - "Cannot enable port %i. Maybe the USB cable is bad?\n", - port1); + dev_err(&port_dev->dev, "Cannot enable. Maybe the USB cable is bad?\n"); + +done: + if (!hub_is_superspeed(hub->hdev)) + up_read(&ehci_cf_port_reset_rwsem); - done: - up_read(&ehci_cf_port_reset_rwsem); return status; } +/* Check if a port is power on */ +static int port_is_power_on(struct usb_hub *hub, unsigned portstatus) +{ + int ret = 0; + + if (hub_is_superspeed(hub->hdev)) { + if (portstatus & USB_SS_PORT_STAT_POWER) + ret = 1; + } else { + if (portstatus & USB_PORT_STAT_POWER) + ret = 1; + } + + return ret; +} + +static void usb_lock_port(struct usb_port *port_dev) + __acquires(&port_dev->status_lock) +{ + mutex_lock(&port_dev->status_lock); + __acquire(&port_dev->status_lock); +} + +static void usb_unlock_port(struct usb_port *port_dev) + __releases(&port_dev->status_lock) +{ + mutex_unlock(&port_dev->status_lock); + __release(&port_dev->status_lock); +} + #ifdef CONFIG_PM -#ifdef CONFIG_USB_SUSPEND +/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */ +static int port_is_suspended(struct usb_hub *hub, unsigned portstatus) +{ + int ret = 0; + + if (hub_is_superspeed(hub->hdev)) { + if ((portstatus & USB_PORT_STAT_LINK_STATE) + == USB_SS_PORT_LS_U3) + ret = 1; + } else { + if (portstatus & USB_PORT_STAT_SUSPEND) + ret = 1; + } + + return ret; +} + +/* Determine whether the device on a port is ready for a normal resume, + * is ready for a reset-resume, or should be disconnected. + */ +static int check_port_resume_type(struct usb_device *udev, + struct usb_hub *hub, int port1, + int status, unsigned portchange, unsigned portstatus) +{ + struct usb_port *port_dev = hub->ports[port1 - 1]; + + /* Is the device still present? */ + if (status || port_is_suspended(hub, portstatus) || + !port_is_power_on(hub, portstatus) || + !(portstatus & USB_PORT_STAT_CONNECTION)) { + if (status >= 0) + status = -ENODEV; + } + + /* Can't do a normal resume if the port isn't enabled, + * so try a reset-resume instead. + */ + else if (!(portstatus & USB_PORT_STAT_ENABLE) && !udev->reset_resume) { + if (udev->persist_enabled) + udev->reset_resume = 1; + else + status = -ENODEV; + } + + if (status) { + dev_dbg(&port_dev->dev, "status %04x.%04x after resume, %d\n", + portchange, portstatus, status); + } else if (udev->reset_resume) { + + /* Late port handoff can set status-change bits */ + if (portchange & USB_PORT_STAT_C_CONNECTION) + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + if (portchange & USB_PORT_STAT_C_ENABLE) + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_ENABLE); + } + + return status; +} + +int usb_disable_ltm(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + /* Check if the roothub and device supports LTM. */ + if (!usb_device_supports_ltm(hcd->self.root_hub) || + !usb_device_supports_ltm(udev)) + return 0; + + /* Clear Feature LTM Enable can only be sent if the device is + * configured. + */ + if (!udev->actconfig) + return 0; + + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_LTM_ENABLE, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} +EXPORT_SYMBOL_GPL(usb_disable_ltm); + +void usb_enable_ltm(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + /* Check if the roothub and device supports LTM. */ + if (!usb_device_supports_ltm(hcd->self.root_hub) || + !usb_device_supports_ltm(udev)) + return; + + /* Set Feature LTM Enable can only be sent if the device is + * configured. + */ + if (!udev->actconfig) + return; + + usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_LTM_ENABLE, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} +EXPORT_SYMBOL_GPL(usb_enable_ltm); + +/* + * usb_enable_remote_wakeup - enable remote wakeup for a device + * @udev: target device + * + * For USB-2 devices: Set the device's remote wakeup feature. + * + * For USB-3 devices: Assume there's only one function on the device and + * enable remote wake for the first interface. FIXME if the interface + * association descriptor shows there's more than one function. + */ +static int usb_enable_remote_wakeup(struct usb_device *udev) +{ + if (udev->speed < USB_SPEED_SUPER) + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + else + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, + USB_INTRF_FUNC_SUSPEND_RW | + USB_INTRF_FUNC_SUSPEND_LP, + NULL, 0, USB_CTRL_SET_TIMEOUT); +} + +/* + * usb_disable_remote_wakeup - disable remote wakeup for a device + * @udev: target device + * + * For USB-2 devices: Clear the device's remote wakeup feature. + * + * For USB-3 devices: Assume there's only one function on the device and + * disable remote wake for the first interface. FIXME if the interface + * association descriptor shows there's more than one function. + */ +static int usb_disable_remote_wakeup(struct usb_device *udev) +{ + if (udev->speed < USB_SPEED_SUPER) + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + else + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} + +/* Count of wakeup-enabled devices at or below udev */ +static unsigned wakeup_enabled_descendants(struct usb_device *udev) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(udev); + + return udev->do_remote_wakeup + + (hub ? hub->wakeup_enabled_descendants : 0); +} /* * usb_port_suspend - suspend a usb device's upstream port @@ -1710,19 +3053,23 @@ static int hub_port_reset(struct usb_hub *hub, int port1, * Linux (2.6) currently has NO mechanisms to initiate that: no khubd * timer, no SRP, no requests through sysfs. * - * If CONFIG_USB_SUSPEND isn't enabled, devices only really suspend when - * the root hub for their bus goes into global suspend ... so we don't - * (falsely) update the device power state to say it suspended. + * If Runtime PM isn't enabled or used, non-SuperSpeed devices may not get + * suspended until their bus goes into global suspend (i.e., the root + * hub is suspended). Nevertheless, we change @udev->state to + * USB_STATE_SUSPENDED as this is the device's "logical" state. The actual + * upstream port setting is stored in @udev->port_is_suspended. * * Returns 0 on success, else negative errno. */ -int usb_port_suspend(struct usb_device *udev) +int usb_port_suspend(struct usb_device *udev, pm_message_t msg) { - struct usb_hub *hub = hdev_to_hub(udev->parent); + struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); + struct usb_port *port_dev = hub->ports[udev->portnum - 1]; int port1 = udev->portnum; int status; + bool really_suspend = true; - // dev_dbg(hub->intfdev, "suspend port %d\n", port1); + usb_lock_port(port_dev); /* enable remote wakeup when appropriate; this lets the device * wake up the upstream hub (including maybe the root hub). @@ -1731,34 +3078,94 @@ int usb_port_suspend(struct usb_device *udev) * we don't explicitly enable it here. */ if (udev->do_remote_wakeup) { - status = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - if (status) + status = usb_enable_remote_wakeup(udev); + if (status) { dev_dbg(&udev->dev, "won't remote wakeup, status %d\n", status); + /* bail if autosuspend is requested */ + if (PMSG_IS_AUTO(msg)) + goto err_wakeup; + } + } + + /* disable USB2 hardware LPM */ + if (udev->usb2_hw_lpm_enabled == 1) + usb_set_usb2_hardware_lpm(udev, 0); + + if (usb_disable_ltm(udev)) { + dev_err(&udev->dev, "Failed to disable LTM before suspend\n."); + status = -ENOMEM; + if (PMSG_IS_AUTO(msg)) + goto err_ltm; + } + if (usb_unlocked_disable_lpm(udev)) { + dev_err(&udev->dev, "Failed to disable LPM before suspend\n."); + status = -ENOMEM; + if (PMSG_IS_AUTO(msg)) + goto err_lpm3; } /* see 7.1.7.6 */ - status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND); + if (hub_is_superspeed(hub->hdev)) + status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3); + + /* + * For system suspend, we do not need to enable the suspend feature + * on individual USB-2 ports. The devices will automatically go + * into suspend a few ms after the root hub stops sending packets. + * The USB 2.0 spec calls this "global suspend". + * + * However, many USB hubs have a bug: They don't relay wakeup requests + * from a downstream port if the port's suspend feature isn't on. + * Therefore we will turn on the suspend feature if udev or any of its + * descendants is enabled for remote wakeup. + */ + else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0) + status = set_port_feature(hub->hdev, port1, + USB_PORT_FEAT_SUSPEND); + else { + really_suspend = false; + status = 0; + } if (status) { - dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", - port1, status); - /* paranoia: "should not happen" */ - (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + dev_dbg(&port_dev->dev, "can't suspend, status %d\n", status); + + /* Try to enable USB3 LPM and LTM again */ + usb_unlocked_enable_lpm(udev); + err_lpm3: + usb_enable_ltm(udev); + err_ltm: + /* Try to enable USB2 hardware LPM again */ + if (udev->usb2_hw_lpm_capable == 1) + usb_set_usb2_hardware_lpm(udev, 1); + + if (udev->do_remote_wakeup) + (void) usb_disable_remote_wakeup(udev); + err_wakeup: + + /* System sleep transitions should never fail */ + if (!PMSG_IS_AUTO(msg)) + status = 0; } else { - /* device has up to 10 msec to fully suspend */ - dev_dbg(&udev->dev, "usb %ssuspend\n", - udev->auto_pm ? "auto-" : ""); + dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n", + (PMSG_IS_AUTO(msg) ? "auto-" : ""), + udev->do_remote_wakeup); + if (really_suspend) { + udev->port_is_suspended = 1; + + /* device has up to 10 msec to fully suspend */ + msleep(10); + } usb_set_device_state(udev, USB_STATE_SUSPENDED); - msleep(10); } + + if (status == 0 && !udev->do_remote_wakeup && udev->persist_enabled + && test_and_clear_bit(port1, hub->child_usage_bits)) + pm_runtime_put_sync(&port_dev->dev); + + usb_mark_last_busy(hub->hdev); + + usb_unlock_port(port_dev); return status; } @@ -1776,11 +3183,11 @@ int usb_port_suspend(struct usb_device *udev) static int finish_port_resume(struct usb_device *udev) { int status = 0; - u16 devstatus; + u16 devstatus = 0; /* caller owns the udev device lock */ - dev_dbg(&udev->dev, "finish %sresume\n", - udev->reset_resume ? "reset-" : ""); + dev_dbg(&udev->dev, "%s\n", + udev->reset_resume ? "finish reset-resume" : "finish resume"); /* usb ch9 identifies four variants of SUSPENDED, based on what * state the device resumes to. Linux currently won't see the @@ -1796,37 +3203,61 @@ static int finish_port_resume(struct usb_device *udev) * operation is carried out here, after the port has been * resumed. */ - if (udev->reset_resume) - status = usb_reset_device(udev); + if (udev->reset_resume) { + /* + * If the device morphs or switches modes when it is reset, + * we don't want to perform a reset-resume. We'll fail the + * resume, which will cause a logical disconnect, and then + * the device will be rediscovered. + */ + retry_reset_resume: + if (udev->quirks & USB_QUIRK_RESET) + status = -ENODEV; + else + status = usb_reset_and_verify_device(udev); + } - /* 10.5.4.5 says be sure devices in the tree are still there. - * For now let's assume the device didn't go crazy on resume, + /* 10.5.4.5 says be sure devices in the tree are still there. + * For now let's assume the device didn't go crazy on resume, * and device drivers will know about any resume quirks. */ if (status == 0) { devstatus = 0; status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstatus); - if (status >= 0) - status = (status > 0 ? 0 : -ENODEV); + + /* If a normal resume failed, try doing a reset-resume */ + if (status && !udev->reset_resume && udev->persist_enabled) { + dev_dbg(&udev->dev, "retry with reset-resume\n"); + udev->reset_resume = 1; + goto retry_reset_resume; + } } if (status) { dev_dbg(&udev->dev, "gone after usb resume? status %d\n", status); - } else if (udev->actconfig) { - le16_to_cpus(&devstatus); - if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, - USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - if (status) - dev_dbg(&udev->dev, "disable remote " - "wakeup, status %d\n", status); + /* + * There are a few quirky devices which violate the standard + * by claiming to have remote wakeup enabled after a reset, + * which crash if the feature is cleared, hence check for + * udev->reset_resume + */ + } else if (udev->actconfig && !udev->reset_resume) { + if (udev->speed < USB_SPEED_SUPER) { + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) + status = usb_disable_remote_wakeup(udev); + } else { + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + &devstatus); + if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP + | USB_INTRF_STAT_FUNC_RW)) + status = usb_disable_remote_wakeup(udev); } + + if (status) + dev_dbg(&udev->dev, + "disable remote wakeup, status %d\n", + status); status = 0; } return status; @@ -1843,9 +3274,8 @@ static int finish_port_resume(struct usb_device *udev) * the host and the device is the same as it was when the device * suspended. * - * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this - * routine won't check that the port is still enabled. Furthermore, - * if @udev->reset_resume is set then finish_port_resume() above will + * If @udev->reset_resume is set then this routine won't check that the + * port is still enabled. Furthermore, finish_port_resume() above will * reset @udev. The end result is that a broken power session can be * recovered and @udev will appear to persist across a loss of VBUS power. * @@ -1857,8 +3287,8 @@ static int finish_port_resume(struct usb_device *udev) * to it will be lost. Using the USB_PERSIST facility, the device can be * made to appear as if it had not disconnected. * - * This facility is inherently dangerous. Although usb_reset_device() - * makes every effort to insure that the same device is present after the + * This facility can be dangerous. Although usb_reset_and_verify_device() makes + * every effort to insure that the same device is present after the * reset as before, it cannot provide a 100% guarantee. Furthermore it's * quite possible for a device to remain unaltered but its media to be * changed. If the user replaces a flash memory card while the system is @@ -1867,33 +3297,42 @@ static int finish_port_resume(struct usb_device *udev) * * Returns 0 on success, else negative errno. */ -int usb_port_resume(struct usb_device *udev) +int usb_port_resume(struct usb_device *udev, pm_message_t msg) { - struct usb_hub *hub = hdev_to_hub(udev->parent); + struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); + struct usb_port *port_dev = hub->ports[udev->portnum - 1]; int port1 = udev->portnum; int status; u16 portchange, portstatus; - unsigned mask_flags, want_flags; + + if (!test_and_set_bit(port1, hub->child_usage_bits)) { + status = pm_runtime_get_sync(&port_dev->dev); + if (status < 0) { + dev_dbg(&udev->dev, "can't resume usb port, status %d\n", + status); + return status; + } + } + + usb_lock_port(port_dev); /* Skip the initial Clear-Suspend step for a remote wakeup */ status = hub_port_status(hub, port1, &portstatus, &portchange); - if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND)) + if (status == 0 && !port_is_suspended(hub, portstatus)) goto SuspendCleared; - // dev_dbg(hub->intfdev, "resume port %d\n", port1); - - set_bit(port1, hub->busy_bits); - /* see 7.1.7.7; affects power usage, but not budgeting */ - status = clear_port_feature(hub->hdev, - port1, USB_PORT_FEAT_SUSPEND); + if (hub_is_superspeed(hub->hdev)) + status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U0); + else + status = usb_clear_port_feature(hub->hdev, + port1, USB_PORT_FEAT_SUSPEND); if (status) { - dev_dbg(hub->intfdev, "can't resume port %d, status %d\n", - port1, status); + dev_dbg(&port_dev->dev, "can't resume, status %d\n", status); } else { /* drive resume for at least 20 msec */ dev_dbg(&udev->dev, "usb %sresume\n", - udev->auto_pm ? "auto-" : ""); + (PMSG_IS_AUTO(msg) ? "auto-" : "")); msleep(25); /* Virtual root hubs can trigger on GET_PORT_STATUS to @@ -1902,157 +3341,201 @@ int usb_port_resume(struct usb_device *udev) */ status = hub_port_status(hub, port1, &portstatus, &portchange); + /* TRSMRCY = 10 msec */ + msleep(10); + } + SuspendCleared: - if (USB_PERSIST && udev->reset_resume) - want_flags = USB_PORT_STAT_POWER - | USB_PORT_STAT_CONNECTION; - else - want_flags = USB_PORT_STAT_POWER - | USB_PORT_STAT_CONNECTION - | USB_PORT_STAT_ENABLE; - mask_flags = want_flags | USB_PORT_STAT_SUSPEND; - - if (status < 0 || (portstatus & mask_flags) != want_flags) { - dev_dbg(hub->intfdev, - "port %d status %04x.%04x after resume, %d\n", - port1, portchange, portstatus, status); - if (status >= 0) - status = -ENODEV; + if (status == 0) { + udev->port_is_suspended = 0; + if (hub_is_superspeed(hub->hdev)) { + if (portchange & USB_PORT_STAT_C_LINK_STATE) + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_PORT_LINK_STATE); } else { if (portchange & USB_PORT_STAT_C_SUSPEND) - clear_port_feature(hub->hdev, port1, + usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_SUSPEND); - /* TRSMRCY = 10 msec */ - msleep(10); } } - clear_bit(port1, hub->busy_bits); - if (!hub->hdev->parent && !hub->busy_bits[0]) - usb_enable_root_hub_irq(hub->hdev->bus); - + status = check_port_resume_type(udev, + hub, port1, status, portchange, portstatus); if (status == 0) status = finish_port_resume(udev); if (status < 0) { dev_dbg(&udev->dev, "can't resume, status %d\n", status); hub_port_logical_disconnect(hub, port1); + } else { + /* Try to enable USB2 hardware LPM */ + if (udev->usb2_hw_lpm_capable == 1) + usb_set_usb2_hardware_lpm(udev, 1); + + /* Try to enable USB3 LTM and LPM */ + usb_enable_ltm(udev); + usb_unlocked_enable_lpm(udev); } + + usb_unlock_port(port_dev); + return status; } -static int remote_wakeup(struct usb_device *udev) +#ifdef CONFIG_PM_RUNTIME + +int usb_remote_wakeup(struct usb_device *udev) { int status = 0; usb_lock_device(udev); if (udev->state == USB_STATE_SUSPENDED) { dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); - usb_mark_last_busy(udev); - status = usb_external_resume_device(udev); + status = usb_autoresume_device(udev); + if (status == 0) { + /* Let the drivers do their thing, then... */ + usb_autosuspend_device(udev); + } } usb_unlock_device(udev); return status; } -#else /* CONFIG_USB_SUSPEND */ - -/* When CONFIG_USB_SUSPEND isn't set, we never suspend or resume any ports. */ - -int usb_port_suspend(struct usb_device *udev) +/* Returns 1 if there was a remote wakeup and a connect status change. */ +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, + u16 portstatus, u16 portchange) + __must_hold(&port_dev->status_lock) { - return 0; -} + struct usb_port *port_dev = hub->ports[port - 1]; + struct usb_device *hdev; + struct usb_device *udev; + int connect_change = 0; + int ret; -int usb_port_resume(struct usb_device *udev) -{ - int status = 0; + hdev = hub->hdev; + udev = port_dev->child; + if (!hub_is_superspeed(hdev)) { + if (!(portchange & USB_PORT_STAT_C_SUSPEND)) + return 0; + usb_clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); + } else { + if (!udev || udev->state != USB_STATE_SUSPENDED || + (portstatus & USB_PORT_STAT_LINK_STATE) != + USB_SS_PORT_LS_U0) + return 0; + } - /* However we may need to do a reset-resume */ - if (udev->reset_resume) { - dev_dbg(&udev->dev, "reset-resume\n"); - status = usb_reset_device(udev); + if (udev) { + /* TRSMRCY = 10 msec */ + msleep(10); + + usb_unlock_port(port_dev); + ret = usb_remote_wakeup(udev); + usb_lock_port(port_dev); + if (ret < 0) + connect_change = 1; + } else { + ret = -ENODEV; + hub_port_disable(hub, port, 1); } - return status; + dev_dbg(&port_dev->dev, "resume, status %d\n", ret); + return connect_change; } -static inline int remote_wakeup(struct usb_device *udev) +#else + +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, + u16 portstatus, u16 portchange) { return 0; } #endif +static int check_ports_changed(struct usb_hub *hub) +{ + int port1; + + for (port1 = 1; port1 <= hub->hdev->maxchild; ++port1) { + u16 portstatus, portchange; + int status; + + status = hub_port_status(hub, port1, &portstatus, &portchange); + if (!status && portchange) + return 1; + } + return 0; +} + static int hub_suspend(struct usb_interface *intf, pm_message_t msg) { struct usb_hub *hub = usb_get_intfdata (intf); struct usb_device *hdev = hub->hdev; unsigned port1; + int status; - /* fail if children aren't already suspended */ + /* + * Warn if children aren't already suspended. + * Also, add up the number of wakeup-enabled descendants. + */ + hub->wakeup_enabled_descendants = 0; for (port1 = 1; port1 <= hdev->maxchild; port1++) { - struct usb_device *udev; + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; - udev = hdev->children [port1-1]; if (udev && udev->can_submit) { - if (!hdev->auto_pm) - dev_dbg(&intf->dev, "port %d nyet suspended\n", - port1); - return -EBUSY; + dev_warn(&port_dev->dev, "device %s not suspended yet\n", + dev_name(&udev->dev)); + if (PMSG_IS_AUTO(msg)) + return -EBUSY; + } + if (udev) + hub->wakeup_enabled_descendants += + wakeup_enabled_descendants(udev); + } + + if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) { + /* check if there are changes pending on hub ports */ + if (check_ports_changed(hub)) { + if (PMSG_IS_AUTO(msg)) + return -EBUSY; + pm_wakeup_event(&hdev->dev, 2000); } } - dev_dbg(&intf->dev, "%s\n", __FUNCTION__); + if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) { + /* Enable hub to send remote wakeup for all ports. */ + for (port1 = 1; port1 <= hdev->maxchild; port1++) { + status = set_port_feature(hdev, + port1 | + USB_PORT_FEAT_REMOTE_WAKE_CONNECT | + USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT | + USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT, + USB_PORT_FEAT_REMOTE_WAKE_MASK); + } + } + + dev_dbg(&intf->dev, "%s\n", __func__); /* stop khubd and related activity */ - hub_quiesce(hub); + hub_quiesce(hub, HUB_SUSPEND); return 0; } static int hub_resume(struct usb_interface *intf) { - struct usb_hub *hub = usb_get_intfdata (intf); - - dev_dbg(&intf->dev, "%s\n", __FUNCTION__); + struct usb_hub *hub = usb_get_intfdata(intf); - /* tell khubd to look for changes on this hub */ - hub_activate(hub); + dev_dbg(&intf->dev, "%s\n", __func__); + hub_activate(hub, HUB_RESUME); return 0; } static int hub_reset_resume(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata(intf); - struct usb_device *hdev = hub->hdev; - int port1; - - hub_power_on(hub); - - for (port1 = 1; port1 <= hdev->maxchild; ++port1) { - struct usb_device *child = hdev->children[port1-1]; - - if (child) { - - /* For "USB_PERSIST"-enabled children we must - * mark the child device for reset-resume and - * turn off the connect-change status to prevent - * khubd from disconnecting it later. - */ - if (USB_PERSIST && child->persist_enabled) { - child->reset_resume = 1; - clear_port_feature(hdev, port1, - USB_PORT_FEAT_C_CONNECTION); - - /* Otherwise we must disconnect the child, - * but as we may not lock the child device here - * we have to do a "logical" disconnect. - */ - } else { - hub_port_logical_disconnect(hub, port1); - } - } - } - hub_activate(hub); + dev_dbg(&intf->dev, "%s\n", __func__); + hub_activate(hub, HUB_RESET_RESUME); return 0; } @@ -2062,10 +3545,10 @@ static int hub_reset_resume(struct usb_interface *intf) * * The USB host controller driver calls this function when its root hub * is resumed and Vbus power has been interrupted or the controller - * has been reset. The routine marks @rhdev as having lost power. When - * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST - * is enabled then it will carry out power-session recovery, otherwise - * it will disconnect all the child devices. + * has been reset. The routine marks @rhdev as having lost power. + * When the hub driver is resumed it will take notice and carry out + * power-session recovery for all the "USB-PERSIST"-enabled child devices; + * the others will be disconnected. */ void usb_root_hub_lost_power(struct usb_device *rhdev) { @@ -2074,17 +3557,459 @@ void usb_root_hub_lost_power(struct usb_device *rhdev) } EXPORT_SYMBOL_GPL(usb_root_hub_lost_power); -#else /* CONFIG_PM */ +static const char * const usb3_lpm_names[] = { + "U0", + "U1", + "U2", + "U3", +}; + +/* + * Send a Set SEL control transfer to the device, prior to enabling + * device-initiated U1 or U2. This lets the device know the exit latencies from + * the time the device initiates a U1 or U2 exit, to the time it will receive a + * packet from the host. + * + * This function will fail if the SEL or PEL values for udev are greater than + * the maximum allowed values for the link state to be enabled. + */ +static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state) +{ + struct usb_set_sel_req *sel_values; + unsigned long long u1_sel; + unsigned long long u1_pel; + unsigned long long u2_sel; + unsigned long long u2_pel; + int ret; + + if (udev->state != USB_STATE_CONFIGURED) + return 0; + + /* Convert SEL and PEL stored in ns to us */ + u1_sel = DIV_ROUND_UP(udev->u1_params.sel, 1000); + u1_pel = DIV_ROUND_UP(udev->u1_params.pel, 1000); + u2_sel = DIV_ROUND_UP(udev->u2_params.sel, 1000); + u2_pel = DIV_ROUND_UP(udev->u2_params.pel, 1000); + + /* + * Make sure that the calculated SEL and PEL values for the link + * state we're enabling aren't bigger than the max SEL/PEL + * value that will fit in the SET SEL control transfer. + * Otherwise the device would get an incorrect idea of the exit + * latency for the link state, and could start a device-initiated + * U1/U2 when the exit latencies are too high. + */ + if ((state == USB3_LPM_U1 && + (u1_sel > USB3_LPM_MAX_U1_SEL_PEL || + u1_pel > USB3_LPM_MAX_U1_SEL_PEL)) || + (state == USB3_LPM_U2 && + (u2_sel > USB3_LPM_MAX_U2_SEL_PEL || + u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) { + dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n", + usb3_lpm_names[state], u1_sel, u1_pel); + return -EINVAL; + } + + /* + * If we're enabling device-initiated LPM for one link state, + * but the other link state has a too high SEL or PEL value, + * just set those values to the max in the Set SEL request. + */ + if (u1_sel > USB3_LPM_MAX_U1_SEL_PEL) + u1_sel = USB3_LPM_MAX_U1_SEL_PEL; + + if (u1_pel > USB3_LPM_MAX_U1_SEL_PEL) + u1_pel = USB3_LPM_MAX_U1_SEL_PEL; + + if (u2_sel > USB3_LPM_MAX_U2_SEL_PEL) + u2_sel = USB3_LPM_MAX_U2_SEL_PEL; + + if (u2_pel > USB3_LPM_MAX_U2_SEL_PEL) + u2_pel = USB3_LPM_MAX_U2_SEL_PEL; + + /* + * usb_enable_lpm() can be called as part of a failed device reset, + * which may be initiated by an error path of a mass storage driver. + * Therefore, use GFP_NOIO. + */ + sel_values = kmalloc(sizeof *(sel_values), GFP_NOIO); + if (!sel_values) + return -ENOMEM; + + sel_values->u1_sel = u1_sel; + sel_values->u1_pel = u1_pel; + sel_values->u2_sel = cpu_to_le16(u2_sel); + sel_values->u2_pel = cpu_to_le16(u2_pel); + + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_SEL, + USB_RECIP_DEVICE, + 0, 0, + sel_values, sizeof *(sel_values), + USB_CTRL_SET_TIMEOUT); + kfree(sel_values); + return ret; +} + +/* + * Enable or disable device-initiated U1 or U2 transitions. + */ +static int usb_set_device_initiated_lpm(struct usb_device *udev, + enum usb3_link_state state, bool enable) +{ + int ret; + int feature; + + switch (state) { + case USB3_LPM_U1: + feature = USB_DEVICE_U1_ENABLE; + break; + case USB3_LPM_U2: + feature = USB_DEVICE_U2_ENABLE; + break; + default: + dev_warn(&udev->dev, "%s: Can't %s non-U1 or U2 state.\n", + __func__, enable ? "enable" : "disable"); + return -EINVAL; + } + + if (udev->state != USB_STATE_CONFIGURED) { + dev_dbg(&udev->dev, "%s: Can't %s %s state " + "for unconfigured device.\n", + __func__, enable ? "enable" : "disable", + usb3_lpm_names[state]); + return 0; + } + + if (enable) { + /* + * Now send the control transfer to enable device-initiated LPM + * for either U1 or U2. + */ + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_SET_FEATURE, + USB_RECIP_DEVICE, + feature, + 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + feature, + 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); + } + if (ret < 0) { + dev_warn(&udev->dev, "%s of device-initiated %s failed.\n", + enable ? "Enable" : "Disable", + usb3_lpm_names[state]); + return -EBUSY; + } + return 0; +} + +static int usb_set_lpm_timeout(struct usb_device *udev, + enum usb3_link_state state, int timeout) +{ + int ret; + int feature; + + switch (state) { + case USB3_LPM_U1: + feature = USB_PORT_FEAT_U1_TIMEOUT; + break; + case USB3_LPM_U2: + feature = USB_PORT_FEAT_U2_TIMEOUT; + break; + default: + dev_warn(&udev->dev, "%s: Can't set timeout for non-U1 or U2 state.\n", + __func__); + return -EINVAL; + } + + if (state == USB3_LPM_U1 && timeout > USB3_LPM_U1_MAX_TIMEOUT && + timeout != USB3_LPM_DEVICE_INITIATED) { + dev_warn(&udev->dev, "Failed to set %s timeout to 0x%x, " + "which is a reserved value.\n", + usb3_lpm_names[state], timeout); + return -EINVAL; + } + + ret = set_port_feature(udev->parent, + USB_PORT_LPM_TIMEOUT(timeout) | udev->portnum, + feature); + if (ret < 0) { + dev_warn(&udev->dev, "Failed to set %s timeout to 0x%x," + "error code %i\n", usb3_lpm_names[state], + timeout, ret); + return -EBUSY; + } + if (state == USB3_LPM_U1) + udev->u1_params.timeout = timeout; + else + udev->u2_params.timeout = timeout; + return 0; +} + +/* + * Enable the hub-initiated U1/U2 idle timeouts, and enable device-initiated + * U1/U2 entry. + * + * We will attempt to enable U1 or U2, but there are no guarantees that the + * control transfers to set the hub timeout or enable device-initiated U1/U2 + * will be successful. + * + * If we cannot set the parent hub U1/U2 timeout, we attempt to let the xHCI + * driver know about it. If that call fails, it should be harmless, and just + * take up more slightly more bus bandwidth for unnecessary U1/U2 exit latency. + */ +static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, + enum usb3_link_state state) +{ + int timeout, ret; + __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat; + __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat; + + /* If the device says it doesn't have *any* exit latency to come out of + * U1 or U2, it's probably lying. Assume it doesn't implement that link + * state. + */ + if ((state == USB3_LPM_U1 && u1_mel == 0) || + (state == USB3_LPM_U2 && u2_mel == 0)) + return; + + /* + * First, let the device know about the exit latencies + * associated with the link state we're about to enable. + */ + ret = usb_req_set_sel(udev, state); + if (ret < 0) { + dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n", + usb3_lpm_names[state]); + return; + } + + /* We allow the host controller to set the U1/U2 timeout internally + * first, so that it can change its schedule to account for the + * additional latency to send data to a device in a lower power + * link state. + */ + timeout = hcd->driver->enable_usb3_lpm_timeout(hcd, udev, state); + + /* xHCI host controller doesn't want to enable this LPM state. */ + if (timeout == 0) + return; + + if (timeout < 0) { + dev_warn(&udev->dev, "Could not enable %s link state, " + "xHCI error %i.\n", usb3_lpm_names[state], + timeout); + return; + } + + if (usb_set_lpm_timeout(udev, state, timeout)) + /* If we can't set the parent hub U1/U2 timeout, + * device-initiated LPM won't be allowed either, so let the xHCI + * host know that this link state won't be enabled. + */ + hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); + + /* Only a configured device will accept the Set Feature U1/U2_ENABLE */ + else if (udev->actconfig) + usb_set_device_initiated_lpm(udev, state, true); + +} -static inline int remote_wakeup(struct usb_device *udev) +/* + * Disable the hub-initiated U1/U2 idle timeouts, and disable device-initiated + * U1/U2 entry. + * + * If this function returns -EBUSY, the parent hub will still allow U1/U2 entry. + * If zero is returned, the parent will not allow the link to go into U1/U2. + * + * If zero is returned, device-initiated U1/U2 entry may still be enabled, but + * it won't have an effect on the bus link state because the parent hub will + * still disallow device-initiated U1/U2 entry. + * + * If zero is returned, the xHCI host controller may still think U1/U2 entry is + * possible. The result will be slightly more bus bandwidth will be taken up + * (to account for U1/U2 exit latency), but it should be harmless. + */ +static int usb_disable_link_state(struct usb_hcd *hcd, struct usb_device *udev, + enum usb3_link_state state) { + int feature; + + switch (state) { + case USB3_LPM_U1: + feature = USB_PORT_FEAT_U1_TIMEOUT; + break; + case USB3_LPM_U2: + feature = USB_PORT_FEAT_U2_TIMEOUT; + break; + default: + dev_warn(&udev->dev, "%s: Can't disable non-U1 or U2 state.\n", + __func__); + return -EINVAL; + } + + if (usb_set_lpm_timeout(udev, state, 0)) + return -EBUSY; + + usb_set_device_initiated_lpm(udev, state, false); + + if (hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state)) + dev_warn(&udev->dev, "Could not disable xHCI %s timeout, " + "bus schedule bandwidth may be impacted.\n", + usb3_lpm_names[state]); + return 0; +} + +/* + * Disable hub-initiated and device-initiated U1 and U2 entry. + * Caller must own the bandwidth_mutex. + * + * This will call usb_enable_lpm() on failure, which will decrement + * lpm_disable_count, and will re-enable LPM if lpm_disable_count reaches zero. + */ +int usb_disable_lpm(struct usb_device *udev) +{ + struct usb_hcd *hcd; + + if (!udev || !udev->parent || + udev->speed != USB_SPEED_SUPER || + !udev->lpm_capable) + return 0; + + hcd = bus_to_hcd(udev->bus); + if (!hcd || !hcd->driver->disable_usb3_lpm_timeout) + return 0; + + udev->lpm_disable_count++; + if ((udev->u1_params.timeout == 0 && udev->u2_params.timeout == 0)) + return 0; + + /* If LPM is enabled, attempt to disable it. */ + if (usb_disable_link_state(hcd, udev, USB3_LPM_U1)) + goto enable_lpm; + if (usb_disable_link_state(hcd, udev, USB3_LPM_U2)) + goto enable_lpm; + return 0; + +enable_lpm: + usb_enable_lpm(udev); + return -EBUSY; +} +EXPORT_SYMBOL_GPL(usb_disable_lpm); + +/* Grab the bandwidth_mutex before calling usb_disable_lpm() */ +int usb_unlocked_disable_lpm(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + int ret; + + if (!hcd) + return -EINVAL; + + mutex_lock(hcd->bandwidth_mutex); + ret = usb_disable_lpm(udev); + mutex_unlock(hcd->bandwidth_mutex); + + return ret; } +EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm); + +/* + * Attempt to enable device-initiated and hub-initiated U1 and U2 entry. The + * xHCI host policy may prevent U1 or U2 from being enabled. + * + * Other callers may have disabled link PM, so U1 and U2 entry will be disabled + * until the lpm_disable_count drops to zero. Caller must own the + * bandwidth_mutex. + */ +void usb_enable_lpm(struct usb_device *udev) +{ + struct usb_hcd *hcd; + + if (!udev || !udev->parent || + udev->speed != USB_SPEED_SUPER || + !udev->lpm_capable) + return; + + udev->lpm_disable_count--; + hcd = bus_to_hcd(udev->bus); + /* Double check that we can both enable and disable LPM. + * Device must be configured to accept set feature U1/U2 timeout. + */ + if (!hcd || !hcd->driver->enable_usb3_lpm_timeout || + !hcd->driver->disable_usb3_lpm_timeout) + return; + + if (udev->lpm_disable_count > 0) + return; + + usb_enable_link_state(hcd, udev, USB3_LPM_U1); + usb_enable_link_state(hcd, udev, USB3_LPM_U2); +} +EXPORT_SYMBOL_GPL(usb_enable_lpm); + +/* Grab the bandwidth_mutex before calling usb_enable_lpm() */ +void usb_unlocked_enable_lpm(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!hcd) + return; + + mutex_lock(hcd->bandwidth_mutex); + usb_enable_lpm(udev); + mutex_unlock(hcd->bandwidth_mutex); +} +EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); + + +#else /* CONFIG_PM */ #define hub_suspend NULL #define hub_resume NULL #define hub_reset_resume NULL -#endif + +int usb_disable_lpm(struct usb_device *udev) +{ + return 0; +} +EXPORT_SYMBOL_GPL(usb_disable_lpm); + +void usb_enable_lpm(struct usb_device *udev) { } +EXPORT_SYMBOL_GPL(usb_enable_lpm); + +int usb_unlocked_disable_lpm(struct usb_device *udev) +{ + return 0; +} +EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm); + +void usb_unlocked_enable_lpm(struct usb_device *udev) { } +EXPORT_SYMBOL_GPL(usb_unlocked_enable_lpm); + +int usb_disable_ltm(struct usb_device *udev) +{ + return 0; +} +EXPORT_SYMBOL_GPL(usb_disable_ltm); + +void usb_enable_ltm(struct usb_device *udev) { } +EXPORT_SYMBOL_GPL(usb_enable_ltm); + +static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, + u16 portstatus, u16 portchange) +{ + return 0; +} + +#endif /* CONFIG_PM */ /* USB 2.0 spec, 7.1.7.3 / fig 7-29: @@ -2092,7 +4017,7 @@ static inline int remote_wakeup(struct usb_device *udev) * Between connect detection and reset signaling there must be a delay * of 100ms at least for debounce and power-settling. The corresponding * timer shall restart whenever the downstream port detects a disconnect. - * + * * Apparently there are some bluetooth and irda-dongles and a number of * low-speed devices for which this debounce period may last over a second. * Not covered by the spec - but easy to deal with. @@ -2102,17 +4027,13 @@ static inline int remote_wakeup(struct usb_device *udev) * every 25ms for transient disconnects. When the port status has been * unchanged for 100ms it returns the port status. */ - -#define HUB_DEBOUNCE_TIMEOUT 1500 -#define HUB_DEBOUNCE_STEP 25 -#define HUB_DEBOUNCE_STABLE 100 - -static int hub_port_debounce(struct usb_hub *hub, int port1) +int hub_port_debounce(struct usb_hub *hub, int port1, bool must_be_connected) { int ret; - int total_time, stable_time = 0; u16 portchange, portstatus; unsigned connection = 0xffff; + int total_time, stable_time = 0; + struct usb_port *port_dev = hub->ports[port1 - 1]; for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { ret = hub_port_status(hub, port1, &portstatus, &portchange); @@ -2121,7 +4042,9 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) if (!(portchange & USB_PORT_STAT_C_CONNECTION) && (portstatus & USB_PORT_STAT_CONNECTION) == connection) { - stable_time += HUB_DEBOUNCE_STEP; + if (!must_be_connected || + (connection == USB_PORT_STAT_CONNECTION)) + stable_time += HUB_DEBOUNCE_STEP; if (stable_time >= HUB_DEBOUNCE_STABLE) break; } else { @@ -2130,7 +4053,7 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) } if (portchange & USB_PORT_STAT_C_CONNECTION) { - clear_port_feature(hub->hdev, port1, + usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_CONNECTION); } @@ -2139,21 +4062,21 @@ static int hub_port_debounce(struct usb_hub *hub, int port1) msleep(HUB_DEBOUNCE_STEP); } - dev_dbg (hub->intfdev, - "debounce: port %d: total %dms stable %dms status 0x%x\n", - port1, total_time, stable_time, portstatus); + dev_dbg(&port_dev->dev, "debounce total %dms stable %dms status 0x%x\n", + total_time, stable_time, portstatus); if (stable_time < HUB_DEBOUNCE_STABLE) return -ETIMEDOUT; return portstatus; } -static void ep0_reinit(struct usb_device *udev) +void usb_ep0_reinit(struct usb_device *udev) { - usb_disable_endpoint(udev, 0 + USB_DIR_IN); - usb_disable_endpoint(udev, 0 + USB_DIR_OUT); - usb_enable_endpoint(udev, &udev->ep0); + usb_disable_endpoint(udev, 0 + USB_DIR_IN, true); + usb_disable_endpoint(udev, 0 + USB_DIR_OUT, true); + usb_enable_endpoint(udev, &udev->ep0, true); } +EXPORT_SYMBOL_GPL(usb_ep0_reinit); #define usb_sndaddr0pipe() (PIPE_CONTROL << 30) #define usb_rcvaddr0pipe() ((PIPE_CONTROL << 30) | USB_DIR_IN) @@ -2161,44 +4084,94 @@ static void ep0_reinit(struct usb_device *udev) static int hub_set_address(struct usb_device *udev, int devnum) { int retval; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); - if (devnum <= 1) + /* + * The host controller will choose the device address, + * instead of the core having chosen it earlier + */ + if (!hcd->driver->address_device && devnum <= 1) return -EINVAL; if (udev->state == USB_STATE_ADDRESS) return 0; if (udev->state != USB_STATE_DEFAULT) return -EINVAL; - retval = usb_control_msg(udev, usb_sndaddr0pipe(), - USB_REQ_SET_ADDRESS, 0, devnum, 0, - NULL, 0, USB_CTRL_SET_TIMEOUT); + if (hcd->driver->address_device) + retval = hcd->driver->address_device(hcd, udev); + else + retval = usb_control_msg(udev, usb_sndaddr0pipe(), + USB_REQ_SET_ADDRESS, 0, devnum, 0, + NULL, 0, USB_CTRL_SET_TIMEOUT); if (retval == 0) { - udev->devnum = devnum; /* Device now using proper address */ + update_devnum(udev, devnum); + /* Device now using proper address. */ usb_set_device_state(udev, USB_STATE_ADDRESS); - ep0_reinit(udev); + usb_ep0_reinit(udev); } return retval; } +/* + * There are reports of USB 3.0 devices that say they support USB 2.0 Link PM + * when they're plugged into a USB 2.0 port, but they don't work when LPM is + * enabled. + * + * Only enable USB 2.0 Link PM if the port is internal (hardwired), or the + * device says it supports the new USB 2.0 Link PM errata by setting the BESL + * support bit in the BOS descriptor. + */ +static void hub_set_initial_usb2_lpm_policy(struct usb_device *udev) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); + int connect_type = USB_PORT_CONNECT_TYPE_UNKNOWN; + + if (!udev->usb2_hw_lpm_capable) + return; + + if (hub) + connect_type = hub->ports[udev->portnum - 1]->connect_type; + + if ((udev->bos->ext_cap->bmAttributes & cpu_to_le32(USB_BESL_SUPPORT)) || + connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + udev->usb2_hw_lpm_allowed = 1; + usb_set_usb2_hardware_lpm(udev, 1); + } +} + +static int hub_enable_device(struct usb_device *udev) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + + if (!hcd->driver->enable_device) + return 0; + if (udev->state == USB_STATE_ADDRESS) + return 0; + if (udev->state != USB_STATE_DEFAULT) + return -EINVAL; + + return hcd->driver->enable_device(hcd, udev); +} + /* Reset device, (re)assign address, get device descriptor. * Device connection must be stable, no more debouncing needed. * Returns device in USB_STATE_ADDRESS, except on error. * * If this is called for an already-existing device (as part of - * usb_reset_device), the caller must own the device lock. For a - * newly detected device that is not accessible through any global - * pointers, it's not necessary to lock the device. + * usb_reset_and_verify_device), the caller must own the device lock and + * the port lock. For a newly detected device that is not accessible + * through any global pointers, it's not necessary to lock the device, + * but it is still necessary to lock the port. */ static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, int retry_counter) { - static DEFINE_MUTEX(usb_address0_mutex); - struct usb_device *hdev = hub->hdev; + struct usb_hcd *hcd = bus_to_hcd(hdev->bus); int i, j, retval; unsigned delay = HUB_SHORT_RESET_TIME; enum usb_device_speed oldspeed = udev->speed; - char *speed, *type; + const char *speed; int devnum = udev->devnum; /* root hub ports have a slightly longer reset period @@ -2215,13 +4188,15 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, if (oldspeed == USB_SPEED_LOW) delay = HUB_LONG_RESET_TIME; - mutex_lock(&usb_address0_mutex); + mutex_lock(&hdev->bus->usb_address0_mutex); /* Reset the device; full speed may morph to high speed */ - retval = hub_port_reset(hub, port1, udev, delay); + /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ + retval = hub_port_reset(hub, port1, udev, delay, false); if (retval < 0) /* error or disconnect */ goto fail; - /* success, speed is known */ + /* success, speed is known */ + retval = -ENODEV; if (oldspeed != USB_SPEED_UNKNOWN && oldspeed != udev->speed) { @@ -2236,41 +4211,37 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * reported as 0xff in the device descriptor). WUSB1.0[4.8.1]. */ switch (udev->speed) { - case USB_SPEED_VARIABLE: /* fixed at 512 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512); + case USB_SPEED_SUPER: + case USB_SPEED_WIRELESS: /* fixed at 512 */ + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); break; case USB_SPEED_HIGH: /* fixed at 64 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ /* to determine the ep0 maxpacket size, try to read * the device descriptor to get bMaxPacketSize0 and * then correct our initial guess. */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_LOW: /* fixed at 8 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); break; default: goto fail; } - - type = ""; - switch (udev->speed) { - case USB_SPEED_LOW: speed = "low"; break; - case USB_SPEED_FULL: speed = "full"; break; - case USB_SPEED_HIGH: speed = "high"; break; - case USB_SPEED_VARIABLE: - speed = "variable"; - type = "Wireless "; - break; - default: speed = "?"; break; - } - dev_info (&udev->dev, - "%s %s speed %sUSB device using %s and address %d\n", - (udev->config) ? "reset" : "new", speed, type, - udev->bus->controller->driver->name, devnum); + + if (udev->speed == USB_SPEED_WIRELESS) + speed = "variable speed Wireless"; + else + speed = usb_speed_string(udev->speed); + + if (udev->speed != USB_SPEED_SUPER) + dev_info(&udev->dev, + "%s %s USB device number %d using %s\n", + (udev->config) ? "reset" : "new", speed, + devnum, udev->bus->controller->driver->name); /* Set up TT records, if needed */ if (hdev->tt) { @@ -2278,16 +4249,21 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, udev->ttport = hdev->ttport; } else if (udev->speed != USB_SPEED_HIGH && hdev->speed == USB_SPEED_HIGH) { + if (!hub->tt.hub) { + dev_err(&udev->dev, "parent hub has no TT\n"); + retval = -EINVAL; + goto fail; + } udev->tt = &hub->tt; udev->ttport = port1; } - + /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? * Because device hardware and firmware is sometimes buggy in * this area, and this is how Linux has done it for ages. * Change it cautiously. * - * NOTE: If USE_NEW_SCHEME() is true we will start by issuing + * NOTE: If use_new_scheme() is true we will start by issuing * a 64-byte GET_DESCRIPTOR request. This is what Windows does, * so it may help with some non-standards-compliant devices. * Otherwise we start with SET_ADDRESS and then try to read the @@ -2295,10 +4271,21 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, * value. */ for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { - if (USE_NEW_SCHEME(retry_counter)) { + bool did_new_scheme = false; + + if (use_new_scheme(udev, retry_counter)) { struct usb_device_descriptor *buf; int r = 0; + did_new_scheme = true; + retval = hub_enable_device(udev); + if (retval < 0) { + dev_err(&udev->dev, + "hub failed to enable device, error %d\n", + retval); + goto fail; + } + #define GET_DESCRIPTOR_BUFSIZE 64 buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO); if (!buf) { @@ -2316,7 +4303,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, USB_DT_DEVICE << 8, 0, buf, GET_DESCRIPTOR_BUFSIZE, - USB_CTRL_GET_TIMEOUT); + initial_descriptor_timeout); switch (buf->bMaxPacketSize0) { case 8: case 16: case 32: case 64: case 255: if (buf->bDescriptorType == @@ -2337,7 +4324,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, buf->bMaxPacketSize0; kfree(buf); - retval = hub_port_reset(hub, port1, udev, delay); + retval = hub_port_reset(hub, port1, udev, delay, false); if (retval < 0) /* error or disconnect */ goto fail; if (oldspeed != udev->speed) { @@ -2347,41 +4334,60 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, goto fail; } if (r) { - dev_err(&udev->dev, "device descriptor " - "read/%s, error %d\n", - "64", r); + if (r != -ENODEV) + dev_err(&udev->dev, "device descriptor read/64, error %d\n", + r); retval = -EMSGSIZE; continue; } #undef GET_DESCRIPTOR_BUFSIZE } - for (j = 0; j < SET_ADDRESS_TRIES; ++j) { - retval = hub_set_address(udev, devnum); - if (retval >= 0) + /* + * If device is WUSB, we already assigned an + * unauthorized address in the Connect Ack sequence; + * authorization will assign the final address. + */ + if (udev->wusb == 0) { + for (j = 0; j < SET_ADDRESS_TRIES; ++j) { + retval = hub_set_address(udev, devnum); + if (retval >= 0) + break; + msleep(200); + } + if (retval < 0) { + if (retval != -ENODEV) + dev_err(&udev->dev, "device not accepting address %d, error %d\n", + devnum, retval); + goto fail; + } + if (udev->speed == USB_SPEED_SUPER) { + devnum = udev->devnum; + dev_info(&udev->dev, + "%s SuperSpeed USB device number %d using %s\n", + (udev->config) ? "reset" : "new", + devnum, udev->bus->controller->driver->name); + } + + /* cope with hardware quirkiness: + * - let SET_ADDRESS settle, some device hardware wants it + * - read ep0 maxpacket even for high and low speed, + */ + msleep(10); + /* use_new_scheme() checks the speed which may have + * changed since the initial look so we cache the result + * in did_new_scheme + */ + if (did_new_scheme) break; - msleep(200); - } - if (retval < 0) { - dev_err(&udev->dev, - "device not accepting address %d, error %d\n", - devnum, retval); - goto fail; } - - /* cope with hardware quirkiness: - * - let SET_ADDRESS settle, some device hardware wants it - * - read ep0 maxpacket even for high and low speed, - */ - msleep(10); - if (USE_NEW_SCHEME(retry_counter)) - break; retval = usb_get_device_descriptor(udev, 8); if (retval < 8) { - dev_err(&udev->dev, "device descriptor " - "read/%s, error %d\n", - "8", retval); + if (retval != -ENODEV) + dev_err(&udev->dev, + "device descriptor read/8, error %d\n", + retval); if (retval >= 0) retval = -EMSGSIZE; } else { @@ -2392,37 +4398,74 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, if (retval) goto fail; - i = udev->descriptor.bMaxPacketSize0 == 0xff? - 512 : udev->descriptor.bMaxPacketSize0; - if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { - if (udev->speed != USB_SPEED_FULL || + if (hcd->phy && !hdev->parent) + usb_phy_notify_connect(hcd->phy, udev->speed); + + /* + * Some superspeed devices have finished the link training process + * and attached to a superspeed hub port, but the device descriptor + * got from those devices show they aren't superspeed devices. Warm + * reset the port attached by the devices can fix them. + */ + if ((udev->speed == USB_SPEED_SUPER) && + (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) { + dev_err(&udev->dev, "got a wrong device descriptor, " + "warm reset device\n"); + hub_port_reset(hub, port1, udev, + HUB_BH_RESET_TIME, true); + retval = -EINVAL; + goto fail; + } + + if (udev->descriptor.bMaxPacketSize0 == 0xff || + udev->speed == USB_SPEED_SUPER) + i = 512; + else + i = udev->descriptor.bMaxPacketSize0; + if (usb_endpoint_maxp(&udev->ep0.desc) != i) { + if (udev->speed == USB_SPEED_LOW || !(i == 8 || i == 16 || i == 32 || i == 64)) { - dev_err(&udev->dev, "ep0 maxpacket = %d\n", i); + dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); retval = -EMSGSIZE; goto fail; } - dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); + if (udev->speed == USB_SPEED_FULL) + dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i); + else + dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i); udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i); - ep0_reinit(udev); + usb_ep0_reinit(udev); } - + retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE); if (retval < (signed)sizeof(udev->descriptor)) { - dev_err(&udev->dev, "device descriptor read/%s, error %d\n", - "all", retval); + if (retval != -ENODEV) + dev_err(&udev->dev, "device descriptor read/all, error %d\n", + retval); if (retval >= 0) retval = -ENOMSG; goto fail; } - retval = 0; + if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { + retval = usb_get_bos_descriptor(udev); + if (!retval) { + udev->lpm_capable = usb_device_supports_lpm(udev); + usb_set_lpm_parameters(udev); + } + } + retval = 0; + /* notify HCD that we have a device connected and addressed */ + if (hcd->driver->update_device) + hcd->driver->update_device(hcd, udev); + hub_set_initial_usb2_lpm_policy(udev); fail: if (retval) { hub_port_disable(hub, port1, 0); - udev->devnum = devnum; /* for disconnect processing */ + update_devnum(udev, devnum); /* for disconnect processing */ } - mutex_unlock(&usb_address0_mutex); + mutex_unlock(&hdev->bus->usb_address0_mutex); return retval; } @@ -2444,7 +4487,8 @@ check_highspeed (struct usb_hub *hub, struct usb_device *udev, int port1) /* hub LEDs are probably harder to miss than syslog */ if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_GREEN_BLINK; - schedule_delayed_work (&hub->leds, 0); + queue_delayed_work(system_power_efficient_wq, + &hub->leds, 0); } } kfree(qual); @@ -2462,126 +4506,140 @@ hub_power_remaining (struct usb_hub *hub) remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent; for (port1 = 1; port1 <= hdev->maxchild; ++port1) { - struct usb_device *udev = hdev->children[port1 - 1]; - int delta; + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; + unsigned unit_load; + int delta; if (!udev) continue; + if (hub_is_superspeed(udev)) + unit_load = 150; + else + unit_load = 100; - /* Unconfigured devices may not use more than 100mA, - * or 8mA for OTG ports */ + /* + * Unconfigured devices may not use more than one unit load, + * or 8mA for OTG ports + */ if (udev->actconfig) - delta = udev->actconfig->desc.bMaxPower * 2; + delta = usb_get_max_power(udev, udev->actconfig); else if (port1 != udev->bus->otg_port || hdev->parent) - delta = 100; + delta = unit_load; else delta = 8; if (delta > hub->mA_per_port) - dev_warn(&udev->dev, "%dmA is over %umA budget " - "for port %d!\n", - delta, hub->mA_per_port, port1); + dev_warn(&port_dev->dev, "%dmA is over %umA budget!\n", + delta, hub->mA_per_port); remaining -= delta; } if (remaining < 0) { dev_warn(hub->intfdev, "%dmA over power budget!\n", - - remaining); + -remaining); remaining = 0; } return remaining; } -/* Handle physical or logical connection change events. - * This routine is called when: - * a port connection-change occurs; - * a port enable-change occurs (often caused by EMI); - * usb_reset_device() encounters changed descriptors (as from - * a firmware download) - * caller already locked the hub - */ -static void hub_port_connect_change(struct usb_hub *hub, int port1, - u16 portstatus, u16 portchange) +static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, + u16 portchange) { + int status, i; + unsigned unit_load; struct usb_device *hdev = hub->hdev; - struct device *hub_dev = hub->intfdev; struct usb_hcd *hcd = bus_to_hcd(hdev->bus); - u16 wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); - int status, i; - - dev_dbg (hub_dev, - "port %d, status %04x, change %04x, %s\n", - port1, portstatus, portchange, portspeed (portstatus)); + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; - if (hub->has_indicators) { - set_port_led(hub, port1, HUB_LED_AUTO); - hub->indicator[port1-1] = INDICATOR_AUTO; - } - /* Disconnect any existing devices under this port */ - if (hdev->children[port1-1]) - usb_disconnect(&hdev->children[port1-1]); - clear_bit(port1, hub->change_bits); + if (udev) { + if (hcd->phy && !hdev->parent && + !(portstatus & USB_PORT_STAT_CONNECTION)) + usb_phy_notify_disconnect(hcd->phy, udev->speed); + usb_disconnect(&port_dev->child); + } -#ifdef CONFIG_USB_OTG - /* during HNP, don't repeat the debounce */ - if (hdev->bus->is_b_host) - portchange &= ~USB_PORT_STAT_C_CONNECTION; -#endif + /* We can forget about a "removed" device when there's a physical + * disconnect or the connect status changes. + */ + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + (portchange & USB_PORT_STAT_C_CONNECTION)) + clear_bit(port1, hub->removed_bits); - if (portchange & USB_PORT_STAT_C_CONNECTION) { - status = hub_port_debounce(hub, port1); + if (portchange & (USB_PORT_STAT_C_CONNECTION | + USB_PORT_STAT_C_ENABLE)) { + status = hub_port_debounce_be_stable(hub, port1); if (status < 0) { - if (printk_ratelimit()) - dev_err (hub_dev, "connect-debounce failed, " - "port %d disabled\n", port1); - goto done; + if (status != -ENODEV && printk_ratelimit()) + dev_err(&port_dev->dev, + "connect-debounce failed\n"); + portstatus &= ~USB_PORT_STAT_CONNECTION; + } else { + portstatus = status; } - portstatus = status; } - /* Return now if nothing is connected */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) { + /* Return now if debouncing failed or nothing is connected or + * the device was "removed". + */ + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + test_bit(port1, hub->removed_bits)) { /* maybe switch power back on (e.g. root hub was reset) */ - if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 - && !(portstatus & (1 << USB_PORT_FEAT_POWER))) + if (hub_is_port_power_switchable(hub) + && !port_is_power_on(hub, portstatus)) set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); - + if (portstatus & USB_PORT_STAT_ENABLE) - goto done; + goto done; return; } + if (hub_is_superspeed(hub->hdev)) + unit_load = 150; + else + unit_load = 100; + status = 0; for (i = 0; i < SET_CONFIG_TRIES; i++) { - struct usb_device *udev; /* reallocate for each attempt, since references * to the previous one can escape in various ways */ udev = usb_alloc_dev(hdev, hdev->bus, port1); if (!udev) { - dev_err (hub_dev, - "couldn't allocate port %d usb_device\n", - port1); + dev_err(&port_dev->dev, + "couldn't allocate usb_device\n"); goto done; } usb_set_device_state(udev, USB_STATE_POWERED); - udev->speed = USB_SPEED_UNKNOWN; - udev->bus_mA = hub->mA_per_port; + udev->bus_mA = hub->mA_per_port; udev->level = hdev->level + 1; + udev->wusb = hub_is_wusb(hub); + + /* Only USB 3.0 devices are connected to SuperSpeed hubs. */ + if (hub_is_superspeed(hub->hdev)) + udev->speed = USB_SPEED_SUPER; + else + udev->speed = USB_SPEED_UNKNOWN; - /* set the address */ - choose_address(udev); + choose_devnum(udev); if (udev->devnum <= 0) { status = -ENOTCONN; /* Don't retry */ goto loop; } - /* reset and get descriptor */ + /* reset (non-USB 3.0 devices) and get descriptor */ + usb_lock_port(port_dev); status = hub_port_init(hub, udev, port1, i); + usb_unlock_port(port_dev); if (status < 0) goto loop; + usb_detect_quirks(udev); + if (udev->quirks & USB_QUIRK_DELAY_INIT) + msleep(1000); + /* consecutive bus-powered hubs aren't reliable; they can * violate the voltage drop budget. if the new child has * a "powered" LED, users should notice we didn't enable it @@ -2589,16 +4647,15 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, * on the parent. */ if (udev->descriptor.bDeviceClass == USB_CLASS_HUB - && udev->bus_mA <= 100) { + && udev->bus_mA <= unit_load) { u16 devstat; status = usb_get_status(udev, USB_RECIP_DEVICE, 0, &devstat); - if (status < 2) { + if (status) { dev_dbg(&udev->dev, "get status %d ?\n", status); goto loop_disable; } - le16_to_cpus(&devstat); if ((devstat & (1 << USB_DEVICE_SELF_POWERED)) == 0) { dev_err(&udev->dev, "can't connect bus-powered hub " @@ -2606,13 +4663,15 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (hub->has_indicators) { hub->indicator[port1-1] = INDICATOR_AMBER_BLINK; - schedule_delayed_work (&hub->leds, 0); + queue_delayed_work( + system_power_efficient_wq, + &hub->leds, 0); } status = -ENOTCONN; /* Don't retry */ goto loop_disable; } } - + /* check for devices running slower than they could */ if (le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0200 && udev->speed == USB_SPEED_FULL @@ -2625,6 +4684,8 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, */ status = 0; + mutex_lock(&usb_port_peer_mutex); + /* We mustn't add new devices if the parent hub has * been disconnected; we would race with the * recursively_mark_NOTATTACHED() routine. @@ -2633,16 +4694,19 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (hdev->state == USB_STATE_NOTATTACHED) status = -ENOTCONN; else - hdev->children[port1-1] = udev; + port_dev->child = udev; spin_unlock_irq(&device_state_lock); + mutex_unlock(&usb_port_peer_mutex); /* Run it through the hoops (find a driver, etc) */ if (!status) { status = usb_new_device(udev); if (status) { + mutex_lock(&usb_port_peer_mutex); spin_lock_irq(&device_state_lock); - hdev->children[port1-1] = NULL; + port_dev->child = NULL; spin_unlock_irq(&device_state_lock); + mutex_unlock(&usb_port_peer_mutex); } } @@ -2651,26 +4715,218 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, status = hub_power_remaining(hub); if (status) - dev_dbg(hub_dev, "%dmA power budget left\n", status); + dev_dbg(hub->intfdev, "%dmA power budget left\n", status); return; loop_disable: hub_port_disable(hub, port1, 1); loop: - ep0_reinit(udev); - release_address(udev); + usb_ep0_reinit(udev); + release_devnum(udev); + hub_free_dev(udev); usb_put_dev(udev); if ((status == -ENOTCONN) || (status == -ENOTSUPP)) break; } - + if (hub->hdev->parent || + !hcd->driver->port_handed_over || + !(hcd->driver->port_handed_over)(hcd, port1)) { + if (status != -ENOTCONN && status != -ENODEV) + dev_err(&port_dev->dev, + "unable to enumerate USB device\n"); + } + done: hub_port_disable(hub, port1, 1); if (hcd->driver->relinquish_port && !hub->hdev->parent) hcd->driver->relinquish_port(hcd, port1); + } +/* Handle physical or logical connection change events. + * This routine is called when: + * a port connection-change occurs; + * a port enable-change occurs (often caused by EMI); + * usb_reset_and_verify_device() encounters changed descriptors (as from + * a firmware download) + * caller already locked the hub + */ +static void hub_port_connect_change(struct usb_hub *hub, int port1, + u16 portstatus, u16 portchange) + __must_hold(&port_dev->status_lock) +{ + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; + int status = -ENODEV; + + dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus, + portchange, portspeed(hub, portstatus)); + + if (hub->has_indicators) { + set_port_led(hub, port1, HUB_LED_AUTO); + hub->indicator[port1-1] = INDICATOR_AUTO; + } + +#ifdef CONFIG_USB_OTG + /* during HNP, don't repeat the debounce */ + if (hub->hdev->bus->is_b_host) + portchange &= ~(USB_PORT_STAT_C_CONNECTION | + USB_PORT_STAT_C_ENABLE); +#endif + + /* Try to resuscitate an existing device */ + if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && + udev->state != USB_STATE_NOTATTACHED) { + if (portstatus & USB_PORT_STAT_ENABLE) { + status = 0; /* Nothing to do */ +#ifdef CONFIG_PM_RUNTIME + } else if (udev->state == USB_STATE_SUSPENDED && + udev->persist_enabled) { + /* For a suspended device, treat this as a + * remote wakeup event. + */ + usb_unlock_port(port_dev); + status = usb_remote_wakeup(udev); + usb_lock_port(port_dev); +#endif + } else { + /* Don't resuscitate */; + } + } + clear_bit(port1, hub->change_bits); + + /* successfully revalidated the connection */ + if (status == 0) + return; + + usb_unlock_port(port_dev); + hub_port_connect(hub, port1, portstatus, portchange); + usb_lock_port(port_dev); +} + +static void port_event(struct usb_hub *hub, int port1) + __must_hold(&port_dev->status_lock) +{ + int connect_change, reset_device = 0; + struct usb_port *port_dev = hub->ports[port1 - 1]; + struct usb_device *udev = port_dev->child; + struct usb_device *hdev = hub->hdev; + u16 portstatus, portchange; + + connect_change = test_bit(port1, hub->change_bits); + clear_bit(port1, hub->event_bits); + clear_bit(port1, hub->wakeup_bits); + + if (hub_port_status(hub, port1, &portstatus, &portchange) < 0) + return; + + if (portchange & USB_PORT_STAT_C_CONNECTION) { + usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION); + connect_change = 1; + } + + if (portchange & USB_PORT_STAT_C_ENABLE) { + if (!connect_change) + dev_dbg(&port_dev->dev, "enable change, status %08x\n", + portstatus); + usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_ENABLE); + + /* + * EM interference sometimes causes badly shielded USB devices + * to be shutdown by the hub, this hack enables them again. + * Works at least with mouse driver. + */ + if (!(portstatus & USB_PORT_STAT_ENABLE) + && !connect_change && udev) { + dev_err(&port_dev->dev, "disabled by hub (EMI?), re-enabling...\n"); + connect_change = 1; + } + } + + if (portchange & USB_PORT_STAT_C_OVERCURRENT) { + u16 status = 0, unused; + + dev_dbg(&port_dev->dev, "over-current change\n"); + usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_C_OVER_CURRENT); + msleep(100); /* Cool down */ + hub_power_on(hub, true); + hub_port_status(hub, port1, &status, &unused); + if (status & USB_PORT_STAT_OVERCURRENT) + dev_err(&port_dev->dev, "over-current condition\n"); + } + + if (portchange & USB_PORT_STAT_C_RESET) { + dev_dbg(&port_dev->dev, "reset change\n"); + usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_RESET); + } + if ((portchange & USB_PORT_STAT_C_BH_RESET) + && hub_is_superspeed(hdev)) { + dev_dbg(&port_dev->dev, "warm reset change\n"); + usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_C_BH_PORT_RESET); + } + if (portchange & USB_PORT_STAT_C_LINK_STATE) { + dev_dbg(&port_dev->dev, "link state change\n"); + usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_C_PORT_LINK_STATE); + } + if (portchange & USB_PORT_STAT_C_CONFIG_ERROR) { + dev_warn(&port_dev->dev, "config error\n"); + usb_clear_port_feature(hdev, port1, + USB_PORT_FEAT_C_PORT_CONFIG_ERROR); + } + + /* skip port actions that require the port to be powered on */ + if (!pm_runtime_active(&port_dev->dev)) + return; + + if (hub_handle_remote_wakeup(hub, port1, portstatus, portchange)) + connect_change = 1; + + /* + * Warm reset a USB3 protocol port if it's in + * SS.Inactive state. + */ + if (hub_port_warm_reset_required(hub, portstatus)) { + dev_dbg(&port_dev->dev, "do warm reset\n"); + if (!udev || !(portstatus & USB_PORT_STAT_CONNECTION) + || udev->state == USB_STATE_NOTATTACHED) { + if (hub_port_reset(hub, port1, NULL, + HUB_BH_RESET_TIME, true) < 0) + hub_port_disable(hub, port1, 1); + } else + reset_device = 1; + } + + /* + * On disconnect USB3 protocol ports transit from U0 to + * SS.Inactive to Rx.Detect. If this happens a warm- + * reset is not needed, but a (re)connect may happen + * before khubd runs and sees the disconnect, and the + * device may be an unknown state. + * + * If the port went through SS.Inactive without khubd + * seeing it the C_LINK_STATE change flag will be set, + * and we reset the dev to put it in a known state. + */ + if (reset_device || (udev && hub_is_superspeed(hub->hdev) + && (portchange & USB_PORT_STAT_C_LINK_STATE) + && (portstatus & USB_PORT_STAT_CONNECTION))) { + usb_unlock_port(port_dev); + usb_lock_device(udev); + usb_reset_device(udev); + usb_unlock_device(udev); + usb_lock_port(port_dev); + connect_change = 0; + } + + if (connect_change) + hub_port_connect_change(hub, port1, portstatus, portchange); +} + + static void hub_events(void) { struct list_head *tmp; @@ -2680,10 +4936,7 @@ static void hub_events(void) struct device *hub_dev; u16 hubstatus; u16 hubchange; - u16 portstatus; - u16 portchange; int i, ret; - int connect_change; /* * We restart the list every time to avoid a deadlock with @@ -2711,9 +4964,7 @@ static void hub_events(void) hub_dev = hub->intfdev; intf = to_usb_interface(hub_dev); dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n", - hdev->state, hub->descriptor - ? hub->descriptor->bNbrPorts - : 0, + hdev->state, hdev->maxchild, /* NOTE: expects max 15 ports... */ (u16) hub->change_bits[0], (u16) hub->event_bits[0]); @@ -2722,12 +4973,12 @@ static void hub_events(void) * disconnected while waiting for the lock to succeed. */ usb_lock_device(hdev); if (unlikely(hub->disconnected)) - goto loop; + goto loop_disconnected; /* If the hub has died, clean up after it */ if (hdev->state == USB_STATE_NOTATTACHED) { hub->error = -ENODEV; - hub_pre_reset(intf); + hub_quiesce(hub, HUB_DISCONNECT); goto loop; } @@ -2746,7 +4997,7 @@ static void hub_events(void) dev_dbg (hub_dev, "resetting for error %d\n", hub->error); - ret = usb_reset_composite_device(hdev, intf); + ret = usb_reset_device(hdev); if (ret) { dev_dbg (hub_dev, "error resetting hub: %d\n", ret); @@ -2758,95 +5009,29 @@ static void hub_events(void) } /* deal with port status changes */ - for (i = 1; i <= hub->descriptor->bNbrPorts; i++) { - if (test_bit(i, hub->busy_bits)) - continue; - connect_change = test_bit(i, hub->change_bits); - if (!test_and_clear_bit(i, hub->event_bits) && - !connect_change && !hub->activating) - continue; - - ret = hub_port_status(hub, i, - &portstatus, &portchange); - if (ret < 0) - continue; - - if (hub->activating && !hdev->children[i-1] && - (portstatus & - USB_PORT_STAT_CONNECTION)) - connect_change = 1; - - if (portchange & USB_PORT_STAT_C_CONNECTION) { - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_CONNECTION); - connect_change = 1; - } - - if (portchange & USB_PORT_STAT_C_ENABLE) { - if (!connect_change) - dev_dbg (hub_dev, - "port %d enable change, " - "status %08x\n", - i, portstatus); - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_ENABLE); + for (i = 1; i <= hdev->maxchild; i++) { + struct usb_port *port_dev = hub->ports[i - 1]; + if (test_bit(i, hub->event_bits) + || test_bit(i, hub->change_bits) + || test_bit(i, hub->wakeup_bits)) { /* - * EM interference sometimes causes badly - * shielded USB devices to be shutdown by - * the hub, this hack enables them again. - * Works at least with mouse driver. + * The get_noresume and barrier ensure that if + * the port was in the process of resuming, we + * flush that work and keep the port active for + * the duration of the port_event(). However, + * if the port is runtime pm suspended + * (powered-off), we leave it in that state, run + * an abbreviated port_event(), and move on. */ - if (!(portstatus & USB_PORT_STAT_ENABLE) - && !connect_change - && hdev->children[i-1]) { - dev_err (hub_dev, - "port %i " - "disabled by hub (EMI?), " - "re-enabling...\n", - i); - connect_change = 1; - } + pm_runtime_get_noresume(&port_dev->dev); + pm_runtime_barrier(&port_dev->dev); + usb_lock_port(port_dev); + port_event(hub, i); + usb_unlock_port(port_dev); + pm_runtime_put_sync(&port_dev->dev); } - - if (portchange & USB_PORT_STAT_C_SUSPEND) { - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_SUSPEND); - if (hdev->children[i-1]) { - ret = remote_wakeup(hdev-> - children[i-1]); - if (ret < 0) - connect_change = 1; - } else { - ret = -ENODEV; - hub_port_disable(hub, i, 1); - } - dev_dbg (hub_dev, - "resume on port %d, status %d\n", - i, ret); - } - - if (portchange & USB_PORT_STAT_C_OVERCURRENT) { - dev_err (hub_dev, - "over-current change on port %d\n", - i); - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_OVER_CURRENT); - hub_power_on(hub); - } - - if (portchange & USB_PORT_STAT_C_RESET) { - dev_dbg (hub_dev, - "reset change on port %d\n", - i); - clear_port_feature(hdev, i, - USB_PORT_FEAT_C_RESET); - } - - if (connect_change) - hub_port_connect_change(hub, i, - portstatus, portchange); - } /* end for i */ + } /* deal with hub status changes */ if (test_and_clear_bit(0, hub->event_bits) == 0) @@ -2864,34 +5049,44 @@ static void hub_events(void) hub->limited_power = 0; } if (hubchange & HUB_CHANGE_OVERCURRENT) { - dev_dbg (hub_dev, "overcurrent change\n"); - msleep(500); /* Cool down */ + u16 status = 0; + u16 unused; + + dev_dbg(hub_dev, "over-current change\n"); clear_hub_feature(hdev, C_HUB_OVER_CURRENT); - hub_power_on(hub); + msleep(500); /* Cool down */ + hub_power_on(hub, true); + hub_hub_status(hub, &status, &unused); + if (status & HUB_STATUS_OVERCURRENT) + dev_err(hub_dev, "over-current " + "condition\n"); } } - hub->activating = 0; - - /* If this is a root hub, tell the HCD it's okay to - * re-enable port-change interrupts now. */ - if (!hdev->parent && !hub->busy_bits[0]) - usb_enable_root_hub_irq(hdev->bus); - -loop_autopm: - /* Allow autosuspend if we're not going to run again */ - if (list_empty(&hub->event_list)) - usb_autopm_enable(intf); -loop: + loop_autopm: + /* Balance the usb_autopm_get_interface() above */ + usb_autopm_put_interface_no_suspend(intf); + loop: + /* Balance the usb_autopm_get_interface_no_resume() in + * kick_khubd() and allow autosuspend. + */ + usb_autopm_put_interface(intf); + loop_disconnected: usb_unlock_device(hdev); kref_put(&hub->kref, hub_release); - } /* end while (1) */ + } /* end while (1) */ } static int hub_thread(void *__unused) { + /* khubd needs to be freezable to avoid interfering with USB-PERSIST + * port handover. Otherwise it might see that a full-speed device + * was gone before the EHCI controller had handed its port over to + * the companion full-speed controller. + */ set_freezable(); + do { hub_events(); wait_event_freezable(khubd_wait, @@ -2903,7 +5098,12 @@ static int hub_thread(void *__unused) return 0; } -static struct usb_device_id hub_id_table [] = { +static const struct usb_device_id hub_id_table[] = { + { .match_flags = USB_DEVICE_ID_MATCH_VENDOR + | USB_DEVICE_ID_MATCH_INT_CLASS, + .idVendor = USB_VENDOR_GENESYS_LOGIC, + .bInterfaceClass = USB_CLASS_HUB, + .driver_info = HUB_QUIRK_CHECK_PORT_AUTOSUSPEND}, { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, .bDeviceClass = USB_CLASS_HUB}, { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, @@ -2922,7 +5122,7 @@ static struct usb_driver hub_driver = { .reset_resume = hub_reset_resume, .pre_reset = hub_pre_reset, .post_reset = hub_post_reset, - .ioctl = hub_ioctl, + .unlocked_ioctl = hub_ioctl, .id_table = hub_id_table, .supports_autosuspend = 1, }; @@ -2960,16 +5160,47 @@ void usb_hub_cleanup(void) usb_deregister(&hub_driver); } /* usb_hub_cleanup() */ -static int config_descriptors_changed(struct usb_device *udev) +static int descriptors_changed(struct usb_device *udev, + struct usb_device_descriptor *old_device_descriptor, + struct usb_host_bos *old_bos) { - unsigned index; - unsigned len = 0; - struct usb_config_descriptor *buf; + int changed = 0; + unsigned index; + unsigned serial_len = 0; + unsigned len; + unsigned old_length; + int length; + char *buf; + + if (memcmp(&udev->descriptor, old_device_descriptor, + sizeof(*old_device_descriptor)) != 0) + return 1; + if ((old_bos && !udev->bos) || (!old_bos && udev->bos)) + return 1; + if (udev->bos) { + len = le16_to_cpu(udev->bos->desc->wTotalLength); + if (len != le16_to_cpu(old_bos->desc->wTotalLength)) + return 1; + if (memcmp(udev->bos->desc, old_bos->desc, len)) + return 1; + } + + /* Since the idVendor, idProduct, and bcdDevice values in the + * device descriptor haven't changed, we will assume the + * Manufacturer and Product strings haven't changed either. + * But the SerialNumber string could be different (e.g., a + * different flash card of the same brand). + */ + if (udev->serial) + serial_len = strlen(udev->serial) + 1; + + len = serial_len; for (index = 0; index < udev->descriptor.bNumConfigurations; index++) { - if (len < le16_to_cpu(udev->config[index].desc.wTotalLength)) - len = le16_to_cpu(udev->config[index].desc.wTotalLength); + old_length = le16_to_cpu(udev->config[index].desc.wTotalLength); + len = max(len, old_length); } + buf = kmalloc(len, GFP_NOIO); if (buf == NULL) { dev_err(&udev->dev, "no mem to re-read configs after reset\n"); @@ -2977,34 +5208,50 @@ static int config_descriptors_changed(struct usb_device *udev) return 1; } for (index = 0; index < udev->descriptor.bNumConfigurations; index++) { - int length; - int old_length = le16_to_cpu(udev->config[index].desc.wTotalLength); - + old_length = le16_to_cpu(udev->config[index].desc.wTotalLength); length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf, old_length); - if (length < old_length) { + if (length != old_length) { dev_dbg(&udev->dev, "config index %d, error %d\n", index, length); + changed = 1; break; } if (memcmp (buf, udev->rawdescriptors[index], old_length) != 0) { dev_dbg(&udev->dev, "config index %d changed (#%d)\n", - index, buf->bConfigurationValue); + index, + ((struct usb_config_descriptor *) buf)-> + bConfigurationValue); + changed = 1; break; } } + + if (!changed && serial_len) { + length = usb_string(udev, udev->descriptor.iSerialNumber, + buf, serial_len); + if (length + 1 != serial_len) { + dev_dbg(&udev->dev, "serial string error %d\n", + length); + changed = 1; + } else if (memcmp(buf, udev->serial, length) != 0) { + dev_dbg(&udev->dev, "serial string changed\n"); + changed = 1; + } + } + kfree(buf); - return index != udev->descriptor.bNumConfigurations; + return changed; } /** - * usb_reset_device - perform a USB port reset to reinitialize a device + * usb_reset_and_verify_device - perform a USB port reset to reinitialize a device * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) * * WARNING - don't use this routine to reset a composite device * (one with multiple interfaces owned by separate drivers)! - * Use usb_reset_composite_device() instead. + * Use usb_reset_device() instead. * * Do a port reset, reassign the device's address, and establish its * former operating configuration. If the reset fails, or the device's @@ -3014,26 +5261,32 @@ static int config_descriptors_changed(struct usb_device *udev) * re-connected. All drivers will be unbound, and the device will be * re-enumerated and probed all over again. * - * Returns 0 if the reset succeeded, -ENODEV if the device has been + * Return: 0 if the reset succeeded, -ENODEV if the device has been * flagged for logical disconnection, or some other negative error code * if the reset wasn't even attempted. * - * The caller must own the device lock. For example, it's safe to use - * this from a driver probe() routine after downloading new firmware. - * For calls that might not occur during probe(), drivers should lock - * the device using usb_lock_device_for_reset(). + * Note: + * The caller must own the device lock and the port lock, the latter is + * taken by usb_reset_device(). For example, it's safe to use + * usb_reset_device() from a driver probe() routine after downloading + * new firmware. For calls that might not occur during probe(), drivers + * should lock the device using usb_lock_device_for_reset(). * * Locking exception: This routine may also be called from within an * autoresume handler. Such usage won't conflict with other tasks * holding the device lock because these tasks should always call - * usb_autopm_resume_device(), thereby preventing any unwanted autoresume. + * usb_autopm_resume_device(), thereby preventing any unwanted + * autoresume. The autoresume handler is expected to have already + * acquired the port lock before calling this routine. */ -int usb_reset_device(struct usb_device *udev) +static int usb_reset_and_verify_device(struct usb_device *udev) { struct usb_device *parent_hdev = udev->parent; struct usb_hub *parent_hub; + struct usb_hcd *hcd = bus_to_hcd(udev->bus); struct usb_device_descriptor descriptor = udev->descriptor; - int i, ret = 0; + struct usb_host_bos *bos; + int i, j, ret = 0; int port1 = udev->portnum; if (udev->state == USB_STATE_NOTATTACHED || @@ -3043,41 +5296,70 @@ int usb_reset_device(struct usb_device *udev) return -EINVAL; } - if (!parent_hdev) { - /* this requires hcd-specific logic; see OHCI hc_restart() */ - dev_dbg(&udev->dev, "%s for root hub!\n", __FUNCTION__); + if (!parent_hdev) return -EISDIR; + + parent_hub = usb_hub_to_struct_hub(parent_hdev); + + /* Disable USB2 hardware LPM. + * It will be re-enabled by the enumeration process. + */ + if (udev->usb2_hw_lpm_enabled == 1) + usb_set_usb2_hardware_lpm(udev, 0); + + bos = udev->bos; + udev->bos = NULL; + + /* Disable LPM and LTM while we reset the device and reinstall the alt + * settings. Device-initiated LPM settings, and system exit latency + * settings are cleared when the device is reset, so we have to set + * them up again. + */ + ret = usb_unlocked_disable_lpm(udev); + if (ret) { + dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); + goto re_enumerate; + } + ret = usb_disable_ltm(udev); + if (ret) { + dev_err(&udev->dev, "%s Failed to disable LTM\n.", + __func__); + goto re_enumerate; } - parent_hub = hdev_to_hub(parent_hdev); - set_bit(port1, parent_hub->busy_bits); for (i = 0; i < SET_CONFIG_TRIES; ++i) { /* ep0 maxpacket size may change; let the HCD know about it. * Other endpoints will be handled by re-enumeration. */ - ep0_reinit(udev); + usb_ep0_reinit(udev); ret = hub_port_init(parent_hub, udev, port1, i); if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV) break; } - clear_bit(port1, parent_hub->busy_bits); - if (!parent_hdev->parent && !parent_hub->busy_bits[0]) - usb_enable_root_hub_irq(parent_hdev->bus); if (ret < 0) goto re_enumerate; - + /* Device might have changed firmware (DFU or similar) */ - if (memcmp(&udev->descriptor, &descriptor, sizeof descriptor) - || config_descriptors_changed (udev)) { + if (descriptors_changed(udev, &descriptor, bos)) { dev_info(&udev->dev, "device firmware changed\n"); udev->descriptor = descriptor; /* for disconnect() calls */ goto re_enumerate; - } - + } + + /* Restore the device's previous configuration */ if (!udev->actconfig) goto done; + mutex_lock(hcd->bandwidth_mutex); + ret = usb_hcd_alloc_bandwidth(udev, udev->actconfig, NULL, NULL); + if (ret < 0) { + dev_warn(&udev->dev, + "Busted HC? Not enough HCD resources for " + "old configuration.\n"); + mutex_unlock(hcd->bandwidth_mutex); + goto re_enumerate; + } ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_CONFIGURATION, 0, udev->actconfig->desc.bConfigurationValue, 0, @@ -3086,20 +5368,38 @@ int usb_reset_device(struct usb_device *udev) dev_err(&udev->dev, "can't restore configuration #%d (error=%d)\n", udev->actconfig->desc.bConfigurationValue, ret); + mutex_unlock(hcd->bandwidth_mutex); goto re_enumerate; - } + } + mutex_unlock(hcd->bandwidth_mutex); usb_set_device_state(udev, USB_STATE_CONFIGURED); + /* Put interfaces back into the same altsettings as before. + * Don't bother to send the Set-Interface request for interfaces + * that were already in altsetting 0; besides being unnecessary, + * many devices can't handle it. Instead just reset the host-side + * endpoint state. + */ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { - struct usb_interface *intf = udev->actconfig->interface[i]; + struct usb_host_config *config = udev->actconfig; + struct usb_interface *intf = config->interface[i]; struct usb_interface_descriptor *desc; - /* set_interface resets host side toggle even - * for altsetting zero. the interface may have no driver. - */ desc = &intf->cur_altsetting->desc; - ret = usb_set_interface(udev, desc->bInterfaceNumber, - desc->bAlternateSetting); + if (desc->bAlternateSetting == 0) { + usb_disable_interface(udev, intf, true); + usb_enable_interface(udev, intf, true); + ret = 0; + } else { + /* Let the bandwidth allocation function know that this + * device has been reset, and it will have to use + * alternate setting 0 as the current alternate setting. + */ + intf->resetting_device = 1; + ret = usb_set_interface(udev, desc->bInterfaceNumber, + desc->bAlternateSetting); + intf->resetting_device = 0; + } if (ret < 0) { dev_err(&udev->dev, "failed to restore interface %d " "altsetting %d (error=%d)\n", @@ -3108,39 +5408,57 @@ int usb_reset_device(struct usb_device *udev) ret); goto re_enumerate; } + /* Resetting also frees any allocated streams */ + for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++) + intf->cur_altsetting->endpoint[j].streams = 0; } done: + /* Now that the alt settings are re-installed, enable LTM and LPM. */ + usb_set_usb2_hardware_lpm(udev, 1); + usb_unlocked_enable_lpm(udev); + usb_enable_ltm(udev); + usb_release_bos_descriptor(udev); + udev->bos = bos; return 0; - + re_enumerate: + /* LPM state doesn't matter when we're about to destroy the device. */ hub_port_logical_disconnect(parent_hub, port1); + usb_release_bos_descriptor(udev); + udev->bos = bos; return -ENODEV; } -EXPORT_SYMBOL_GPL(usb_reset_device); /** - * usb_reset_composite_device - warn interface drivers and perform a USB port reset + * usb_reset_device - warn interface drivers and perform a USB port reset * @udev: device to reset (not in SUSPENDED or NOTATTACHED state) - * @iface: interface bound to the driver making the request (optional) * * Warns all drivers bound to registered interfaces (using their pre_reset * method), performs the port reset, and then lets the drivers know that * the reset is over (using their post_reset method). * - * Return value is the same as for usb_reset_device(). + * Return: The same as for usb_reset_and_verify_device(). * + * Note: * The caller must own the device lock. For example, it's safe to use * this from a driver probe() routine after downloading new firmware. * For calls that might not occur during probe(), drivers should lock * the device using usb_lock_device_for_reset(). + * + * If an interface is currently being probed or disconnected, we assume + * its driver knows how to handle resets. For all other interfaces, + * if the driver doesn't have pre_reset and post_reset methods then + * we attempt to unbind it and rebind afterward. */ -int usb_reset_composite_device(struct usb_device *udev, - struct usb_interface *iface) +int usb_reset_device(struct usb_device *udev) { int ret; int i; + unsigned int noio_flag; + struct usb_port *port_dev; struct usb_host_config *config = udev->actconfig; + struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); if (udev->state == USB_STATE_NOTATTACHED || udev->state == USB_STATE_SUSPENDED) { @@ -3149,43 +5467,206 @@ int usb_reset_composite_device(struct usb_device *udev, return -EINVAL; } + if (!udev->parent) { + /* this requires hcd-specific logic; see ohci_restart() */ + dev_dbg(&udev->dev, "%s for root hub!\n", __func__); + return -EISDIR; + } + + port_dev = hub->ports[udev->portnum - 1]; + + /* + * Don't allocate memory with GFP_KERNEL in current + * context to avoid possible deadlock if usb mass + * storage interface or usbnet interface(iSCSI case) + * is included in current configuration. The easist + * approach is to do it for every device reset, + * because the device 'memalloc_noio' flag may have + * not been set before reseting the usb device. + */ + noio_flag = memalloc_noio_save(); + /* Prevent autosuspend during the reset */ usb_autoresume_device(udev); - if (iface && iface->condition != USB_INTERFACE_BINDING) - iface = NULL; - if (config) { for (i = 0; i < config->desc.bNumInterfaces; ++i) { struct usb_interface *cintf = config->interface[i]; struct usb_driver *drv; + int unbind = 0; if (cintf->dev.driver) { drv = to_usb_driver(cintf->dev.driver); - if (drv->pre_reset) - (drv->pre_reset)(cintf); - /* FIXME: Unbind if pre_reset returns an error or isn't defined */ + if (drv->pre_reset && drv->post_reset) + unbind = (drv->pre_reset)(cintf); + else if (cintf->condition == + USB_INTERFACE_BOUND) + unbind = 1; + if (unbind) + usb_forced_unbind_intf(cintf); } } } - ret = usb_reset_device(udev); + usb_lock_port(port_dev); + ret = usb_reset_and_verify_device(udev); + usb_unlock_port(port_dev); if (config) { for (i = config->desc.bNumInterfaces - 1; i >= 0; --i) { struct usb_interface *cintf = config->interface[i]; struct usb_driver *drv; + int rebind = cintf->needs_binding; - if (cintf->dev.driver) { + if (!rebind && cintf->dev.driver) { drv = to_usb_driver(cintf->dev.driver); if (drv->post_reset) - (drv->post_reset)(cintf); - /* FIXME: Unbind if post_reset returns an error or isn't defined */ + rebind = (drv->post_reset)(cintf); + else if (cintf->condition == + USB_INTERFACE_BOUND) + rebind = 1; + if (rebind) + cintf->needs_binding = 1; } } + usb_unbind_and_rebind_marked_interfaces(udev); } usb_autosuspend_device(udev); + memalloc_noio_restore(noio_flag); return ret; } -EXPORT_SYMBOL_GPL(usb_reset_composite_device); +EXPORT_SYMBOL_GPL(usb_reset_device); + + +/** + * usb_queue_reset_device - Reset a USB device from an atomic context + * @iface: USB interface belonging to the device to reset + * + * This function can be used to reset a USB device from an atomic + * context, where usb_reset_device() won't work (as it blocks). + * + * Doing a reset via this method is functionally equivalent to calling + * usb_reset_device(), except for the fact that it is delayed to a + * workqueue. This means that any drivers bound to other interfaces + * might be unbound, as well as users from usbfs in user space. + * + * Corner cases: + * + * - Scheduling two resets at the same time from two different drivers + * attached to two different interfaces of the same device is + * possible; depending on how the driver attached to each interface + * handles ->pre_reset(), the second reset might happen or not. + * + * - If a driver is unbound and it had a pending reset, the reset will + * be cancelled. + * + * - This function can be called during .probe() or .disconnect() + * times. On return from .disconnect(), any pending resets will be + * cancelled. + * + * There is no no need to lock/unlock the @reset_ws as schedule_work() + * does its own. + * + * NOTE: We don't do any reference count tracking because it is not + * needed. The lifecycle of the work_struct is tied to the + * usb_interface. Before destroying the interface we cancel the + * work_struct, so the fact that work_struct is queued and or + * running means the interface (and thus, the device) exist and + * are referenced. + */ +void usb_queue_reset_device(struct usb_interface *iface) +{ + schedule_work(&iface->reset_ws); +} +EXPORT_SYMBOL_GPL(usb_queue_reset_device); + +/** + * usb_hub_find_child - Get the pointer of child device + * attached to the port which is specified by @port1. + * @hdev: USB device belonging to the usb hub + * @port1: port num to indicate which port the child device + * is attached to. + * + * USB drivers call this function to get hub's child device + * pointer. + * + * Return: %NULL if input param is invalid and + * child's usb_device pointer if non-NULL. + */ +struct usb_device *usb_hub_find_child(struct usb_device *hdev, + int port1) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + + if (port1 < 1 || port1 > hdev->maxchild) + return NULL; + return hub->ports[port1 - 1]->child; +} +EXPORT_SYMBOL_GPL(usb_hub_find_child); + +void usb_hub_adjust_deviceremovable(struct usb_device *hdev, + struct usb_hub_descriptor *desc) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + enum usb_port_connect_type connect_type; + int i; + + if (!hub) + return; + + if (!hub_is_superspeed(hdev)) { + for (i = 1; i <= hdev->maxchild; i++) { + struct usb_port *port_dev = hub->ports[i - 1]; + + connect_type = port_dev->connect_type; + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u8 mask = 1 << (i%8); + + if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) { + dev_dbg(&port_dev->dev, "DeviceRemovable is changed to 1 according to platform information.\n"); + desc->u.hs.DeviceRemovable[i/8] |= mask; + } + } + } + } else { + u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable); + + for (i = 1; i <= hdev->maxchild; i++) { + struct usb_port *port_dev = hub->ports[i - 1]; + + connect_type = port_dev->connect_type; + if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) { + u16 mask = 1 << i; + + if (!(port_removable & mask)) { + dev_dbg(&port_dev->dev, "DeviceRemovable is changed to 1 according to platform information.\n"); + port_removable |= mask; + } + } + } + + desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable); + } +} + +#ifdef CONFIG_ACPI +/** + * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle + * @hdev: USB device belonging to the usb hub + * @port1: port num of the port + * + * Return: Port's acpi handle if successful, %NULL if params are + * invalid. + */ +acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, + int port1) +{ + struct usb_hub *hub = usb_hub_to_struct_hub(hdev); + + if (!hub) + return NULL; + + return ACPI_HANDLE(&hub->ports[port1 - 1]->dev); +} +#endif |
