diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-13 20:58:18 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-12-13 20:58:18 +0100 |
commit | c474009cc1573df73d7fc4aff5ecc22c94e95fde (patch) | |
tree | 5ca501d881ac8522e9c93fac0a1d5b2fd5239c7c | |
parent | Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/... (diff) | |
parent | USB: add quirk for devices with broken LPM (diff) | |
download | linux-c474009cc1573df73d7fc4aff5ecc22c94e95fde.tar.xz linux-c474009cc1573df73d7fc4aff5ecc22c94e95fde.zip |
Merge tag 'usb-4.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB driver fixes from Greg KH:
"Here are a number of small USB fixes for 4.4-rc5. All of them have
been in linux-next. The majority are gadget and phy issues, with a
few new quirks and device ids added as well"
* tag 'usb-4.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (32 commits)
USB: add quirk for devices with broken LPM
xhci: fix usb2 resume timing and races.
usb: musb: fail with error when no DMA controller set
usb: gadget: uvc: fix permissions of configfs attributes
usb: musb: core: Fix pm runtime for deferred probe
usb: phy: msm: fix a possible NULL dereference
USB: host: ohci-at91: fix a crash in ohci_hcd_at91_overcurrent_irq
usb: Quiet down false peer failure messages
usb: xhci: fix config fail of FS hub behind a HS hub with MTT
xhci: Fix memory leak in xhci_pme_acpi_rtd3_enable()
usb: Use the USB_SS_MULT() macro to decode burst multiplier for log message
USB: whci-hcd: add check for dma mapping error
usb: core : hub: Fix BOS 'NULL pointer' kernel panic
USB: quirks: Apply ALWAYS_POLL to all ELAN devices
usb-storage: Fix scsi-sd failure "Invalid field in cdb" for USB adapter JMicron
USB: quirks: Fix another ELAN touchscreen
usb: dwc3: gadget: don't prestart interrupt endpoints
USB: serial: Another Infineon flash loader USB ID
USB: cdc_acm: Ignore Infineon Flash Loader utility
USB: cp210x: Remove CP2110 ID from compatibility list
...
30 files changed, 200 insertions, 79 deletions
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9024a3de4032..8b78a7f1f779 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -316,11 +316,6 @@ #define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 #define USB_VENDOR_ID_ELAN 0x04f3 -#define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089 -#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b -#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103 0x0103 -#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c 0x010c -#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f #define USB_VENDOR_ID_ELECOM 0x056e #define USB_DEVICE_ID_ELECOM_BM084 0x0061 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 2324520b006d..7dd0953cd70f 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -72,11 +72,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, - { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c, HID_QUIRK_ALWAYS_POLL }, - { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, @@ -340,7 +336,8 @@ static const struct hid_blacklist *usbhid_exists_squirk(const u16 idVendor, for (; hid_blacklist[n].idVendor; n++) if (hid_blacklist[n].idVendor == idVendor && - hid_blacklist[n].idProduct == idProduct) + (hid_blacklist[n].idProduct == (__u16) HID_ANY_ID || + hid_blacklist[n].idProduct == idProduct)) bl_entry = &hid_blacklist[n]; if (bl_entry != NULL) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index b30e7423549b..26ca4f910cb0 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1838,6 +1838,11 @@ static const struct usb_device_id acm_ids[] = { }, #endif + /* Exclude Infineon Flash Loader utility */ + { USB_DEVICE(0x058b, 0x0041), + .driver_info = IGNORE_DEVICE, + }, + /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTO_NONE) }, diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 7caff020106e..5050760f5e17 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -115,7 +115,8 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, USB_SS_MULT(desc->bmAttributes) > 3) { dev_warn(ddev, "Isoc endpoint has Mult of %d in " "config %d interface %d altsetting %d ep %d: " - "setting to 3\n", desc->bmAttributes + 1, + "setting to 3\n", + USB_SS_MULT(desc->bmAttributes), cfgno, inum, asnum, ep->desc.bEndpointAddress); ep->ss_ep_comp.bmAttributes = 2; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index bdeadc112d29..a5cc032ef77a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -124,6 +124,10 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) int usb_device_supports_lpm(struct usb_device *udev) { + /* Some devices have trouble with LPM */ + if (udev->quirks & USB_QUIRK_NO_LPM) + return 0; + /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. */ @@ -4512,6 +4516,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, goto fail; } + usb_detect_quirks(udev); + if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { retval = usb_get_bos_descriptor(udev); if (!retval) { @@ -4710,7 +4716,6 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, if (status < 0) goto loop; - usb_detect_quirks(udev); if (udev->quirks & USB_QUIRK_DELAY_INIT) msleep(1000); @@ -5326,9 +5331,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) 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 @@ -5337,15 +5339,18 @@ static int usb_reset_and_verify_device(struct usb_device *udev) ret = usb_unlocked_disable_lpm(udev); if (ret) { dev_err(&udev->dev, "%s Failed to disable LPM\n.", __func__); - goto re_enumerate; + goto re_enumerate_no_bos; } ret = usb_disable_ltm(udev); if (ret) { dev_err(&udev->dev, "%s Failed to disable LTM\n.", __func__); - goto re_enumerate; + goto re_enumerate_no_bos; } + bos = udev->bos; + udev->bos = NULL; + for (i = 0; i < SET_CONFIG_TRIES; ++i) { /* ep0 maxpacket size may change; let the HCD know about it. @@ -5442,10 +5447,11 @@ done: 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; +re_enumerate_no_bos: + /* LPM state doesn't matter when we're about to destroy the device. */ + hub_port_logical_disconnect(parent_hub, port1); return -ENODEV; } diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 210618319f10..5487fe308f01 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -206,7 +206,7 @@ static int link_peers(struct usb_port *left, struct usb_port *right) else method = "default"; - pr_warn("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n", + pr_debug("usb: failed to peer %s and %s by %s (%s:%s) (%s:%s)\n", dev_name(&left->dev), dev_name(&right->dev), method, dev_name(&left->dev), lpeer ? dev_name(&lpeer->dev) : "none", @@ -265,7 +265,7 @@ static void link_peers_report(struct usb_port *left, struct usb_port *right) if (rc == 0) { dev_dbg(&left->dev, "peered to %s\n", dev_name(&right->dev)); } else { - dev_warn(&left->dev, "failed to peer to %s (%d)\n", + dev_dbg(&left->dev, "failed to peer to %s (%d)\n", dev_name(&right->dev), rc); pr_warn_once("usb: port power management may be unreliable\n"); usb_port_block_power_off = 1; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f5a381945db2..6dc810bce295 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -125,6 +125,9 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04f3, 0x016f), .driver_info = USB_QUIRK_DEVICE_QUALIFIER }, + { USB_DEVICE(0x04f3, 0x21b8), .driver_info = + USB_QUIRK_DEVICE_QUALIFIER }, + /* Roland SC-8820 */ { USB_DEVICE(0x0582, 0x0007), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -199,6 +202,12 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x1a0a, 0x0200), .driver_info = USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, + /* Blackmagic Design Intensity Shuttle */ + { USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM }, + + /* Blackmagic Design UltraStudio SDI */ + { USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM }, + { } /* terminating entry must be last */ }; diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index e61d773cf65e..39c1cbf0e75d 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -125,9 +125,11 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) if (ret) return ret; - ret = clk_prepare_enable(hsotg->clk); - if (ret) - return ret; + if (hsotg->clk) { + ret = clk_prepare_enable(hsotg->clk); + if (ret) + return ret; + } if (hsotg->uphy) ret = usb_phy_init(hsotg->uphy); @@ -175,7 +177,8 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) if (ret) return ret; - clk_disable_unprepare(hsotg->clk); + if (hsotg->clk) + clk_disable_unprepare(hsotg->clk); ret = regulator_bulk_disable(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); @@ -212,14 +215,41 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) */ hsotg->phy = devm_phy_get(hsotg->dev, "usb2-phy"); if (IS_ERR(hsotg->phy)) { - hsotg->phy = NULL; + ret = PTR_ERR(hsotg->phy); + switch (ret) { + case -ENODEV: + case -ENOSYS: + hsotg->phy = NULL; + break; + case -EPROBE_DEFER: + return ret; + default: + dev_err(hsotg->dev, "error getting phy %d\n", ret); + return ret; + } + } + + if (!hsotg->phy) { hsotg->uphy = devm_usb_get_phy(hsotg->dev, USB_PHY_TYPE_USB2); - if (IS_ERR(hsotg->uphy)) - hsotg->uphy = NULL; - else - hsotg->plat = dev_get_platdata(hsotg->dev); + if (IS_ERR(hsotg->uphy)) { + ret = PTR_ERR(hsotg->uphy); + switch (ret) { + case -ENODEV: + case -ENXIO: + hsotg->uphy = NULL; + break; + case -EPROBE_DEFER: + return ret; + default: + dev_err(hsotg->dev, "error getting usb phy %d\n", + ret); + return ret; + } + } } + hsotg->plat = dev_get_platdata(hsotg->dev); + if (hsotg->phy) { /* * If using the generic PHY framework, check if the PHY bus @@ -229,11 +259,6 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) hsotg->phyif = GUSBCFG_PHYIF8; } - if (!hsotg->phy && !hsotg->uphy && !hsotg->plat) { - dev_err(hsotg->dev, "no platform data or transceiver defined\n"); - return -EPROBE_DEFER; - } - /* Clock */ hsotg->clk = devm_clk_get(hsotg->dev, "otg"); if (IS_ERR(hsotg->clk)) { @@ -342,20 +367,6 @@ static int dwc2_driver_probe(struct platform_device *dev) if (retval) return retval; - irq = platform_get_irq(dev, 0); - if (irq < 0) { - dev_err(&dev->dev, "missing IRQ resource\n"); - return irq; - } - - dev_dbg(hsotg->dev, "registering common handler for irq%d\n", - irq); - retval = devm_request_irq(hsotg->dev, irq, - dwc2_handle_common_intr, IRQF_SHARED, - dev_name(hsotg->dev), hsotg); - if (retval) - return retval; - res = platform_get_resource(dev, IORESOURCE_MEM, 0); hsotg->regs = devm_ioremap_resource(&dev->dev, res); if (IS_ERR(hsotg->regs)) @@ -390,6 +401,20 @@ static int dwc2_driver_probe(struct platform_device *dev) dwc2_set_all_params(hsotg->core_params, -1); + irq = platform_get_irq(dev, 0); + if (irq < 0) { + dev_err(&dev->dev, "missing IRQ resource\n"); + return irq; + } + + dev_dbg(hsotg->dev, "registering common handler for irq%d\n", + irq); + retval = devm_request_irq(hsotg->dev, irq, + dwc2_handle_common_intr, IRQF_SHARED, + dev_name(hsotg->dev), hsotg); + if (retval) + return retval; + retval = dwc2_lowlevel_hw_enable(hsotg); if (retval) return retval; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e24a01cc98df..a58376fd65fe 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1078,6 +1078,7 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * little bit faster. */ if (!usb_endpoint_xfer_isoc(dep->endpoint.desc) && + !usb_endpoint_xfer_int(dep->endpoint.desc) && !(dep->flags & DWC3_EP_BUSY)) { ret = __dwc3_gadget_kick_transfer(dep, 0, true); goto out; diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index adc6d52efa46..cf43e9e18368 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -423,7 +423,7 @@ static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf, spin_unlock_irq(&ffs->ev.waitq.lock); mutex_unlock(&ffs->mutex); - return unlikely(__copy_to_user(buf, events, size)) ? -EFAULT : size; + return unlikely(copy_to_user(buf, events, size)) ? -EFAULT : size; } static ssize_t ffs_ep0_read(struct file *file, char __user *buf, @@ -513,7 +513,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf, /* unlocks spinlock */ ret = __ffs_ep0_queue_wait(ffs, data, len); - if (likely(ret > 0) && unlikely(__copy_to_user(buf, data, len))) + if (likely(ret > 0) && unlikely(copy_to_user(buf, data, len))) ret = -EFAULT; goto done_mutex; @@ -3493,7 +3493,7 @@ static char *ffs_prepare_buffer(const char __user *buf, size_t len) if (unlikely(!data)) return ERR_PTR(-ENOMEM); - if (unlikely(__copy_from_user(data, buf, len))) { + if (unlikely(copy_from_user(data, buf, len))) { kfree(data); return ERR_PTR(-EFAULT); } diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 42acb45e1ab4..898a570319f1 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -370,6 +370,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt) if (err) { ERROR(midi, "%s queue req: %d\n", midi->out_ep->name, err); + free_ep_req(midi->out_ep, req); } } @@ -545,7 +546,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req) } } - if (req->length > 0) { + if (req->length > 0 && ep->enabled) { int err; err = usb_ep_queue(ep, req, GFP_ATOMIC); diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 289ebca316d3..ad8c9b05572d 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -20,7 +20,7 @@ #define UVC_ATTR(prefix, cname, aname) \ static struct configfs_attribute prefix##attr_##cname = { \ .ca_name = __stringify(aname), \ - .ca_mode = S_IRUGO, \ + .ca_mode = S_IRUGO | S_IWUGO, \ .ca_owner = THIS_MODULE, \ .show = prefix##cname##_show, \ .store = prefix##cname##_store, \ diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c index 670ac0b12f00..001a3b74a993 100644 --- a/drivers/usb/gadget/udc/pxa27x_udc.c +++ b/drivers/usb/gadget/udc/pxa27x_udc.c @@ -2536,6 +2536,9 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state) udc->pullup_resume = udc->pullup_on; dplus_pullup(udc, 0); + if (udc->driver) + udc->driver->disconnect(&udc->gadget); + return 0; } diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 342ffd140122..8c6e15bd6ff0 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -473,6 +473,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) if (!pdata) return -ENOMEM; + pdev->dev.platform_data = pdata; + if (!of_property_read_u32(np, "num-ports", &ports)) pdata->ports = ports; @@ -483,6 +485,7 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) */ if (i >= pdata->ports) { pdata->vbus_pin[i] = -EINVAL; + pdata->overcurrent_pin[i] = -EINVAL; continue; } @@ -513,10 +516,8 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) } at91_for_each_port(i) { - if (i >= pdata->ports) { - pdata->overcurrent_pin[i] = -EINVAL; - continue; - } + if (i >= pdata->ports) + break; pdata->overcurrent_pin[i] = of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags); @@ -552,8 +553,6 @@ static int ohci_hcd_at91_drv_probe(struct platform_device *pdev) } } - pdev->dev.platform_data = pdata; - device_init_wakeup(&pdev->dev, 1); return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev); } diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index dc31c425ce01..9f1c0538b211 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -377,6 +377,10 @@ static int qset_fill_page_list(struct whc *whc, struct whc_std *std, gfp_t mem_f if (std->pl_virt == NULL) return -ENOMEM; std->dma_addr = dma_map_single(whc->wusbhc.dev, std->pl_virt, pl_len, DMA_TO_DEVICE); + if (dma_mapping_error(whc->wusbhc.dev, std->dma_addr)) { + kfree(std->pl_virt); + return -EFAULT; + } for (p = 0; p < std->num_pointers; p++) { std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0230965fb78c..f980c239eded 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -733,8 +733,30 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, if ((raw_port_status & PORT_RESET) || !(raw_port_status & PORT_PE)) return 0xffffffff; - if (time_after_eq(jiffies, - bus_state->resume_done[wIndex])) { + /* did port event handler already start resume timing? */ + if (!bus_state->resume_done[wIndex]) { + /* If not, maybe we are in a host initated resume? */ + if (test_bit(wIndex, &bus_state->resuming_ports)) { + /* Host initated resume doesn't time the resume + * signalling using resume_done[]. + * It manually sets RESUME state, sleeps 20ms + * and sets U0 state. This should probably be + * changed, but not right now. + */ + } else { + /* port resume was discovered now and here, + * start resume timing + */ + unsigned long timeout = jiffies + + msecs_to_jiffies(USB_RESUME_TIMEOUT); + + set_bit(wIndex, &bus_state->resuming_ports); + bus_state->resume_done[wIndex] = timeout; + mod_timer(&hcd->rh_timer, timeout); + } + /* Has resume been signalled for USB_RESUME_TIME yet? */ + } else if (time_after_eq(jiffies, + bus_state->resume_done[wIndex])) { int time_left; xhci_dbg(xhci, "Resume USB2 port %d\n", @@ -775,13 +797,26 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, } else { /* * The resume has been signaling for less than - * 20ms. Report the port status as SUSPEND, - * let the usbcore check port status again - * and clear resume signaling later. + * USB_RESUME_TIME. Report the port status as SUSPEND, + * let the usbcore check port status again and clear + * resume signaling later. */ status |= USB_PORT_STAT_SUSPEND; } } + /* + * Clear stale usb2 resume signalling variables in case port changed + * state during resume signalling. For example on error + */ + if ((bus_state->resume_done[wIndex] || + test_bit(wIndex, &bus_state->resuming_ports)) && + (raw_port_status & PORT_PLS_MASK) != XDEV_U3 && + (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) { + bus_state->resume_done[wIndex] = 0; + clear_bit(wIndex, &bus_state->resuming_ports); + } + + if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 && (raw_port_status & PORT_POWER)) { if (bus_state->suspended_ports & (1 << wIndex)) { @@ -1115,6 +1150,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, if ((temp & PORT_PE) == 0) goto error; + set_bit(wIndex, &bus_state->resuming_ports); xhci_set_link_state(xhci, port_array, wIndex, XDEV_RESUME); spin_unlock_irqrestore(&xhci->lock, flags); @@ -1122,6 +1158,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, spin_lock_irqsave(&xhci->lock, flags); xhci_set_link_state(xhci, port_array, wIndex, XDEV_U0); + clear_bit(wIndex, &bus_state->resuming_ports); } bus_state->port_c_suspend |= 1 << wIndex; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 17f6897acde2..c62109091d12 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -188,10 +188,14 @@ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) 0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45, 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23, }; - acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, NULL); + union acpi_object *obj; + + obj = acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, + NULL); + ACPI_FREE(obj); } #else - static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { } +static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { } #endif /* CONFIG_ACPI */ /* called during probe() after chip reset completes */ diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 6c5e8133cf87..eeaa6c6bd540 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1583,7 +1583,8 @@ static void handle_port_status(struct xhci_hcd *xhci, */ bogus_port_status = true; goto cleanup; - } else { + } else if (!test_bit(faked_port_index, + &bus_state->resuming_ports)) { xhci_dbg(xhci, "resume HS port %d\n", port_id); bus_state->resume_done[faked_port_index] = jiffies + msecs_to_jiffies(USB_RESUME_TIMEOUT); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index dfa44d3e8eee..3f912705dcef 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4778,8 +4778,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG); slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx); slot_ctx->dev_info |= cpu_to_le32(DEV_HUB); + /* + * refer to section 6.2.2: MTT should be 0 for full speed hub, + * but it may be already set to 1 when setup an xHCI virtual + * device, so clear it anyway. + */ if (tt->multi) slot_ctx->dev_info |= cpu_to_le32(DEV_MTT); + else if (hdev->speed == USB_SPEED_FULL) + slot_ctx->dev_info &= cpu_to_le32(~DEV_MTT); + if (xhci->hci_version > 0x95) { xhci_dbg(xhci, "xHCI version %x needs hub " "TT think time and number of ports\n", diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 1f2037bbeb0d..45c83baf675d 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -159,7 +159,7 @@ config USB_TI_CPPI_DMA config USB_TI_CPPI41_DMA bool 'TI CPPI 4.1 (AM335x)' - depends on ARCH_OMAP + depends on ARCH_OMAP && DMADEVICES select TI_CPPI41 config USB_TUSB_OMAP_DMA diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 18cfc0a361cb..ee9ff7028b92 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2017,7 +2017,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) /* We need musb_read/write functions initialized for PM */ pm_runtime_use_autosuspend(musb->controller); pm_runtime_set_autosuspend_delay(musb->controller, 200); - pm_runtime_irq_safe(musb->controller); pm_runtime_enable(musb->controller); /* The musb_platform_init() call: @@ -2095,6 +2094,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) #ifndef CONFIG_MUSB_PIO_ONLY if (!musb->ops->dma_init || !musb->ops->dma_exit) { dev_err(dev, "DMA controller not set\n"); + status = -ENODEV; goto fail2; } musb_dma_controller_create = musb->ops->dma_init; @@ -2218,6 +2218,12 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) pm_runtime_put(musb->controller); + /* + * For why this is currently needed, see commit 3e43a0725637 + * ("usb: musb: core: add pm_runtime_irq_safe()") + */ + pm_runtime_irq_safe(musb->controller); + return 0; fail5: diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c index 80eb991c2506..0d19a6d61a71 100644 --- a/drivers/usb/phy/phy-msm-usb.c +++ b/drivers/usb/phy/phy-msm-usb.c @@ -1506,7 +1506,6 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) { struct msm_otg_platform_data *pdata; struct extcon_dev *ext_id, *ext_vbus; - const struct of_device_id *id; struct device_node *node = pdev->dev.of_node; struct property *prop; int len, ret, words; @@ -1518,8 +1517,9 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg) motg->pdata = pdata; - id = of_match_device(msm_otg_dt_match, &pdev->dev); - pdata->phy_type = (enum msm_usb_phy_type) id->data; + pdata->phy_type = (enum msm_usb_phy_type)of_device_get_match_data(&pdev->dev); + if (!pdata->phy_type) + return 1; motg->link_rst = devm_reset_control_get(&pdev->dev, "link"); if (IS_ERR(motg->link_rst)) diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index b7536af777ab..c2936dc48ca7 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -143,12 +143,17 @@ static const struct mxs_phy_data imx6sx_phy_data = { .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS, }; +static const struct mxs_phy_data imx6ul_phy_data = { + .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS, +}; + static const struct of_device_id mxs_phy_dt_ids[] = { { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, }, { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, }, { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, }, { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, }, { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, }, + { .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids); diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index de4f97d84a82..8f7a78e70975 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c @@ -131,7 +131,8 @@ static void __usbhsg_queue_pop(struct usbhsg_uep *uep, struct device *dev = usbhsg_gpriv_to_dev(gpriv); struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv); - dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); + if (pipe) + dev_dbg(dev, "pipe %d : queue pop\n", usbhs_pipe_number(pipe)); ureq->req.status = status; spin_unlock(usbhs_priv_to_lock(priv)); @@ -685,7 +686,13 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) struct usbhsg_request *ureq = usbhsg_req_to_ureq(req); struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep); - usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq)); + if (pipe) + usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq)); + + /* + * To dequeue a request, this driver should call the usbhsg_queue_pop() + * even if the pipe is NULL. + */ usbhsg_queue_pop(uep, ureq, -ECONNRESET); return 0; diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index eac7ccaa3c85..7d4f51a32e66 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -132,7 +132,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c index 3658662898fc..a204782ae530 100644 --- a/drivers/usb/serial/usb-serial-simple.c +++ b/drivers/usb/serial/usb-serial-simple.c @@ -53,6 +53,7 @@ DEVICE(funsoft, FUNSOFT_IDS); /* Infineon Flashloader driver */ #define FLASHLOADER_IDS() \ + { USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \ { USB_DEVICE(0x8087, 0x0716) } DEVICE(flashloader, FLASHLOADER_IDS); diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index e69151664436..5c66d3f7a6d0 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -796,6 +796,10 @@ static int uas_slave_configure(struct scsi_device *sdev) if (devinfo->flags & US_FL_NO_REPORT_OPCODES) sdev->no_report_opcodes = 1; + /* A few buggy USB-ATA bridges don't understand FUA */ + if (devinfo->flags & US_FL_BROKEN_FUA) + sdev->broken_fua = 1; + scsi_change_queue_depth(sdev, devinfo->qdepth - 2); return 0; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6b2479123de7..7ffe4209067b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1987,7 +1987,7 @@ UNUSUAL_DEV( 0x14cd, 0x6600, 0x0201, 0x0201, US_FL_IGNORE_RESIDUE ), /* Reported by Michael Büsch <m@bues.ch> */ -UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0114, +UNUSUAL_DEV( 0x152d, 0x0567, 0x0114, 0x0116, "JMicron", "USB to ATA/ATAPI Bridge", USB_SC_DEVICE, USB_PR_DEVICE, NULL, diff --git a/drivers/usb/storage/unusual_uas.h b/drivers/usb/storage/unusual_uas.h index c85ea530085f..ccc113e83d88 100644 --- a/drivers/usb/storage/unusual_uas.h +++ b/drivers/usb/storage/unusual_uas.h @@ -132,7 +132,7 @@ UNUSUAL_DEV(0x152d, 0x0567, 0x0000, 0x9999, "JMicron", "JMS567", USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_REPORT_OPCODES), + US_FL_BROKEN_FUA | US_FL_NO_REPORT_OPCODES), /* Reported-by: Hans de Goede <hdegoede@redhat.com> */ UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999, diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 9948c874e3f1..1d0043dc34e4 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -47,4 +47,7 @@ /* device generates spurious wakeup, ignore remote wakeup capability */ #define USB_QUIRK_IGNORE_REMOTE_WAKEUP BIT(9) +/* device can't handle Link Power Management */ +#define USB_QUIRK_NO_LPM BIT(10) + #endif /* __LINUX_USB_QUIRKS_H */ |