diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/core/hub.c | 15 | ||||
-rw-r--r-- | drivers/usb/core/quirks.c | 7 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 6 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 5 | ||||
-rw-r--r-- | drivers/usb/early/ehci-dbgp.c | 38 | ||||
-rw-r--r-- | drivers/usb/gadget/function/u_ether.c | 11 | ||||
-rw-r--r-- | drivers/usb/gadget/udc/omap_udc.c | 88 | ||||
-rw-r--r-- | drivers/usb/host/hwa-hc.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ohci-mem.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 351 | ||||
-rw-r--r-- | drivers/usb/host/xhci-mem.c | 30 | ||||
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/xhci-ring.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 64 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 16 | ||||
-rw-r--r-- | drivers/usb/misc/appledisplay.c | 9 | ||||
-rw-r--r-- | drivers/usb/serial/console.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/ene_ub6250.c | 2 | ||||
-rw-r--r-- | drivers/usb/storage/unusual_realtek.h | 10 | ||||
-rw-r--r-- | drivers/usb/typec/tcpm/fusb302.c | 2 | ||||
-rw-r--r-- | drivers/usb/typec/tcpm/tcpm.c | 21 |
21 files changed, 381 insertions, 316 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 0f9381b69a3b..1d1e61e980f3 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1112,6 +1112,16 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) 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; @@ -2251,7 +2261,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev) /* 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; @@ -5163,7 +5173,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, /* 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 }; + char *envp[3]; struct device *hub_dev; char *port_dev_path; @@ -5187,6 +5197,7 @@ static void port_over_current_notify(struct usb_port *port_dev) if (!envp[1]) goto exit; + envp[2] = NULL; kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp); kfree(envp[1]); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f9ff03e6af93..514c5214ddb2 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -209,6 +209,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Microsoft LifeCam-VX700 v2.0 */ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */ + { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */ { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, @@ -330,6 +333,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Midiman M-Audio Keystation 88es */ { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME }, + /* SanDisk Ultra Fit and Ultra Flair */ + { USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM }, + { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 79d8bd7a612e..4ebfbd737905 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -832,14 +832,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number); */ int __usb_get_extra_descriptor(char *buffer, unsigned size, - unsigned char type, void **ptr) + unsigned char type, void **ptr, size_t minsize) { struct usb_descriptor_header *header; while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; - if (header->bLength < 2) { + if (header->bLength < 2 || header->bLength > size) { printk(KERN_ERR "%s: bogus descriptor, type %d length %d\n", usbcore_name, @@ -848,7 +848,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, return -1; } - if (header->bDescriptorType == type) { + if (header->bDescriptorType == type && header->bLength >= minsize) { *ptr = header; return 0; } diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2ecde30ad0b7..07bd31bb2f8a 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1587,9 +1587,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) unsigned transfer_in_flight; unsigned started; - if (dep->flags & DWC3_EP_STALL) - return 0; - if (dep->number > 1) trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue); else @@ -1611,8 +1608,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) else dep->flags |= DWC3_EP_STALL; } else { - if (!(dep->flags & DWC3_EP_STALL)) - return 0; ret = dwc3_send_clear_stall_ep_cmd(dep); if (ret) diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index d633c2abe5a4..ea0d531c63e2 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -631,28 +631,28 @@ static int ehci_reset_port(int port) if (!(portsc & PORT_RESET)) break; } - if (portsc & PORT_RESET) { - /* force reset to complete */ - loop = 100 * 1000; - writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), - &ehci_regs->port_status[port - 1]); - do { - udelay(1); - portsc = readl(&ehci_regs->port_status[port-1]); - } while ((portsc & PORT_RESET) && (--loop > 0)); - } + if (portsc & PORT_RESET) { + /* force reset to complete */ + loop = 100 * 1000; + writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), + &ehci_regs->port_status[port - 1]); + do { + udelay(1); + portsc = readl(&ehci_regs->port_status[port-1]); + } while ((portsc & PORT_RESET) && (--loop > 0)); + } - /* Device went away? */ - if (!(portsc & PORT_CONNECT)) - return -ENOTCONN; + /* Device went away? */ + if (!(portsc & PORT_CONNECT)) + return -ENOTCONN; - /* bomb out completely if something weird happened */ - if ((portsc & PORT_CSC)) - return -EINVAL; + /* bomb out completely if something weird happened */ + if ((portsc & PORT_CSC)) + return -EINVAL; - /* If we've finished resetting, then break out of the loop */ - if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) - return 0; + /* If we've finished resetting, then break out of the loop */ + if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) + return 0; return -EBUSY; } diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 1000d864929c..0f026d445e31 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -401,12 +401,12 @@ done: static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) { struct usb_request *req; - struct usb_request *tmp; unsigned long flags; /* fill unused rxq slots with some skb */ spin_lock_irqsave(&dev->req_lock, flags); - list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) { + while (!list_empty(&dev->rx_reqs)) { + req = list_first_entry(&dev->rx_reqs, struct usb_request, list); list_del_init(&req->list); spin_unlock_irqrestore(&dev->req_lock, flags); @@ -1125,7 +1125,6 @@ void gether_disconnect(struct gether *link) { struct eth_dev *dev = link->ioport; struct usb_request *req; - struct usb_request *tmp; WARN_ON(!dev); if (!dev) @@ -1142,7 +1141,8 @@ void gether_disconnect(struct gether *link) */ usb_ep_disable(link->in_ep); spin_lock(&dev->req_lock); - list_for_each_entry_safe(req, tmp, &dev->tx_reqs, list) { + while (!list_empty(&dev->tx_reqs)) { + req = list_first_entry(&dev->tx_reqs, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); @@ -1154,7 +1154,8 @@ void gether_disconnect(struct gether *link) usb_ep_disable(link->out_ep); spin_lock(&dev->req_lock); - list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) { + while (!list_empty(&dev->rx_reqs)) { + req = list_first_entry(&dev->rx_reqs, struct usb_request, list); list_del(&req->list); spin_unlock(&dev->req_lock); diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 3a16431da321..fcf13ef33b31 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2033,6 +2033,7 @@ static inline int machine_without_vbus_sense(void) { return machine_is_omap_innovator() || machine_is_omap_osk() + || machine_is_omap_palmte() || machine_is_sx1() /* No known omap7xx boards with vbus sense */ || cpu_is_omap7xx(); @@ -2041,7 +2042,7 @@ static inline int machine_without_vbus_sense(void) static int omap_udc_start(struct usb_gadget *g, struct usb_gadget_driver *driver) { - int status = -ENODEV; + int status; struct omap_ep *ep; unsigned long flags; @@ -2079,6 +2080,7 @@ static int omap_udc_start(struct usb_gadget *g, goto done; } } else { + status = 0; if (can_pullup(udc)) pullup_enable(udc); else @@ -2593,9 +2595,22 @@ omap_ep_setup(char *name, u8 addr, u8 type, static void omap_udc_release(struct device *dev) { - complete(udc->done); + pullup_disable(udc); + if (!IS_ERR_OR_NULL(udc->transceiver)) { + usb_put_phy(udc->transceiver); + udc->transceiver = NULL; + } + omap_writew(0, UDC_SYSCON1); + remove_proc_file(); + if (udc->dc_clk) { + if (udc->clk_requested) + omap_udc_enable_clock(0); + clk_put(udc->hhc_clk); + clk_put(udc->dc_clk); + } + if (udc->done) + complete(udc->done); kfree(udc); - udc = NULL; } static int @@ -2627,6 +2642,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv) udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.max_speed = USB_SPEED_FULL; udc->gadget.name = driver_name; + udc->gadget.quirk_ep_out_aligned_size = 1; udc->transceiver = xceiv; /* ep0 is special; put it right after the SETUP buffer */ @@ -2867,8 +2883,8 @@ bad_on_1710: udc->clr_halt = UDC_RESET_EP; /* USB general purpose IRQ: ep0, state changes, dma, etc */ - status = request_irq(pdev->resource[1].start, omap_udc_irq, - 0, driver_name, udc); + status = devm_request_irq(&pdev->dev, pdev->resource[1].start, + omap_udc_irq, 0, driver_name, udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[1].start, status); @@ -2876,20 +2892,20 @@ bad_on_1710: } /* USB "non-iso" IRQ (PIO for all but ep0) */ - status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, - 0, "omap_udc pio", udc); + status = devm_request_irq(&pdev->dev, pdev->resource[2].start, + omap_udc_pio_irq, 0, "omap_udc pio", udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[2].start, status); - goto cleanup2; + goto cleanup1; } #ifdef USE_ISO - status = request_irq(pdev->resource[3].start, omap_udc_iso_irq, - 0, "omap_udc iso", udc); + status = devm_request_irq(&pdev->dev, pdev->resource[3].start, + omap_udc_iso_irq, 0, "omap_udc iso", udc); if (status != 0) { ERR("can't get irq %d, err %d\n", (int) pdev->resource[3].start, status); - goto cleanup3; + goto cleanup1; } #endif if (cpu_is_omap16xx() || cpu_is_omap7xx()) { @@ -2900,23 +2916,8 @@ bad_on_1710: } create_proc_file(); - status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, - omap_udc_release); - if (status) - goto cleanup4; - - return 0; - -cleanup4: - remove_proc_file(); - -#ifdef USE_ISO -cleanup3: - free_irq(pdev->resource[2].start, udc); -#endif - -cleanup2: - free_irq(pdev->resource[1].start, udc); + return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, + omap_udc_release); cleanup1: kfree(udc); @@ -2943,42 +2944,15 @@ static int omap_udc_remove(struct platform_device *pdev) { DECLARE_COMPLETION_ONSTACK(done); - if (!udc) - return -ENODEV; - - usb_del_gadget_udc(&udc->gadget); - if (udc->driver) - return -EBUSY; - udc->done = &done; - pullup_disable(udc); - if (!IS_ERR_OR_NULL(udc->transceiver)) { - usb_put_phy(udc->transceiver); - udc->transceiver = NULL; - } - omap_writew(0, UDC_SYSCON1); - - remove_proc_file(); - -#ifdef USE_ISO - free_irq(pdev->resource[3].start, udc); -#endif - free_irq(pdev->resource[2].start, udc); - free_irq(pdev->resource[1].start, udc); + usb_del_gadget_udc(&udc->gadget); - if (udc->dc_clk) { - if (udc->clk_requested) - omap_udc_enable_clock(0); - clk_put(udc->hhc_clk); - clk_put(udc->dc_clk); - } + wait_for_completion(&done); release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); - wait_for_completion(&done); - return 0; } diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 684d6f074c3a..09a8ebd95588 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -640,7 +640,7 @@ static int hwahc_security_create(struct hwahc *hwahc) top = itr + itr_size; result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), - USB_DT_SECURITY, (void **) &secd); + USB_DT_SECURITY, (void **) &secd, sizeof(*secd)); if (result == -1) { dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); return 0; diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c index b3da3f12e5b1..3965ac0341eb 100644 --- a/drivers/usb/host/ohci-mem.c +++ b/drivers/usb/host/ohci-mem.c @@ -57,14 +57,10 @@ static int ohci_mem_init (struct ohci_hcd *ohci) static void ohci_mem_cleanup (struct ohci_hcd *ohci) { - if (ohci->td_cache) { - dma_pool_destroy (ohci->td_cache); - ohci->td_cache = NULL; - } - if (ohci->ed_cache) { - dma_pool_destroy (ohci->ed_cache); - ohci->ed_cache = NULL; - } + dma_pool_destroy(ohci->td_cache); + ohci->td_cache = NULL; + dma_pool_destroy(ohci->ed_cache); + ohci->ed_cache = NULL; } /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 94aca1b5ac8a..c7601750c37f 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -714,13 +714,6 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, struct xhci_port *port, } } -/* Updates Link Status for USB 2.1 port */ -static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg) -{ - if ((status_reg & PORT_PLS_MASK) == XDEV_U2) - *status |= USB_PORT_STAT_L1; -} - /* Updates Link Status for super Speed port */ static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci, u32 *status, u32 status_reg) @@ -802,6 +795,100 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, } } +static int xhci_handle_usb2_port_link_resume(struct xhci_port *port, + u32 *status, u32 portsc, + unsigned long flags) +{ + struct xhci_bus_state *bus_state; + struct xhci_hcd *xhci; + struct usb_hcd *hcd; + int slot_id; + u32 wIndex; + + hcd = port->rhub->hcd; + bus_state = &port->rhub->bus_state; + xhci = hcd_to_xhci(hcd); + wIndex = port->hcd_portnum; + + if ((portsc & PORT_RESET) || !(portsc & PORT_PE)) { + *status = 0xffffffff; + return -EINVAL; + } + /* 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); + usb_hcd_start_port_resume(&hcd->self, wIndex); + } + /* 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", wIndex + 1); + bus_state->resume_done[wIndex] = 0; + clear_bit(wIndex, &bus_state->resuming_ports); + + set_bit(wIndex, &bus_state->rexit_ports); + + xhci_test_and_clear_bit(xhci, port, PORT_PLC); + xhci_set_link_state(xhci, port, XDEV_U0); + + spin_unlock_irqrestore(&xhci->lock, flags); + time_left = wait_for_completion_timeout( + &bus_state->rexit_done[wIndex], + msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS)); + spin_lock_irqsave(&xhci->lock, flags); + + if (time_left) { + slot_id = xhci_find_slot_id_by_port(hcd, xhci, + wIndex + 1); + if (!slot_id) { + xhci_dbg(xhci, "slot_id is zero\n"); + *status = 0xffffffff; + return -ENODEV; + } + xhci_ring_device(xhci, slot_id); + } else { + int port_status = readl(port->addr); + + xhci_warn(xhci, "Port resume %i msec timed out, portsc = 0x%x\n", + XHCI_MAX_REXIT_TIMEOUT_MS, + port_status); + *status |= USB_PORT_STAT_SUSPEND; + clear_bit(wIndex, &bus_state->rexit_ports); + } + + usb_hcd_end_port_resume(&hcd->self, wIndex); + bus_state->port_c_suspend |= 1 << wIndex; + bus_state->suspended_ports &= ~(1 << wIndex); + } else { + /* + * The resume has been signaling for less than + * 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; + } + return 0; +} + static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li) { u32 ext_stat = 0; @@ -818,6 +905,85 @@ static u32 xhci_get_ext_port_status(u32 raw_port_status, u32 port_li) return ext_stat; } +static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status, + u32 portsc) +{ + struct xhci_bus_state *bus_state; + struct xhci_hcd *xhci; + u32 link_state; + u32 portnum; + + bus_state = &port->rhub->bus_state; + xhci = hcd_to_xhci(port->rhub->hcd); + link_state = portsc & PORT_PLS_MASK; + portnum = port->hcd_portnum; + + /* USB3 specific wPortChange bits + * + * Port link change with port in resume state should not be + * reported to usbcore, as this is an internal state to be + * handled by xhci driver. Reporting PLC to usbcore may + * cause usbcore clearing PLC first and port change event + * irq won't be generated. + */ + + if (portsc & PORT_PLC && (link_state != XDEV_RESUME)) + *status |= USB_PORT_STAT_C_LINK_STATE << 16; + if (portsc & PORT_WRC) + *status |= USB_PORT_STAT_C_BH_RESET << 16; + if (portsc & PORT_CEC) + *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; + + /* USB3 specific wPortStatus bits */ + if (portsc & PORT_POWER) { + *status |= USB_SS_PORT_STAT_POWER; + /* link state handling */ + if (link_state == XDEV_U0) + bus_state->suspended_ports &= ~(1 << portnum); + } + + xhci_hub_report_usb3_link_state(xhci, status, portsc); + xhci_del_comp_mod_timer(xhci, portsc, portnum); +} + +static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status, + u32 portsc, unsigned long flags) +{ + struct xhci_bus_state *bus_state; + u32 link_state; + u32 portnum; + int ret; + + bus_state = &port->rhub->bus_state; + link_state = portsc & PORT_PLS_MASK; + portnum = port->hcd_portnum; + + /* USB2 wPortStatus bits */ + if (portsc & PORT_POWER) { + *status |= USB_PORT_STAT_POWER; + + /* link state is only valid if port is powered */ + if (link_state == XDEV_U3) + *status |= USB_PORT_STAT_SUSPEND; + if (link_state == XDEV_U2) + *status |= USB_PORT_STAT_L1; + if (link_state == XDEV_U0) { + bus_state->resume_done[portnum] = 0; + clear_bit(portnum, &bus_state->resuming_ports); + if (bus_state->suspended_ports & (1 << portnum)) { + bus_state->suspended_ports &= ~(1 << portnum); + bus_state->port_c_suspend |= 1 << portnum; + } + } + if (link_state == XDEV_RESUME) { + ret = xhci_handle_usb2_port_link_resume(port, status, + portsc, flags); + if (ret) + return; + } + } +} + /* * Converts a raw xHCI port status into the format that external USB 2.0 or USB * 3.0 hubs use. @@ -835,16 +1001,14 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, __releases(&xhci->lock) __acquires(&xhci->lock) { - struct xhci_hcd *xhci = hcd_to_xhci(hcd); u32 status = 0; - int slot_id; struct xhci_hub *rhub; struct xhci_port *port; rhub = xhci_get_rhub(hcd); port = rhub->ports[wIndex]; - /* wPortChange bits */ + /* common wPortChange bits */ if (raw_port_status & PORT_CSC) status |= USB_PORT_STAT_C_CONNECTION << 16; if (raw_port_status & PORT_PEC) @@ -853,107 +1017,25 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, status |= USB_PORT_STAT_C_OVERCURRENT << 16; if ((raw_port_status & PORT_RC)) status |= USB_PORT_STAT_C_RESET << 16; - /* USB3.0 only */ - if (hcd->speed >= HCD_USB3) { - /* Port link change with port in resume state should not be - * reported to usbcore, as this is an internal state to be - * handled by xhci driver. Reporting PLC to usbcore may - * cause usbcore clearing PLC first and port change event - * irq won't be generated. - */ - if ((raw_port_status & PORT_PLC) && - (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) - status |= USB_PORT_STAT_C_LINK_STATE << 16; - if ((raw_port_status & PORT_WRC)) - status |= USB_PORT_STAT_C_BH_RESET << 16; - if ((raw_port_status & PORT_CEC)) - status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; - } - if (hcd->speed < HCD_USB3) { - if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3 - && (raw_port_status & PORT_POWER)) - status |= USB_PORT_STAT_SUSPEND; + /* common wPortStatus bits */ + if (raw_port_status & PORT_CONNECT) { + status |= USB_PORT_STAT_CONNECTION; + status |= xhci_port_speed(raw_port_status); } - if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && - !DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) { - if ((raw_port_status & PORT_RESET) || - !(raw_port_status & PORT_PE)) - return 0xffffffff; - /* 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); - usb_hcd_start_port_resume(&hcd->self, wIndex); - } - /* 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", - wIndex + 1); - bus_state->resume_done[wIndex] = 0; - clear_bit(wIndex, &bus_state->resuming_ports); - - set_bit(wIndex, &bus_state->rexit_ports); - - xhci_test_and_clear_bit(xhci, port, PORT_PLC); - xhci_set_link_state(xhci, port, XDEV_U0); - - spin_unlock_irqrestore(&xhci->lock, flags); - time_left = wait_for_completion_timeout( - &bus_state->rexit_done[wIndex], - msecs_to_jiffies( - XHCI_MAX_REXIT_TIMEOUT_MS)); - spin_lock_irqsave(&xhci->lock, flags); - - if (time_left) { - slot_id = xhci_find_slot_id_by_port(hcd, - xhci, wIndex + 1); - if (!slot_id) { - xhci_dbg(xhci, "slot_id is zero\n"); - return 0xffffffff; - } - xhci_ring_device(xhci, slot_id); - } else { - int port_status = readl(port->addr); - xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", - XHCI_MAX_REXIT_TIMEOUT_MS, - port_status); - status |= USB_PORT_STAT_SUSPEND; - clear_bit(wIndex, &bus_state->rexit_ports); - } + if (raw_port_status & PORT_PE) + status |= USB_PORT_STAT_ENABLE; + if (raw_port_status & PORT_OC) + status |= USB_PORT_STAT_OVERCURRENT; + if (raw_port_status & PORT_RESET) + status |= USB_PORT_STAT_RESET; - usb_hcd_end_port_resume(&hcd->self, wIndex); - bus_state->port_c_suspend |= 1 << wIndex; - bus_state->suspended_ports &= ~(1 << wIndex); - } else { - /* - * The resume has been signaling for less than - * 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; - } - } + /* USB2 and USB3 specific bits, including Port Link State */ + if (hcd->speed >= HCD_USB3) + xhci_get_usb3_port_status(port, &status, raw_port_status); + else + xhci_get_usb2_port_status(port, &status, raw_port_status, + flags); /* * Clear stale usb2 resume signalling variables in case port changed * state during resume signalling. For example on error @@ -967,44 +1049,6 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, usb_hcd_end_port_resume(&hcd->self, wIndex); } - - if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 && - (raw_port_status & PORT_POWER)) { - if (bus_state->suspended_ports & (1 << wIndex)) { - bus_state->suspended_ports &= ~(1 << wIndex); - if (hcd->speed < HCD_USB3) - bus_state->port_c_suspend |= 1 << wIndex; - } - bus_state->resume_done[wIndex] = 0; - clear_bit(wIndex, &bus_state->resuming_ports); - } - if (raw_port_status & PORT_CONNECT) { - status |= USB_PORT_STAT_CONNECTION; - status |= xhci_port_speed(raw_port_status); - } - if (raw_port_status & PORT_PE) - status |= USB_PORT_STAT_ENABLE; - if (raw_port_status & PORT_OC) - status |= USB_PORT_STAT_OVERCURRENT; - if (raw_port_status & PORT_RESET) - status |= USB_PORT_STAT_RESET; - if (raw_port_status & PORT_POWER) { - if (hcd->speed >= HCD_USB3) - status |= USB_SS_PORT_STAT_POWER; - else - status |= USB_PORT_STAT_POWER; - } - /* Update Port Link State */ - if (hcd->speed >= HCD_USB3) { - xhci_hub_report_usb3_link_state(xhci, &status, raw_port_status); - /* - * Verify if all USB3 Ports Have entered U0 already. - * Delete Compliance Mode Timer if so. - */ - xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex); - } else { - xhci_hub_report_usb2_link_state(&status, raw_port_status); - } if (bus_state->port_c_suspend & (1 << wIndex)) status |= USB_PORT_STAT_C_SUSPEND << 16; @@ -1031,7 +1075,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, rhub = xhci_get_rhub(hcd); ports = rhub->ports; max_ports = rhub->num_ports; - bus_state = &xhci->bus_state[hcd_index(hcd)]; + bus_state = &rhub->bus_state; spin_lock_irqsave(&xhci->lock, flags); switch (typeReq) { @@ -1421,7 +1465,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) rhub = xhci_get_rhub(hcd); ports = rhub->ports; max_ports = rhub->num_ports; - bus_state = &xhci->bus_state[hcd_index(hcd)]; + bus_state = &rhub->bus_state; /* Initial status is no changes */ retval = (max_ports + 8) / 8; @@ -1480,7 +1524,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) rhub = xhci_get_rhub(hcd); ports = rhub->ports; max_ports = rhub->num_ports; - bus_state = &xhci->bus_state[hcd_index(hcd)]; + bus_state = &rhub->bus_state; wake_enabled = hcd->self.root_hub->do_remote_wakeup; spin_lock_irqsave(&xhci->lock, flags); @@ -1622,7 +1666,7 @@ int xhci_bus_resume(struct usb_hcd *hcd) rhub = xhci_get_rhub(hcd); ports = rhub->ports; max_ports = rhub->num_ports; - bus_state = &xhci->bus_state[hcd_index(hcd)]; + bus_state = &rhub->bus_state; if (time_before(jiffies, bus_state->next_statechange)) msleep(5); @@ -1723,13 +1767,10 @@ int xhci_bus_resume(struct usb_hcd *hcd) unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd) { - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct xhci_bus_state *bus_state; - - bus_state = &xhci->bus_state[hcd_index(hcd)]; + struct xhci_hub *rhub = xhci_get_rhub(hcd); /* USB3 port wakeups are reported via usb_wakeup_notification() */ - return bus_state->resuming_ports; /* USB2 ports only */ + return rhub->bus_state.resuming_ports; /* USB2 ports only */ } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index b1f27aa38b10..36a3eb8849f1 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1922,8 +1922,8 @@ no_bw: xhci->page_size = 0; xhci->page_shift = 0; - xhci->bus_state[0].bus_suspended = 0; - xhci->bus_state[1].bus_suspended = 0; + xhci->usb2_rhub.bus_state.bus_suspended = 0; + xhci->usb3_rhub.bus_state.bus_suspended = 0; } static int xhci_test_trb_in_td(struct xhci_hcd *xhci, @@ -2181,23 +2181,11 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports, if (major_revision < 0x03 && xhci->num_ext_caps < max_caps) xhci->ext_caps[xhci->num_ext_caps++] = temp; - /* Check the host's USB2 LPM capability */ - if ((xhci->hci_version == 0x96) && (major_revision != 0x03) && - (temp & XHCI_L1C)) { + if ((xhci->hci_version >= 0x100) && (major_revision != 0x03) && + (temp & XHCI_HLC)) { xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "xHCI 0.96: support USB2 software lpm"); - xhci->sw_lpm_support = 1; - } - - if ((xhci->hci_version >= 0x100) && (major_revision != 0x03)) { - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "xHCI 1.0: support USB2 software lpm"); - xhci->sw_lpm_support = 1; - if (temp & XHCI_HLC) { - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "xHCI 1.0: support USB2 hardware lpm"); - xhci->hw_lpm_support = 1; - } + "xHCI 1.0: support USB2 hardware lpm"); + xhci->hw_lpm_support = 1; } port_offset--; @@ -2536,10 +2524,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) for (i = 0; i < MAX_HC_SLOTS; i++) xhci->devs[i] = NULL; for (i = 0; i < USB_MAXCHILDREN; i++) { - xhci->bus_state[0].resume_done[i] = 0; - xhci->bus_state[1].resume_done[i] = 0; + xhci->usb2_rhub.bus_state.resume_done[i] = 0; + xhci->usb3_rhub.bus_state.resume_done[i] = 0; /* Only the USB 2.0 completions will ever be used. */ - init_completion(&xhci->bus_state[1].rexit_done[i]); + init_completion(&xhci->usb2_rhub.bus_state.rexit_done[i]); } if (scratchpad_alloc(xhci, flags)) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index a9515265db4d..a9ec7051f286 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -139,6 +139,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == 0x43bb)) xhci->quirks |= XHCI_SUSPEND_DELAY; + if (pdev->vendor == PCI_VENDOR_ID_AMD && + (pdev->device == 0x15e0 || pdev->device == 0x15e1)) + xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND; + if (pdev->vendor == PCI_VENDOR_ID_AMD) xhci->quirks |= XHCI_TRUST_TX_LENGTH; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 65750582133f..40fa25c4d041 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1593,7 +1593,7 @@ static void handle_port_status(struct xhci_hcd *xhci, } hcd = port->rhub->hcd; - bus_state = &xhci->bus_state[hcd_index(hcd)]; + bus_state = &port->rhub->bus_state; hcd_portnum = port->hcd_portnum; portsc = readl(port->addr); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c928dbbff881..46ab9c041091 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -169,7 +169,7 @@ int xhci_reset(struct xhci_hcd *xhci) { u32 command; u32 state; - int ret, i; + int ret; state = readl(&xhci->op_regs->status); @@ -215,11 +215,12 @@ int xhci_reset(struct xhci_hcd *xhci) ret = xhci_handshake(&xhci->op_regs->status, STS_CNR, 0, 10 * 1000 * 1000); - for (i = 0; i < 2; i++) { - xhci->bus_state[i].port_c_suspend = 0; - xhci->bus_state[i].suspended_ports = 0; - xhci->bus_state[i].resuming_ports = 0; - } + xhci->usb2_rhub.bus_state.port_c_suspend = 0; + xhci->usb2_rhub.bus_state.suspended_ports = 0; + xhci->usb2_rhub.bus_state.resuming_ports = 0; + xhci->usb3_rhub.bus_state.port_c_suspend = 0; + xhci->usb3_rhub.bus_state.suspended_ports = 0; + xhci->usb3_rhub.bus_state.resuming_ports = 0; return ret; } @@ -968,6 +969,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) unsigned int delay = XHCI_MAX_HALT_USEC; struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; + u32 res; if (!hcd->state) return 0; @@ -1021,11 +1023,28 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) command = readl(&xhci->op_regs->command); command |= CMD_CSS; writel(command, &xhci->op_regs->command); + xhci->broken_suspend = 0; if (xhci_handshake(&xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { - xhci_warn(xhci, "WARN: xHC save state timeout\n"); - spin_unlock_irq(&xhci->lock); - return -ETIMEDOUT; + /* + * AMD SNPS xHC 3.0 occasionally does not clear the + * SSS bit of USBSTS and when driver tries to poll + * to see if the xHC clears BIT(8) which never happens + * and driver assumes that controller is not responding + * and times out. To workaround this, its good to check + * if SRE and HCE bits are not set (as per xhci + * Section 5.4.2) and bypass the timeout. + */ + res = readl(&xhci->op_regs->status); + if ((xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND) && + (((res & STS_SRE) == 0) && + ((res & STS_HCE) == 0))) { + xhci->broken_suspend = 1; + } else { + xhci_warn(xhci, "WARN: xHC save state timeout\n"); + spin_unlock_irq(&xhci->lock); + return -ETIMEDOUT; + } } spin_unlock_irq(&xhci->lock); @@ -1069,16 +1088,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* Wait a bit if either of the roothubs need to settle from the * transition into bus suspend. */ - if (time_before(jiffies, xhci->bus_state[0].next_statechange) || - time_before(jiffies, - xhci->bus_state[1].next_statechange)) + + if (time_before(jiffies, xhci->usb2_rhub.bus_state.next_statechange) || + time_before(jiffies, xhci->usb3_rhub.bus_state.next_statechange)) msleep(100); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); spin_lock_irq(&xhci->lock); - if (xhci->quirks & XHCI_RESET_ON_RESUME) + if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend) hibernated = true; if (!hibernated) { @@ -4370,8 +4389,7 @@ static int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); int portnum = udev->portnum - 1; - if (hcd->speed >= HCD_USB3 || !xhci->sw_lpm_support || - !udev->lpm_capable) + if (hcd->speed >= HCD_USB3 || !udev->lpm_capable) return 0; /* we only support lpm for non-hub device connected to root hub yet */ @@ -4496,6 +4514,14 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci, { unsigned long long timeout_ns; + /* Prevent U1 if service interval is shorter than U1 exit latency */ + if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { + if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) { + dev_dbg(&udev->dev, "Disable U1, ESIT shorter than exit latency\n"); + return USB3_LPM_DISABLED; + } + } + if (xhci->quirks & XHCI_INTEL_HOST) timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc); else @@ -4552,6 +4578,14 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci, { unsigned long long timeout_ns; + /* Prevent U2 if service interval is shorter than U2 exit latency */ + if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { + if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) { + dev_dbg(&udev->dev, "Disable U2, ESIT shorter than exit latency\n"); + return USB3_LPM_DISABLED; + } + } + if (xhci->quirks & XHCI_INTEL_HOST) timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc); else diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 260b259b72bc..a1638f2aa338 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1682,13 +1682,6 @@ struct xhci_bus_state { */ #define XHCI_MAX_REXIT_TIMEOUT_MS 20 -static inline unsigned int hcd_index(struct usb_hcd *hcd) -{ - if (hcd->speed >= HCD_USB3) - return 0; - else - return 1; -} struct xhci_port { __le32 __iomem *addr; int hw_portnum; @@ -1700,6 +1693,8 @@ struct xhci_hub { struct xhci_port **ports; unsigned int num_ports; struct usb_hcd *hcd; + /* keep track of bus suspend info */ + struct xhci_bus_state bus_state; /* supported prococol extended capabiliy values */ u8 maj_rev; u8 min_rev; @@ -1850,16 +1845,13 @@ struct xhci_hcd { #define XHCI_ZERO_64B_REGS BIT_ULL(32) #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33) #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) +#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) unsigned int num_active_eps; unsigned int limit_active_eps; - /* There are two roothubs to keep track of bus suspend info for */ - struct xhci_bus_state bus_state[2]; struct xhci_port *hw_ports; struct xhci_hub usb2_rhub; struct xhci_hub usb3_rhub; - /* support xHCI 0.96 spec USB2 software LPM */ - unsigned sw_lpm_support:1; /* support xHCI 1.0 spec USB2 hardware LPM */ unsigned hw_lpm_support:1; /* cached usb2 extened protocol capabilites */ @@ -1879,6 +1871,8 @@ struct xhci_hcd { void *dbc; /* platform-specific data -- must come last */ unsigned long priv[0] __aligned(sizeof(s64)); + /* Broken Suspend flag for SNPS Suspend resume issue */ + u8 broken_suspend; }; /* Platform specific overrides to generic XHCI hc_driver ops */ diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 85b48c6ddc7e..ac92725458b5 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -51,6 +51,7 @@ static const struct usb_device_id appledisplay_table[] = { { APPLEDISPLAY_DEVICE(0x921c) }, { APPLEDISPLAY_DEVICE(0x921d) }, { APPLEDISPLAY_DEVICE(0x9222) }, + { APPLEDISPLAY_DEVICE(0x9226) }, { APPLEDISPLAY_DEVICE(0x9236) }, /* Terminating entry */ @@ -68,7 +69,6 @@ struct appledisplay { struct delayed_work work; int button_pressed; - spinlock_t lock; struct mutex sysfslock; /* concurrent read and write */ }; @@ -78,7 +78,6 @@ static void appledisplay_complete(struct urb *urb) { struct appledisplay *pdata = urb->context; struct device *dev = &pdata->udev->dev; - unsigned long flags; int status = urb->status; int retval; @@ -104,8 +103,6 @@ static void appledisplay_complete(struct urb *urb) goto exit; } - spin_lock_irqsave(&pdata->lock, flags); - switch(pdata->urbdata[1]) { case ACD_BTN_BRIGHT_UP: case ACD_BTN_BRIGHT_DOWN: @@ -118,8 +115,6 @@ static void appledisplay_complete(struct urb *urb) break; } - spin_unlock_irqrestore(&pdata->lock, flags); - exit: retval = usb_submit_urb(pdata->urb, GFP_ATOMIC); if (retval) { @@ -228,7 +223,6 @@ static int appledisplay_probe(struct usb_interface *iface, pdata->udev = udev; - spin_lock_init(&pdata->lock); INIT_DELAYED_WORK(&pdata->work, appledisplay_work); mutex_init(&pdata->sysfslock); @@ -260,6 +254,7 @@ static int appledisplay_probe(struct usb_interface *iface, usb_rcvintpipe(udev, int_in_endpointAddr), pdata->urbdata, ACD_URB_BUFFER_LEN, appledisplay_complete, pdata, 1); + pdata->urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; if (usb_submit_urb(pdata->urb, GFP_KERNEL)) { retval = -EIO; dev_err(&iface->dev, "Submitting URB failed\n"); diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 17940589c647..7d289302ff6c 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -101,7 +101,6 @@ static int usb_console_setup(struct console *co, char *options) cflag |= PARENB; break; } - co->cflag = cflag; /* * no need to check the index here: if the index is wrong, console @@ -164,6 +163,7 @@ static int usb_console_setup(struct console *co, char *options) serial->type->set_termios(tty, port, &dummy); tty_port_tty_set(&port->port, NULL); + tty_save_termios(tty); tty_kref_put(tty); } tty_port_set_initialized(&port->port, 1); diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 4d261e4de9ad..c26129d5b943 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -1131,7 +1131,7 @@ static int ms_lib_alloc_writebuf(struct us_data *us) ms_lib_clear_writebuf(us); -return 0; + return 0; } static int ms_lib_force_setlogical_pair(struct us_data *us, u16 logblk, u16 phyblk) diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h index d17cd95b55bb..6b2140f966ef 100644 --- a/drivers/usb/storage/unusual_realtek.h +++ b/drivers/usb/storage/unusual_realtek.h @@ -27,4 +27,14 @@ UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999, "USB Card Reader", USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), +UNUSUAL_DEV(0x0bda, 0x0177, 0x0000, 0x9999, + "Realtek", + "USB Card Reader", + USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), + +UNUSUAL_DEV(0x0bda, 0x0184, 0x0000, 0x9999, + "Realtek", + "USB Card Reader", + USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), + #endif /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */ diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index 43b64d9309d0..e9344997329c 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -1765,7 +1765,7 @@ static int fusb302_probe(struct i2c_client *client, * to be set by the platform code which also registers the i2c client * for the fusb302. */ - if (device_property_read_string(dev, "fcs,extcon-name", &name) == 0) { + if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) { chip->extcon = extcon_get_extcon_dev(name); if (!chip->extcon) return -EPROBE_DEFER; diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index dbbd71f754d0..3620efee2688 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -317,6 +317,9 @@ struct tcpm_port { /* Deadline in jiffies to exit src_try_wait state */ unsigned long max_wait; + /* port belongs to a self powered device */ + bool self_powered; + #ifdef CONFIG_DEBUG_FS struct dentry *dentry; struct mutex logbuffer_lock; /* log buffer access lock */ @@ -3254,7 +3257,8 @@ static void run_state_machine(struct tcpm_port *port) case SRC_HARD_RESET_VBUS_OFF: tcpm_set_vconn(port, true); tcpm_set_vbus(port, false); - tcpm_set_roles(port, false, TYPEC_SOURCE, TYPEC_HOST); + tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE, + TYPEC_HOST); tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); break; case SRC_HARD_RESET_VBUS_ON: @@ -3266,8 +3270,10 @@ static void run_state_machine(struct tcpm_port *port) case SNK_HARD_RESET_SINK_OFF: memset(&port->pps_data, 0, sizeof(port->pps_data)); tcpm_set_vconn(port, false); - tcpm_set_charge(port, false); - tcpm_set_roles(port, false, TYPEC_SINK, TYPEC_DEVICE); + if (port->pd_capable) + tcpm_set_charge(port, false); + tcpm_set_roles(port, port->self_powered, TYPEC_SINK, + TYPEC_DEVICE); /* * VBUS may or may not toggle, depending on the adapter. * If it doesn't toggle, transition to SNK_HARD_RESET_SINK_ON @@ -3297,6 +3303,12 @@ static void run_state_machine(struct tcpm_port *port) * Similar, dual-mode ports in source mode should transition * to PE_SNK_Transition_to_default. */ + if (port->pd_capable) { + tcpm_set_current_limit(port, + tcpm_get_current_limit(port), + 5000); + tcpm_set_charge(port, true); + } tcpm_set_attached_state(port, true); tcpm_set_state(port, SNK_STARTUP, 0); break; @@ -4412,6 +4424,8 @@ sink: return -EINVAL; port->operating_snk_mw = mw / 1000; + port->self_powered = fwnode_property_read_bool(fwnode, "self-powered"); + return 0; } @@ -4720,6 +4734,7 @@ static int tcpm_copy_caps(struct tcpm_port *port, port->typec_caps.prefer_role = tcfg->default_role; port->typec_caps.type = tcfg->type; port->typec_caps.data = tcfg->data; + port->self_powered = port->tcpc->config->self_powered; return 0; } |