diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-11 15:40:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-11 15:40:06 -0700 |
commit | 17a20acaf171124017f43bc70bb4d7ca88070659 (patch) | |
tree | 8bc639ee52ed71fcfb32496dd4f16e03bdbf29b4 /drivers/usb/core | |
parent | d72619706abc4aa7e540ea882dae883cee7cc3b3 (diff) | |
parent | 2bc8bb813cba6e699b29fd0b30720288866a5e5d (diff) | |
download | linux-17a20acaf171124017f43bc70bb4d7ca88070659.tar.bz2 |
Merge tag 'usb-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / PHY updates from Greg KH:
"Here is the big USB and PHY driver pull request for 5.3-rc1.
Lots of stuff here, all of which has been in linux-next for a while
with no reported issues. Nothing is earth-shattering, just constant
forward progress for more devices supported and cleanups and small
fixes:
- USB gadget driver updates and fixes
- new USB gadget driver for some hardware, followed by a quick revert
of those patches as they were not ready to be merged...
- PHY driver updates
- Lots of new driver additions and cleanups with a few fixes mixed
in"
* tag 'usb-5.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (145 commits)
Revert "usb: gadget: storage: Remove warning message"
Revert "dt-bindings: add binding for USBSS-DRD controller."
Revert "usb:gadget Separated decoding functions from dwc3 driver."
Revert "usb:gadget Patch simplify usb_decode_set_clear_feature function."
Revert "usb:gadget Simplify usb_decode_get_set_descriptor function."
Revert "usb:cdns3 Add Cadence USB3 DRD Driver"
Revert "usb:cdns3 Fix for stuck packets in on-chip OUT buffer."
usb :fsl: Change string format for errata property
usb: host: Stops USB controller init if PLL fails to lock
usb: linux/fsl_device: Add platform member has_fsl_erratum_a006918
usb: phy: Workaround for USB erratum-A005728
usb: fsl: Set USB_EN bit to select ULPI phy
usb: Handle USB3 remote wakeup for LPM enabled devices correctly
drivers/usb/typec/tps6598x.c: fix 4CC cmd write
drivers/usb/typec/tps6598x.c: fix portinfo width
usb: storage: scsiglue: Do not skip VPD if try_vpd_pages is set
usb: renesas_usbhs: add a workaround for a race condition of workqueue
usb: gadget: udc: renesas_usb3: remove redundant assignment to ret
usb: dwc2: use a longer AHB idle timeout in dwc2_core_reset()
USB: gadget: function: fix issue Unneeded variable: "value"
...
Diffstat (limited to 'drivers/usb/core')
-rw-r--r-- | drivers/usb/core/Kconfig | 1 | ||||
-rw-r--r-- | drivers/usb/core/devio.c | 71 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 45 | ||||
-rw-r--r-- | drivers/usb/core/notify.c | 3 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 10 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 1 |
6 files changed, 81 insertions, 50 deletions
diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index bdb6bd0b63a6..ecaacc8ed311 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -45,7 +45,6 @@ config USB_DYNAMIC_MINORS config USB_OTG bool "OTG support" depends on PM - default n help The most notable feature of USB OTG is support for a "Dual-Role" device, which can act as either a device diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index a02448105527..e2f316ac8b01 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -48,9 +48,6 @@ #define USB_DEVICE_MAX (USB_MAXBUS * 128) #define USB_SG_SIZE 16384 /* split-size for large txs */ -/* Mutual exclusion for removal, open, and release */ -DEFINE_MUTEX(usbfs_mutex); - struct usb_dev_state { struct list_head list; /* state list */ struct usb_device *dev; @@ -977,15 +974,9 @@ static int usbdev_open(struct inode *inode, struct file *file) ret = -ENODEV; - /* Protect against simultaneous removal or release */ - mutex_lock(&usbfs_mutex); - /* usbdev device-node */ if (imajor(inode) == USB_DEVICE_MAJOR) dev = usbdev_lookup_by_devt(inode->i_rdev); - - mutex_unlock(&usbfs_mutex); - if (!dev) goto out_free_ps; @@ -1306,6 +1297,39 @@ static int proc_connectinfo(struct usb_dev_state *ps, void __user *arg) return 0; } +static int proc_conninfo_ex(struct usb_dev_state *ps, + void __user *arg, size_t size) +{ + struct usbdevfs_conninfo_ex ci; + struct usb_device *udev = ps->dev; + + if (size < sizeof(ci.size)) + return -EINVAL; + + memset(&ci, 0, sizeof(ci)); + ci.size = sizeof(ci); + ci.busnum = udev->bus->busnum; + ci.devnum = udev->devnum; + ci.speed = udev->speed; + + while (udev && udev->portnum != 0) { + if (++ci.num_ports <= ARRAY_SIZE(ci.ports)) + ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports] = + udev->portnum; + udev = udev->parent; + } + + if (ci.num_ports < ARRAY_SIZE(ci.ports)) + memmove(&ci.ports[0], + &ci.ports[ARRAY_SIZE(ci.ports) - ci.num_ports], + ci.num_ports); + + if (copy_to_user(arg, &ci, min(sizeof(ci), size))) + return -EFAULT; + + return 0; +} + static int proc_resetdevice(struct usb_dev_state *ps) { struct usb_host_config *actconfig = ps->dev->actconfig; @@ -1484,15 +1508,15 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb ret = -EFAULT; goto error; } - if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) { + if (uurb->buffer_length < (le16_to_cpu(dr->wLength) + 8)) { ret = -EINVAL; goto error; } ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest, - le16_to_cpup(&dr->wIndex)); + le16_to_cpu(dr->wIndex)); if (ret) goto error; - uurb->buffer_length = le16_to_cpup(&dr->wLength); + uurb->buffer_length = le16_to_cpu(dr->wLength); uurb->buffer += 8; if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) { is_in = 1; @@ -1507,9 +1531,9 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb "bRequest=%02x wValue=%04x " "wIndex=%04x wLength=%04x\n", dr->bRequestType, dr->bRequest, - __le16_to_cpup(&dr->wValue), - __le16_to_cpup(&dr->wIndex), - __le16_to_cpup(&dr->wLength)); + __le16_to_cpu(dr->wValue), + __le16_to_cpu(dr->wIndex), + __le16_to_cpu(dr->wLength)); u = sizeof(struct usb_ctrlrequest); break; @@ -2137,6 +2161,9 @@ static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) if (ps->privileges_dropped) return -EACCES; + if (!connected(ps)) + return -ENODEV; + /* alloc buffer */ size = _IOC_SIZE(ctl->ioctl_code); if (size > 0) { @@ -2153,11 +2180,6 @@ static int proc_ioctl(struct usb_dev_state *ps, struct usbdevfs_ioctl *ctl) } } - if (!connected(ps)) { - kfree(buf); - return -ENODEV; - } - if (ps->dev->state != USB_STATE_CONFIGURED) retval = -EHOSTUNREACH; else if (!(intf = usb_ifnum_to_if(ps->dev, ctl->ifno))) @@ -2259,7 +2281,7 @@ static int proc_get_capabilities(struct usb_dev_state *ps, void __user *arg) caps = USBDEVFS_CAP_ZERO_PACKET | USBDEVFS_CAP_NO_PACKET_SIZE_LIM | USBDEVFS_CAP_REAP_AFTER_DISCONNECT | USBDEVFS_CAP_MMAP | - USBDEVFS_CAP_DROP_PRIVILEGES; + USBDEVFS_CAP_DROP_PRIVILEGES | USBDEVFS_CAP_CONNINFO_EX; if (!ps->dev->bus->no_stop_on_short) caps |= USBDEVFS_CAP_BULK_CONTINUATION; if (ps->dev->bus->sg_tablesize) @@ -2558,6 +2580,13 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, break; } + /* Handle variable-length commands */ + switch (cmd & ~IOCSIZE_MASK) { + case USBDEVFS_CONNINFO_EX(0): + ret = proc_conninfo_ex(ps, p, _IOC_SIZE(cmd)); + break; + } + done: usb_unlock_device(dev); if (ret >= 0) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 2f94568ba385..236313f41f4a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -873,7 +873,7 @@ int usb_hub_clear_tt_buffer(struct urb *urb) /* info that CLEAR_TT_BUFFER needs */ clear->tt = tt->multi ? udev->ttport : 1; clear->devinfo = usb_pipeendpoint (pipe); - clear->devinfo |= udev->devnum << 4; + clear->devinfo |= ((u16)udev->devaddr) << 4; clear->devinfo |= usb_pipecontrol(pipe) ? (USB_ENDPOINT_XFER_CONTROL << 11) : (USB_ENDPOINT_XFER_BULK << 11); @@ -2125,6 +2125,8 @@ 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; + if (!udev->devaddr) + udev->devaddr = (u8)devnum; } static void hub_free_dev(struct usb_device *udev) @@ -2719,7 +2721,7 @@ static bool use_new_scheme(struct usb_device *udev, int retry, } /* Is a USB 3.0 port in the Inactive or Compliance Mode state? - * Port worm reset is required to recover + * Port warm reset is required to recover */ static bool hub_port_warm_reset_required(struct usb_hub *hub, int port1, u16 portstatus) @@ -3617,6 +3619,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, struct usb_device *hdev; struct usb_device *udev; int connect_change = 0; + u16 link_state; int ret; hdev = hub->hdev; @@ -3626,9 +3629,11 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, return 0; usb_clear_port_feature(hdev, port, USB_PORT_FEAT_C_SUSPEND); } else { + link_state = portstatus & USB_PORT_STAT_LINK_STATE; if (!udev || udev->state != USB_STATE_SUSPENDED || - (portstatus & USB_PORT_STAT_LINK_STATE) != - USB_SS_PORT_LS_U0) + (link_state != USB_SS_PORT_LS_U0 && + link_state != USB_SS_PORT_LS_U1 && + link_state != USB_SS_PORT_LS_U2)) return 0; } @@ -3999,6 +4004,9 @@ static int usb_set_lpm_timeout(struct usb_device *udev, * control transfers to set the hub timeout or enable device-initiated U1/U2 * will be successful. * + * If the control transfer to enable device-initiated U1/U2 entry fails, then + * hub-initiated U1/U2 will be disabled. + * * 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. @@ -4053,23 +4061,24 @@ static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev, * host know that this link state won't be enabled. */ hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); - } else { - /* Only a configured device will accept the Set Feature - * U1/U2_ENABLE - */ - if (udev->actconfig) - usb_set_device_initiated_lpm(udev, state, true); + return; + } - /* As soon as usb_set_lpm_timeout(timeout) returns 0, the - * hub-initiated LPM is enabled. Thus, LPM is enabled no - * matter the result of usb_set_device_initiated_lpm(). - * The only difference is whether device is able to initiate - * LPM. - */ + /* Only a configured device will accept the Set Feature + * U1/U2_ENABLE + */ + if (udev->actconfig && + usb_set_device_initiated_lpm(udev, state, true) == 0) { if (state == USB3_LPM_U1) udev->usb3_lpm_u1_enabled = 1; else if (state == USB3_LPM_U2) udev->usb3_lpm_u2_enabled = 1; + } else { + /* Don't request U1/U2 entry if the device + * cannot transition to U1/U2. + */ + usb_set_lpm_timeout(udev, state, 0); + hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state); } } @@ -4139,7 +4148,7 @@ int usb_disable_lpm(struct usb_device *udev) if (!udev || !udev->parent || udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || - udev->state < USB_STATE_DEFAULT) + udev->state < USB_STATE_CONFIGURED) return 0; hcd = bus_to_hcd(udev->bus); @@ -4198,7 +4207,7 @@ void usb_enable_lpm(struct usb_device *udev) if (!udev || !udev->parent || udev->speed < USB_SPEED_SUPER || !udev->lpm_capable || - udev->state < USB_STATE_DEFAULT) + udev->state < USB_STATE_CONFIGURED) return; udev->lpm_disable_count--; diff --git a/drivers/usb/core/notify.c b/drivers/usb/core/notify.c index ab474b11523e..e6143663778f 100644 --- a/drivers/usb/core/notify.c +++ b/drivers/usb/core/notify.c @@ -53,11 +53,8 @@ void usb_notify_add_device(struct usb_device *udev) void usb_notify_remove_device(struct usb_device *udev) { - /* Protect against simultaneous usbfs open */ - mutex_lock(&usbfs_mutex); blocking_notifier_call_chain(&usb_notifier_list, USB_DEVICE_REMOVE, udev); - mutex_unlock(&usbfs_mutex); } void usb_notify_add_bus(struct usb_bus *ubus) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 7fcb9f782931..5a0df527a8ca 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1185,19 +1185,17 @@ static struct notifier_block usb_bus_nb = { .notifier_call = usb_bus_notify, }; -struct dentry *usb_debug_root; -EXPORT_SYMBOL_GPL(usb_debug_root); +static struct dentry *usb_devices_root; static void usb_debugfs_init(void) { - usb_debug_root = debugfs_create_dir("usb", NULL); - debugfs_create_file("devices", 0444, usb_debug_root, NULL, - &usbfs_devices_fops); + usb_devices_root = debugfs_create_file("devices", 0444, usb_debug_root, + NULL, &usbfs_devices_fops); } static void usb_debugfs_cleanup(void) { - debugfs_remove_recursive(usb_debug_root); + debugfs_remove(usb_devices_root); } /* diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index d95a5358f73d..bd8d01f85a13 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -169,7 +169,6 @@ extern const struct attribute_group *usb_device_groups[]; extern const struct attribute_group *usb_interface_groups[]; /* usbfs stuff */ -extern struct mutex usbfs_mutex; extern struct usb_driver usbfs_driver; extern const struct file_operations usbfs_devices_fops; extern const struct file_operations usbdev_file_operations; |