Commit cf242421 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'usb-5.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are four small USB fixes for 5.2-rc6.

  They include two xhci bugfixes, a chipidea fix, and a small dwc2 fix.
  Nothing major, just nice things to get resolved for reported issues.

  All have been in linux-next with no reported issues"

* tag 'usb-5.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  xhci: detect USB 3.2 capable host controllers correctly
  usb: xhci: Don't try to recover an endpoint if port is in error state.
  usb: dwc2: Use generic PHY width in params setup
  usb: chipidea: udc: workaround for endpoint conflict issue
parents c884d8ac d28bdaff
...@@ -1622,6 +1622,25 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) ...@@ -1622,6 +1622,25 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on)
static int ci_udc_start(struct usb_gadget *gadget, static int ci_udc_start(struct usb_gadget *gadget,
struct usb_gadget_driver *driver); struct usb_gadget_driver *driver);
static int ci_udc_stop(struct usb_gadget *gadget); static int ci_udc_stop(struct usb_gadget *gadget);
/* Match ISOC IN from the highest endpoint */
static struct usb_ep *ci_udc_match_ep(struct usb_gadget *gadget,
struct usb_endpoint_descriptor *desc,
struct usb_ss_ep_comp_descriptor *comp_desc)
{
struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget);
struct usb_ep *ep;
if (usb_endpoint_xfer_isoc(desc) && usb_endpoint_dir_in(desc)) {
list_for_each_entry_reverse(ep, &ci->gadget.ep_list, ep_list) {
if (ep->caps.dir_in && !ep->claimed)
return ep;
}
}
return NULL;
}
/** /**
* Device operations part of the API to the USB controller hardware, * Device operations part of the API to the USB controller hardware,
* which don't involve endpoints (or i/o) * which don't involve endpoints (or i/o)
...@@ -1635,6 +1654,7 @@ static const struct usb_gadget_ops usb_gadget_ops = { ...@@ -1635,6 +1654,7 @@ static const struct usb_gadget_ops usb_gadget_ops = {
.vbus_draw = ci_udc_vbus_draw, .vbus_draw = ci_udc_vbus_draw,
.udc_start = ci_udc_start, .udc_start = ci_udc_start,
.udc_stop = ci_udc_stop, .udc_stop = ci_udc_stop,
.match_ep = ci_udc_match_ep,
}; };
static int init_eps(struct ci_hdrc *ci) static int init_eps(struct ci_hdrc *ci)
......
...@@ -253,6 +253,15 @@ static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg) ...@@ -253,6 +253,15 @@ static void dwc2_set_param_phy_utmi_width(struct dwc2_hsotg *hsotg)
val = (hsotg->hw_params.utmi_phy_data_width == val = (hsotg->hw_params.utmi_phy_data_width ==
GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16; GHWCFG4_UTMI_PHY_DATA_WIDTH_8) ? 8 : 16;
if (hsotg->phy) {
/*
* If using the generic PHY framework, check if the PHY bus
* width is 8-bit and set the phyif appropriately.
*/
if (phy_get_bus_width(hsotg->phy) == 8)
val = 8;
}
hsotg->params.phy_utmi_width = val; hsotg->params.phy_utmi_width = val;
} }
......
...@@ -271,15 +271,6 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg) ...@@ -271,15 +271,6 @@ static int dwc2_lowlevel_hw_init(struct dwc2_hsotg *hsotg)
hsotg->plat = dev_get_platdata(hsotg->dev); hsotg->plat = dev_get_platdata(hsotg->dev);
if (hsotg->phy) {
/*
* If using the generic PHY framework, check if the PHY bus
* width is 8-bit and set the phyif appropriately.
*/
if (phy_get_bus_width(hsotg->phy) == 8)
hsotg->params.phy_utmi_width = 8;
}
/* Clock */ /* Clock */
hsotg->clk = devm_clk_get_optional(hsotg->dev, "otg"); hsotg->clk = devm_clk_get_optional(hsotg->dev, "otg");
if (IS_ERR(hsotg->clk)) { if (IS_ERR(hsotg->clk)) {
......
...@@ -1612,8 +1612,13 @@ static void handle_port_status(struct xhci_hcd *xhci, ...@@ -1612,8 +1612,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(hcd);
} }
if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) if (hcd->speed >= HCD_USB3 &&
(portsc & PORT_PLS_MASK) == XDEV_INACTIVE) {
slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
if (slot_id && xhci->devs[slot_id])
xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
bus_state->port_remote_wakeup &= ~(1 << hcd_portnum); bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
}
if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
xhci_dbg(xhci, "port resume event for port %d\n", port_id); 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,6 +1806,14 @@ static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci,
{ {
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
struct xhci_command *command; struct xhci_command *command;
/*
* Avoid resetting endpoint if link is inactive. Can cause host hang.
* Device will be reset soon to recover the link so don't do anything
*/
if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR)
return;
command = xhci_alloc_command(xhci, false, GFP_ATOMIC); command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
if (!command) if (!command)
return; return;
......
...@@ -1466,6 +1466,10 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag ...@@ -1466,6 +1466,10 @@ static int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
xhci_dbg(xhci, "urb submitted during PCI suspend\n"); xhci_dbg(xhci, "urb submitted during PCI suspend\n");
return -ESHUTDOWN; return -ESHUTDOWN;
} }
if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) {
xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n");
return -ENODEV;
}
if (usb_endpoint_xfer_isoc(&urb->ep->desc)) if (usb_endpoint_xfer_isoc(&urb->ep->desc))
num_tds = urb->number_of_packets; num_tds = urb->number_of_packets;
...@@ -3754,6 +3758,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd, ...@@ -3754,6 +3758,7 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
} }
/* If necessary, update the number of active TTs on this root port */ /* If necessary, update the number of active TTs on this root port */
xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps); xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps);
virt_dev->flags = 0;
ret = 0; ret = 0;
command_cleanup: command_cleanup:
...@@ -5060,16 +5065,26 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) ...@@ -5060,16 +5065,26 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
} else { } else {
/* /*
* Some 3.1 hosts return sbrn 0x30, use xhci supported protocol * Some 3.1 hosts return sbrn 0x30, use xhci supported protocol
* minor revision instead of sbrn * minor revision instead of sbrn. Minor revision is a two digit
* BCD containing minor and sub-minor numbers, only show minor.
*/ */
minor_rev = xhci->usb3_rhub.min_rev; minor_rev = xhci->usb3_rhub.min_rev / 0x10;
if (minor_rev) {
switch (minor_rev) {
case 2:
hcd->speed = HCD_USB32;
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
hcd->self.root_hub->rx_lanes = 2;
hcd->self.root_hub->tx_lanes = 2;
break;
case 1:
hcd->speed = HCD_USB31; hcd->speed = HCD_USB31;
hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS;
break;
} }
xhci_info(xhci, "Host supports USB 3.%x %s SuperSpeed\n", xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n",
minor_rev, minor_rev,
minor_rev ? "Enhanced" : ""); minor_rev ? "Enhanced " : "");
xhci->usb3_rhub.hcd = hcd; xhci->usb3_rhub.hcd = hcd;
/* xHCI private pointer was set in xhci_pci_probe for the second /* xHCI private pointer was set in xhci_pci_probe for the second
......
...@@ -1010,6 +1010,15 @@ struct xhci_virt_device { ...@@ -1010,6 +1010,15 @@ struct xhci_virt_device {
u8 real_port; u8 real_port;
struct xhci_interval_bw_table *bw_table; struct xhci_interval_bw_table *bw_table;
struct xhci_tt_bw_info *tt_info; struct xhci_tt_bw_info *tt_info;
/*
* flags for state tracking based on events and issued commands.
* Software can not rely on states from output contexts because of
* latency between events and xHC updating output context values.
* See xhci 1.1 section 4.8.3 for more details
*/
unsigned long flags;
#define VDEV_PORT_ERROR BIT(0) /* Port error, link inactive */
/* The current max exit latency for the enabled USB3 link states. */ /* The current max exit latency for the enabled USB3 link states. */
u16 current_mel; u16 current_mel;
/* Used for the debugfs interfaces. */ /* Used for the debugfs interfaces. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment