#define USB_VENDOR_GENESYS_LOGIC 0x05e3
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
+extern int deny_new_usb;
+
/* Protect struct usb_device->state and ->children members
* Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
USB_PORT_FEAT_ENABLE);
}
+ /*
+ * Add debounce if USB3 link is in polling/link training state.
+ * Link will automatically transition to Enabled state after
+ * link training completes.
+ */
+ if (hub_is_superspeed(hdev) &&
+ ((portstatus & USB_PORT_STAT_LINK_STATE) ==
+ USB_SS_PORT_LS_POLLING))
+ need_debounce_delay = true;
+
/* Clear status-change flags; we'll debounce later */
if (portchange & USB_PORT_STAT_C_CONNECTION) {
need_debounce_delay = true;
struct usb_host_interface *desc;
struct usb_device *hdev;
struct usb_hub *hub;
+ struct usb_hcd *hcd;
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
* usbcore.autosuspend = -1 then keep autosuspend disabled.
*/
#ifdef CONFIG_PM
- if (hdev->dev.power.autosuspend_delay >= 0)
+ /*
+ * bus suspend is executed before USB3.0 hub and devices are detected,
+ * which causes USB3.0 hub and devices aren't recognized when l2 sleep is enabled.
+ * Restoring suspend delay will resolve USB3.0 hub detect issue.
+ */
+ hcd = bus_to_hcd(hdev->bus);
+ if ((hdev->dev.power.autosuspend_delay >= 0) && !hcd->driver->usb_l2_check(hcd))
pm_runtime_set_autosuspend_delay(&hdev->dev, 0);
#endif
/* descriptor may appear anywhere in config */
err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
le16_to_cpu(udev->config[0].desc.wTotalLength),
- USB_DT_OTG, (void **) &desc);
+ USB_DT_OTG, (void **) &desc, sizeof(*desc));
if (err || !(desc->bmAttributes & USB_OTG_HNP))
return 0;
goto done;
return;
}
+
+ if (deny_new_usb) {
+ dev_err(&port_dev->dev, "denied insert of USB device on port %d\n", port1);
+ goto done;
+ }
+
if (hub_is_superspeed(hub->hdev))
unit_load = 150;
else
struct usb_interface *intf;
struct usb_hub *hub;
struct device *hub_dev;
+ struct usb_hcd *hcd;
u16 hubstatus;
u16 hubchange;
int i, ret;
hub = container_of(work, struct usb_hub, events);
hdev = hub->hdev;
hub_dev = hub->intfdev;
+ hcd = bus_to_hcd(hdev->bus);
intf = to_usb_interface(hub_dev);
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
/* Lock the device, then check to see if we were
* disconnected while waiting for the lock to succeed. */
usb_lock_device(hdev);
+ hcd->is_in_hub_event = true;
if (unlikely(hub->disconnected))
goto out_hdev_lock;
/* Balance the usb_autopm_get_interface() above */
usb_autopm_put_interface_no_suspend(intf);
out_hdev_lock:
+ hcd->is_in_hub_event = false;
usb_unlock_device(hdev);
/* Balance the stuff in kick_hub_wq() and allow autosuspend */