diff options
| -rw-r--r-- | drivers/usb/chipidea/udc.c | 20 | ||||
| -rw-r--r-- | drivers/usb/dwc2/params.c | 9 | ||||
| -rw-r--r-- | drivers/usb/dwc2/platform.c | 9 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 15 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.c | 25 | ||||
| -rw-r--r-- | drivers/usb/host/xhci.h | 9 |
6 files changed, 72 insertions, 15 deletions
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 829e947cabf5..6a5ee8e6da10 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
| @@ -1622,6 +1622,25 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) | |||
| 1622 | static int ci_udc_start(struct usb_gadget *gadget, | 1622 | static int ci_udc_start(struct usb_gadget *gadget, |
| 1623 | struct usb_gadget_driver *driver); | 1623 | struct usb_gadget_driver *driver); |
| 1624 | static int ci_udc_stop(struct usb_gadget *gadget); | 1624 | static int ci_udc_stop(struct usb_gadget *gadget); |
| 1625 | |||
| 1626 | /* Match ISOC IN from the highest endpoint */ | ||
| 1627 | static struct usb_ep *ci_udc_match_ep(struct usb_gadget *gadget, | ||
| 1628 | struct usb_endpoint_descriptor *desc, | ||
| 1629 | struct usb_ss_ep_comp_descriptor *comp_desc) | ||
| 1630 | { | ||
| 1631 | struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); | ||
| 1632 | struct usb_ep *ep; | ||
| 1633 | |||
| 1634 | if (usb_endpoint_xfer_isoc(desc) && usb_endpoint_dir_in(desc)) { | ||
| 1635 | list_for_each_entry_reverse(ep, &ci->gadget.ep_list, ep_list) { | ||
| 1636 | if (ep->caps.dir_in && !ep->claimed) | ||
| 1637 | return ep; | ||
| 1638 | } | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | return NULL; | ||
| 1642 | } | ||
| 1643 | |||
| 1625 | /** | 1644 | /** |
| 1626 | * Device operations part of the API to the USB controller hardware, | 1645 | * Device operations part of the API to the USB controller hardware, |
| 1627 | * which don't involve endpoints (or i/o) | 1646 | * which don't involve endpoints (or i/o) |
| @@ -1635,6 +1654,7 @@ static const struct usb_gadget_ops usb_gadget_ops = { | |||
| 1635 | .vbus_draw = ci_udc_vbus_draw, | 1654 | .vbus_draw = ci_udc_vbus_draw, |
| 1636 | .udc_start = ci_udc_start, | 1655 | .udc_start = ci_udc_start, |
| 1637 | .udc_stop = ci_udc_stop, | 1656 | .udc_stop = ci_udc_stop, |
| 1657 | .match_ep = ci_udc_match_ep, | ||
| 1638 | }; | 1658 | }; |
| 1639 | 1659 | ||
| 1640 | static int init_eps(struct ci_hdrc *ci) | 1660 | static int init_eps(struct ci_hdrc *ci) |
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 6900eea57526..5949262ff669 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c | |||
| @@ -253,6 +253,15 @@ static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg) | |||
| 253 | val = (hsotg->hw_params.utmi_phy_data_width == | 253 | val = (hsotg->hw_params.utmi_phy_data_width == |
| 254 | GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; | 254 | GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; |
| 255 | 255 | ||
| 256 | if (hsotg->phy) { | ||
| 257 | /* | ||
| 258 | * If using the generic PHY framework, check if the PHY bus | ||
| 259 | * width is 8-bit and set the phyif appropriately. | ||
| 260 | */ | ||
| 261 | if (phy_get_bus_width(hsotg->phy) == 8) | ||
| 262 | val = 8; | ||
| 263 | } | ||
| 264 | |||
| 256 | hsotg->params.phy_utmi_width = val; | 265 | hsotg->params.phy_utmi_width = val; |
| 257 | } | 266 | } |
| 258 | 267 | ||
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index d10a7f8daec3..e98d7812da2d 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c | |||
| @@ -271,15 +271,6 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) | |||
| 271 | 271 | ||
| 272 | hsotg->plat = dev_get_platdata(hsotg->dev); | 272 | hsotg->plat = dev_get_platdata(hsotg->dev); |
| 273 | 273 | ||
| 274 | if (hsotg->phy) { | ||
| 275 | /* | ||
| 276 | * If using the generic PHY framework, check if the PHY bus | ||
| 277 | * width is 8-bit and set the phyif appropriately. | ||
| 278 | */ | ||
| 279 | if (phy_get_bus_width(hsotg->phy) == 8) | ||
| 280 | hsotg->params.phy_utmi_width = 8; | ||
| 281 | } | ||
| 282 | |||
| 283 | /* Clock */ | 274 | /* Clock */ |
| 284 | hsotg->clk = devm_clk_get_optional(hsotg->dev, "otg"); | 275 | hsotg->clk = devm_clk_get_optional(hsotg->dev, "otg"); |
| 285 | if (IS_ERR(hsotg->clk)) { | 276 | if (IS_ERR(hsotg->clk)) { |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index feffceb31e8a..121782e22c01 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
| @@ -1612,8 +1612,13 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
| 1612 | usb_hcd_resume_root_hub(hcd); | 1612 | usb_hcd_resume_root_hub(hcd); |
| 1613 | } | 1613 | } |
| 1614 | 1614 | ||
| 1615 | if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) | 1615 | if (hcd->speed >= HCD_USB3 && |
| 1616 | (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) { | ||
| 1617 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); | ||
| 1618 | if (slot_id && xhci->devs[slot_id]) | ||
| 1619 | xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR; | ||
| 1616 | bus_state->port_remote_wakeup &= ~(1 << hcd_portnum); | 1620 | bus_state->port_remote_wakeup &= ~(1 << hcd_portnum); |
| 1621 | } | ||
| 1617 | 1622 | ||
| 1618 | if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { | 1623 | if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { |
| 1619 | xhci_dbg(xhci, "port resume event for port %d\n", port_id); | 1624 | xhci_dbg(xhci, "port resume event for port %d\n", port_id); |
| @@ -1801,6 +1806,14 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci, | |||
| 1801 | { | 1806 | { |
| 1802 | struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; | 1807 | struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; |
| 1803 | struct xhci_command *command; | 1808 | struct xhci_command *command; |
| 1809 | |||
| 1810 | /* | ||
| 1811 | * Avoid resetting endpoint if link is inactive. Can cause host hang. | ||
| 1812 | * Device will be reset soon to recover the link so don't do anything | ||
| 1813 | */ | ||
| 1814 | if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) | ||
| 1815 | return; | ||
| 1816 | |||
| 1804 | command = xhci_alloc_command(xhci, false, GFP_ATOMIC); | 1817 | command = xhci_alloc_command(xhci, false, GFP_ATOMIC); |
| 1805 | if (!command) | 1818 | if (!command) |
| 1806 | return; | 1819 | return; |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 20db378a6012..3f79f35d0b19 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
| @@ -1466,6 +1466,10 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag | |||
| 1466 | xhci_dbg(xhci, "urb submitted during PCI suspend\n"); | 1466 | xhci_dbg(xhci, "urb submitted during PCI suspend\n"); |
| 1467 | return -ESHUTDOWN; | 1467 | return -ESHUTDOWN; |
| 1468 | } | 1468 | } |
| 1469 | if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) { | ||
| 1470 | xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n"); | ||
| 1471 | return -ENODEV; | ||
| 1472 | } | ||
| 1469 | 1473 | ||
| 1470 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) | 1474 | if (usb_endpoint_xfer_isoc(&urb->ep->desc)) |
| 1471 | num_tds = urb->number_of_packets; | 1475 | num_tds = urb->number_of_packets; |
| @@ -3754,6 +3758,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, | |||
| 3754 | } | 3758 | } |
| 3755 | /* If necessary, update the number of active TTs on this root port */ | 3759 | /* If necessary, update the number of active TTs on this root port */ |
| 3756 | xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps); | 3760 | xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps); |
| 3761 | virt_dev->flags = 0; | ||
| 3757 | ret = 0; | 3762 | ret = 0; |
| 3758 | 3763 | ||
| 3759 | command_cleanup: | 3764 | command_cleanup: |
| @@ -5060,16 +5065,26 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) | |||
| 5060 | } else { | 5065 | } else { |
| 5061 | /* | 5066 | /* |
| 5062 | * Some 3.1 hosts return sbrn 0x30, use xhci supported protocol | 5067 | * Some 3.1 hosts return sbrn 0x30, use xhci supported protocol |
| 5063 | * minor revision instead of sbrn | 5068 | * minor revision instead of sbrn. Minor revision is a two digit |
| 5069 | * BCD containing minor and sub-minor numbers, only show minor. | ||
| 5064 | */ | 5070 | */ |
| 5065 | minor_rev = xhci->usb3_rhub.min_rev; | 5071 | minor_rev = xhci->usb3_rhub.min_rev / 0x10; |
| 5066 | if (minor_rev) { | 5072 | |
| 5073 | switch (minor_rev) { | ||
| 5074 | case 2: | ||
| 5075 | hcd->speed = HCD_USB32; | ||
| 5076 | hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; | ||
| 5077 | hcd->self.root_hub->rx_lanes = 2; | ||
| 5078 | hcd->self.root_hub->tx_lanes = 2; | ||
| 5079 | break; | ||
| 5080 | case 1: | ||
| 5067 | hcd->speed = HCD_USB31; | 5081 | hcd->speed = HCD_USB31; |
| 5068 | hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; | 5082 | hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; |
| 5083 | break; | ||
| 5069 | } | 5084 | } |
| 5070 | xhci_info(xhci, "Host supports USB 3.%x %s SuperSpeed\n", | 5085 | xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", |
| 5071 | minor_rev, | 5086 | minor_rev, |
| 5072 | minor_rev ? "Enhanced" : ""); | 5087 | minor_rev ? "Enhanced " : ""); |
| 5073 | 5088 | ||
| 5074 | xhci->usb3_rhub.hcd = hcd; | 5089 | xhci->usb3_rhub.hcd = hcd; |
| 5075 | /* xHCI private pointer was set in xhci_pci_probe for the second | 5090 | /* xHCI private pointer was set in xhci_pci_probe for the second |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 7f8b950d1a73..92e764c54154 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
| @@ -1010,6 +1010,15 @@ struct xhci_virt_device { | |||
| 1010 | u8 real_port; | 1010 | u8 real_port; |
| 1011 | struct xhci_interval_bw_table *bw_table; | 1011 | struct xhci_interval_bw_table *bw_table; |
| 1012 | struct xhci_tt_bw_info *tt_info; | 1012 | struct xhci_tt_bw_info *tt_info; |
| 1013 | /* | ||
| 1014 | * flags for state tracking based on events and issued commands. | ||
| 1015 | * Software can not rely on states from output contexts because of | ||
| 1016 | * latency between events and xHC updating output context values. | ||
| 1017 | * See xhci 1.1 section 4.8.3 for more details | ||
| 1018 | */ | ||
| 1019 | unsigned long flags; | ||
| 1020 | #define VDEV_PORT_ERROR BIT(0) /* Port error, link inactive */ | ||
| 1021 | |||
| 1013 | /* The current max exit latency for the enabled USB3 link states. */ | 1022 | /* The current max exit latency for the enabled USB3 link states. */ |
| 1014 | u16 current_mel; | 1023 | u16 current_mel; |
| 1015 | /* Used for the debugfs interfaces. */ | 1024 | /* Used for the debugfs interfaces. */ |
