From ed194d1367698a0872a2b75bbe06b3932ce9df3a Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2018 11:20:00 +0200 Subject: usb: core: remove local_irq_save() around ->complete() handler The core disabled interrupts before invocation the ->complete handler because the handler might have expected that interrupts are disabled. All handlers were audited and use proper locking now. With it, the core code no longer needs to disable interrupts before invoking the ->complete handler. Remove local_irq_save() statement before invoking the ->complete handler. Signed-off-by: Sebastian Andrzej Siewior Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 1c21955fe7c0..f985d2303095 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1755,20 +1755,7 @@ static void __usb_hcd_giveback_urb(struct urb *urb) /* pass ownership to the completion handler */ urb->status = status; - - /* - * We disable local IRQs here avoid possible deadlock because - * drivers may call spin_lock() to hold lock which might be - * acquired in one hard interrupt handler. - * - * The local_irq_save()/local_irq_restore() around complete() - * will be removed if current USB drivers have been cleaned up - * and no one may trigger the above deadlock situation when - * running complete() in tasklet. - */ - local_irq_save(flags); urb->complete(urb); - local_irq_restore(flags); usb_anchor_resume_wakeups(anchor); atomic_dec(&urb->use_count); -- cgit v1.2.3 From 71741bd6776aff40bc6e57d458a65d7e41190274 Mon Sep 17 00:00:00 2001 From: Salil Kapur Date: Sun, 5 Aug 2018 21:28:08 -0700 Subject: USB: Removing NULL check for pool since dma_pool_destroy is safe Removing NULL check for pool since dma_pool_destroy is safe Signed-off-by: Salil Kapur Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/buffer.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index 77eef8acff94..f641342cdec0 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -101,12 +101,8 @@ void hcd_buffer_destroy(struct usb_hcd *hcd) return; for (i = 0; i < HCD_BUFFER_POOLS; i++) { - struct dma_pool *pool = hcd->pool[i]; - - if (pool) { - dma_pool_destroy(pool); - hcd->pool[i] = NULL; - } + dma_pool_destroy(hcd->pool[i]); + hcd->pool[i] = NULL; } } -- cgit v1.2.3 From 0a6ab90c0a8fc8ece91ad2bf7e3310ebb563b32b Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Fri, 31 Aug 2018 18:01:54 +0800 Subject: usb: core: phy: clean up return value check about devm_of_phy_get_by_index() Use IS_ERR() instead of IS_ERR_OR_NULL() because devm_of_phy_get_by_index() never return NULL value; But still need ignore the error of -ENODEV, for more information, please refer to: [0] https://lkml.org/lkml/2018/4/19/88 [1] https://patchwork.kernel.org/patch/10160181/ Signed-off-by: Chunfeng Yun Reviewed-by: Johan Hovold Reviewed-by: Martin Blumenstingl Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/phy.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/phy.c b/drivers/usb/core/phy.c index 9879767452a2..38b2c776c4b4 100644 --- a/drivers/usb/core/phy.c +++ b/drivers/usb/core/phy.c @@ -23,10 +23,11 @@ static int usb_phy_roothub_add_phy(struct device *dev, int index, struct list_head *list) { struct usb_phy_roothub *roothub_entry; - struct phy *phy = devm_of_phy_get_by_index(dev, dev->of_node, index); + struct phy *phy; - if (IS_ERR_OR_NULL(phy)) { - if (!phy || PTR_ERR(phy) == -ENODEV) + phy = devm_of_phy_get_by_index(dev, dev->of_node, index); + if (IS_ERR(phy)) { + if (PTR_ERR(phy) == -ENODEV) return 0; else return PTR_ERR(phy); -- cgit v1.2.3 From d6142b91e9cc249b3aa22c90fade67e2e2d52cdb Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 11 Sep 2018 09:37:12 +0200 Subject: usb: core: remove flags variable in __usb_hcd_giveback_urb() In commit ed194d1367698 ("usb: core: remove local_irq_save() around ->complete() handler") I removed the only user of the flags variable and forgot to remove the variable, leading to warning because it is unused now. Remove the unused variable. Fixes: ed194d1367698 ("usb: core: remove local_irq_save() around ->complete() handler") Reported-by: Stephen Rothwell Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Gustavo A. R. Silva Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f985d2303095..487025d31d44 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1738,7 +1738,6 @@ static void __usb_hcd_giveback_urb(struct urb *urb) struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus); struct usb_anchor *anchor = urb->anchor; int status = urb->unlinked; - unsigned long flags; urb->hcpriv = NULL; if (unlikely((urb->transfer_flags & URB_SHORT_NOT_OK) && -- cgit v1.2.3 From f13912d3f014a7f2fa5c35d25ee8c3f96bda6272 Mon Sep 17 00:00:00 2001 From: Saranya Gopal Date: Wed, 12 Sep 2018 08:46:26 +0530 Subject: usbcore: Select UAC3 configuration for audio if present USB audio class 3.0 specification introduced many significant changes like - new power domains, support for LPM/L1 - new cluster descriptor - new high capability and class-specific string descriptors - BADD profiles - ... and many other things (check spec from link below: http://www.usb.org/developers/docs/devclass_docs/USB_Audio_v3.0.zip) Now that UAC3 is supported in linux, choose UAC3 configuration for audio if the device supports it. Selecting this configuration will enable the system to save power by leveraging the new power domains and LPM L1 capability and also support new codec types and data formats for consumer audio applications. Signed-off-by: Saranya Gopal Reviewed-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/generic.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c index bc8242bc4564..356b05c82dbc 100644 --- a/drivers/usb/core/generic.c +++ b/drivers/usb/core/generic.c @@ -21,6 +21,7 @@ #include #include +#include #include "usb.h" static inline const char *plural(int n) @@ -42,6 +43,16 @@ static int is_activesync(struct usb_interface_descriptor *desc) && desc->bInterfaceProtocol == 1; } +static bool is_audio(struct usb_interface_descriptor *desc) +{ + return desc->bInterfaceClass == USB_CLASS_AUDIO; +} + +static bool is_uac3_config(struct usb_interface_descriptor *desc) +{ + return desc->bInterfaceProtocol == UAC_VERSION_3; +} + int usb_choose_configuration(struct usb_device *udev) { int i; @@ -121,6 +132,22 @@ int usb_choose_configuration(struct usb_device *udev) #endif } + /* + * Select first configuration as default for audio so that + * devices that don't comply with UAC3 protocol are supported. + * But, still iterate through other configurations and + * select UAC3 compliant config if present. + */ + if (i == 0 && num_configs > 1 && desc && is_audio(desc)) { + best = c; + continue; + } + + if (i > 0 && desc && is_audio(desc) && is_uac3_config(desc)) { + best = c; + break; + } + /* From the remaining configs, choose the first one whose * first interface is for a non-vendor-specific class. * Reason: Linux is more likely to have a class driver -- cgit v1.2.3 From 201af55da8a3986297d7c3493f839dfc96ffd7db Mon Sep 17 00:00:00 2001 From: Jon Flatley Date: Thu, 20 Sep 2018 10:17:54 -0700 Subject: usb: core: added uevent for over-current After commit 1cbd53c8cd85 ("usb: core: introduce per-port over-current counters") usb ports expose a sysfs value 'over_current_count' to user space. This value on its own is not very useful as it requires manual polling. As a solution, fire a udev event from the usb hub device that specifies the values 'OVER_CURRENT_PORT' and 'OVER_CURRENT_COUNT' that indicate the path of the usb port where the over-current event occurred and the value of 'over_current_count' in sysfs. Additionally, call sysfs_notify() so the sysfs value supports poll(). Signed-off-by: Jon Flatley Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-usb | 9 ++++++++- drivers/usb/core/hub.c | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers/usb/core') diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 08d456e07b53..c4a70f532ec3 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -219,7 +219,14 @@ Description: ports and report them to the kernel. This attribute is to expose the number of over-current situation occurred on a specific port to user space. This file will contain an unsigned 32 bit value - which wraps to 0 after its maximum is reached. + which wraps to 0 after its maximum is reached. This file supports + poll() for monitoring changes to this value in user space. + + Any time this value changes the corresponding hub device will send a + udev event with the following attributes: + + OVER_CURRENT_PORT=/sys/bus/usb/devices/.../(hub interface)/portX + OVER_CURRENT_COUNT=[current value of this sysfs attribute] What: /sys/bus/usb/devices/.../(hub interface)/portX/usb3_lpm_permit Date: November 2015 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 462ce49f683a..7801bb30bdba 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -5147,6 +5148,40 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, usb_lock_port(port_dev); } +/* Handle notifying userspace about hub over-current events */ +static void port_over_current_notify(struct usb_port *port_dev) +{ + static char *envp[] = { NULL, NULL, NULL }; + struct device *hub_dev; + char *port_dev_path; + + sysfs_notify(&port_dev->dev.kobj, NULL, "over_current_count"); + + hub_dev = port_dev->dev.parent; + + if (!hub_dev) + return; + + port_dev_path = kobject_get_path(&port_dev->dev.kobj, GFP_KERNEL); + if (!port_dev_path) + return; + + envp[0] = kasprintf(GFP_KERNEL, "OVER_CURRENT_PORT=%s", port_dev_path); + if (!envp[0]) + return; + + envp[1] = kasprintf(GFP_KERNEL, "OVER_CURRENT_COUNT=%u", + port_dev->over_current_count); + if (!envp[1]) + goto exit; + + kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp); + + kfree(envp[1]); +exit: + kfree(envp[0]); +} + static void port_event(struct usb_hub *hub, int port1) __must_hold(&port_dev->status_lock) { @@ -5189,6 +5224,7 @@ static void port_event(struct usb_hub *hub, int port1) if (portchange & USB_PORT_STAT_C_OVERCURRENT) { u16 status = 0, unused; port_dev->over_current_count++; + port_over_current_notify(port_dev); dev_dbg(&port_dev->dev, "over-current change #%u\n", port_dev->over_current_count); -- cgit v1.2.3 From bd0e6c9614b95352eb31d0207df16dc156c527fa Mon Sep 17 00:00:00 2001 From: Zeng Tao Date: Fri, 28 Sep 2018 19:27:52 +0800 Subject: usb: hub: try old enumeration scheme first for high speed devices The new scheme is required just to support legacy low and full-speed devices. For high speed devices, it will slower the enumeration speed. So in this patch we try the "old" enumeration scheme first for high speed devices, and this is what Windows does since Windows 8. Signed-off-by: Zeng Tao Acked-by: Alan Stern Reviewed-by: Roger Quadros Signed-off-by: Greg Kroah-Hartman --- Documentation/admin-guide/kernel-parameters.txt | 3 ++- drivers/usb/core/hub.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/usb/core') diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 92eb1f42240d..151c527571e5 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -4610,7 +4610,8 @@ usbcore.old_scheme_first= [USB] Start with the old device initialization - scheme (default 0 = off). + scheme, applies only to low and full-speed devices + (default 0 = off). usbcore.usbfs_memory_mb= [USB] Memory limit (in MB) for buffers allocated by diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7801bb30bdba..bf76a3dd4359 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2661,11 +2661,13 @@ static bool use_new_scheme(struct usb_device *udev, int retry, { int old_scheme_first_port = port_dev->quirks & USB_PORT_QUIRK_OLD_SCHEME; + int quick_enumeration = (udev->speed == USB_SPEED_HIGH); if (udev->speed >= USB_SPEED_SUPER) return false; - return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first); + return USE_NEW_SCHEME(retry, old_scheme_first_port || old_scheme_first + || quick_enumeration); } /* Is a USB 3.0 port in the Inactive or Compliance Mode state? -- cgit v1.2.3 From 355c74e55e9992126ec5e568a3edb8e280fe040d Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Fri, 28 Sep 2018 15:40:31 +0200 Subject: usb: export firmware port location in sysfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform firmware "location" data is used to find port peer relationships. But firmware is an unreliable source, and there are real world examples of errors leading to missing or wrong peer relationships. Debugging this is currently hard. Exporting the location attribute makes it easier to spot mismatches between the firmware data and the real world. Signed-off-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-usb | 10 ++++++++++ drivers/usb/core/port.c | 10 ++++++++++ 2 files changed, 20 insertions(+) (limited to 'drivers/usb/core') diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index c4a70f532ec3..559baa5c418c 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -189,6 +189,16 @@ Description: The file will read "hotplug", "wired" and "not used" if the information is available, and "unknown" otherwise. +What: /sys/bus/usb/devices/.../(hub interface)/portX/location +Date: October 2018 +Contact: Bjørn Mork +Description: + Some platforms provide usb port physical location through + firmware. This is used by the kernel to pair up logical ports + mapping to the same physical connector. The attribute exposes the + raw location value as a hex integer. + + What: /sys/bus/usb/devices/.../(hub interface)/portX/quirks Date: May 2018 Contact: Nicolas Boichat diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 4a2143195395..1a06a4b5fbb1 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -16,6 +16,15 @@ static int usb_port_block_power_off; static const struct attribute_group *port_dev_group[]; +static ssize_t location_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_port *port_dev = to_usb_port(dev); + + return sprintf(buf, "0x%08x\n", port_dev->location); +} +static DEVICE_ATTR_RO(location); + static ssize_t connect_type_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -140,6 +149,7 @@ static DEVICE_ATTR_RW(usb3_lpm_permit); static struct attribute *port_dev_attrs[] = { &dev_attr_connect_type.attr, + &dev_attr_location.attr, &dev_attr_quirks.attr, &dev_attr_over_current_count.attr, NULL, -- cgit v1.2.3 From bf7f547ecdd707e7b4fcbc467b4f9ddb29915391 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 3 Oct 2018 10:59:57 +0100 Subject: usb: core: fix memory leak on port_dev_path allocation Currently the allocation of port_dev_path from the call to kobject_get_path is not being kfree'd, causing a memory leak. Fix this by kfree'ing this at the end of the function. Add an extra error exit path to fix one of the early leaks when envp[0] fails to be allocated. Detected by CoverityScan, CID#1473771 ("Resource Leak") Fixes: 201af55da8a3 ("usb: core: added uevent for over-current") Signed-off-by: Colin Ian King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index bf76a3dd4359..c6077d582d29 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5170,7 +5170,7 @@ static void port_over_current_notify(struct usb_port *port_dev) envp[0] = kasprintf(GFP_KERNEL, "OVER_CURRENT_PORT=%s", port_dev_path); if (!envp[0]) - return; + goto exit_path; envp[1] = kasprintf(GFP_KERNEL, "OVER_CURRENT_COUNT=%u", port_dev->over_current_count); @@ -5182,6 +5182,8 @@ static void port_over_current_notify(struct usb_port *port_dev) kfree(envp[1]); exit: kfree(envp[0]); +exit_path: + kfree(port_dev_path); } static void port_event(struct usb_hub *hub, int port1) -- cgit v1.2.3 From c36e96bd259d5ec1e73c2cbfdc3ef935e6b0f830 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 4 Oct 2018 03:06:12 +0000 Subject: USB: core: remove set but not used variable 'udev' Fixes gcc '-Wunused-but-set-variable' warning: drivers/usb/core/driver.c: In function 'usb_driver_claim_interface': drivers/usb/core/driver.c:513:21: warning: variable 'udev' set but not used [-Wunused-but-set-variable] Since commit c183813fcee44a24 ("USB: remove LPM management from usb_driver_claim_interface()"), 'udev' is not used. Signed-off-by: YueHaibing Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/usb/core') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a1f225f077cd..53564386ed57 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -510,7 +510,6 @@ int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv) { struct device *dev; - struct usb_device *udev; int retval = 0; if (!iface) @@ -524,8 +523,6 @@ int usb_driver_claim_interface(struct usb_driver *driver, if (!iface->authorized) return -ENODEV; - udev = interface_to_usbdev(iface); - dev->driver = &driver->drvwrap.driver; usb_set_intfdata(iface, priv); iface->needs_binding = 0; -- cgit v1.2.3