diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-06-03 21:17:49 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-06-03 21:17:49 +0300 |
commit | 54c2cc79194c961a213c1d375fe3aa4165664cc4 (patch) | |
tree | a6f03d84b18dcab2a03c0d162327bba2f577cfb5 /drivers/usb/host/xhci.c | |
parent | 932c2989b59008e530ffcc7c7e6ef507a28b28ca (diff) | |
parent | 97fa5887cf283bb75ffff5f6b2c0e71794c02400 (diff) | |
download | linux-54c2cc79194c961a213c1d375fe3aa4165664cc4.tar.xz |
Merge tag 'usb-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / Thunderbolt updates from Greg KH:
"Here is the "big" set of USB and Thunderbolt driver changes for
5.18-rc1. For the most part it's been a quiet development cycle for
the USB core, but there are the usual "hot spots" of development
activity.
Included in here are:
- Thunderbolt driver updates:
- fixes for devices without displayport adapters
- lane bonding support and improvements
- other minor changes based on device testing
- dwc3 gadget driver changes.
It seems this driver will never be finished given that the IP core
is showing up in zillions of new devices and each implementation
decides to do something different with it...
- uvc gadget driver updates as more devices start to use and rely on
this hardware as well
- usb_maxpacket() api changes to remove an unneeded and unused
parameter.
- usb-serial driver device id updates and small cleanups
- typec cleanups and fixes based on device testing
- device tree updates for usb properties
- lots of other small fixes and driver updates.
All of these have been in linux-next for weeks with no reported
problems"
* tag 'usb-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (154 commits)
USB: new quirk for Dell Gen 2 devices
usb: dwc3: core: Add error log when core soft reset failed
usb: dwc3: gadget: Move null pinter check to proper place
usb: hub: Simplify error and success path in port_over_current_notify
usb: cdns3: allocate TX FIFO size according to composite EP number
usb: dwc3: Fix ep0 handling when getting reset while doing control transfer
usb: Probe EHCI, OHCI controllers asynchronously
usb: isp1760: Fix out-of-bounds array access
xhci: Don't defer primary roothub registration if there is only one roothub
USB: serial: option: add Quectel BG95 modem
USB: serial: pl2303: fix type detection for odd device
xhci: Allow host runtime PM as default for Intel Alder Lake N xHCI
xhci: Remove quirk for over 10 year old evaluation hardware
xhci: prevent U2 link power state if Intel tier policy prevented U1
xhci: use generic command timer for stop endpoint commands.
usb: host: xhci-plat: omit shared hcd if either root hub has no ports
usb: host: xhci-plat: prepare operation w/o shared hcd
usb: host: xhci-plat: create shared hcd after having added main hcd
xhci: prepare for operation w/o shared hcd
xhci: factor out parts of xhci_gen_setup()
...
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r-- | drivers/usb/host/xhci.c | 175 |
1 files changed, 94 insertions, 81 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 25b87e99b4dd..f0ab63138016 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -486,6 +486,10 @@ static void compliance_mode_recovery(struct timer_list *t) xhci = from_timer(xhci, t, comp_mode_recovery_timer); rhub = &xhci->usb3_rhub; + hcd = rhub->hcd; + + if (!hcd) + return; for (i = 0; i < rhub->num_ports; i++) { temp = readl(rhub->ports[i]->addr); @@ -499,7 +503,6 @@ static void compliance_mode_recovery(struct timer_list *t) i + 1); xhci_dbg_trace(xhci, trace_xhci_dbg_quirks, "Attempting compliance mode recovery"); - hcd = xhci->shared_hcd; if (hcd->state == HC_STATE_SUSPENDED) usb_hcd_resume_root_hub(hcd); @@ -612,14 +615,11 @@ static int xhci_run_finished(struct xhci_hcd *xhci) xhci_halt(xhci); return -ENODEV; } - xhci->shared_hcd->state = HC_STATE_RUNNING; xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Finished xhci_run for USB3 roothub"); return 0; } @@ -694,12 +694,17 @@ int xhci_run(struct usb_hcd *hcd) xhci_free_command(xhci, command); } xhci_dbg_trace(xhci, trace_xhci_dbg_init, - "Finished xhci_run for USB2 roothub"); + "Finished %s for main hcd", __func__); xhci_create_dbc_dev(xhci); xhci_debugfs_init(xhci); + if (xhci_has_one_roothub(xhci)) + return xhci_run_finished(xhci); + + set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags); + return 0; } EXPORT_SYMBOL_GPL(xhci_run); @@ -992,7 +997,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) return 0; if (hcd->state != HC_STATE_SUSPENDED || - xhci->shared_hcd->state != HC_STATE_SUSPENDED) + (xhci->shared_hcd && xhci->shared_hcd->state != HC_STATE_SUSPENDED)) return -EINVAL; /* Clear root port wake on bits if wakeup not allowed. */ @@ -1009,15 +1014,18 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) __func__, hcd->self.busnum); clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); del_timer_sync(&hcd->rh_timer); - clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); - del_timer_sync(&xhci->shared_hcd->rh_timer); + if (xhci->shared_hcd) { + clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + del_timer_sync(&xhci->shared_hcd->rh_timer); + } if (xhci->quirks & XHCI_SUSPEND_DELAY) usleep_range(1000, 1500); spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + if (xhci->shared_hcd) + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); /* step 1: stop endpoint */ /* skipped assuming that port suspend has done */ @@ -1117,7 +1125,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) msleep(100); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); + if (xhci->shared_hcd) + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); spin_lock_irq(&xhci->lock); @@ -1177,7 +1186,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* Let the USB core know _both_ roothubs lost power. */ usb_root_hub_lost_power(xhci->main_hcd->self.root_hub); - usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); + if (xhci->shared_hcd) + usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); xhci_dbg(xhci, "Stop HCD\n"); xhci_halt(xhci); @@ -1217,12 +1227,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) xhci_dbg(xhci, "Start the primary HCD\n"); retval = xhci_run(hcd->primary_hcd); - if (!retval) { + if (!retval && secondary_hcd) { xhci_dbg(xhci, "Start the secondary HCD\n"); retval = xhci_run(secondary_hcd); } hcd->state = HC_STATE_SUSPENDED; - xhci->shared_hcd->state = HC_STATE_SUSPENDED; + if (xhci->shared_hcd) + xhci->shared_hcd->state = HC_STATE_SUSPENDED; goto done; } @@ -1260,7 +1271,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) } if (pending_portevent) { - usb_hcd_resume_root_hub(xhci->shared_hcd); + if (xhci->shared_hcd) + usb_hcd_resume_root_hub(xhci->shared_hcd); usb_hcd_resume_root_hub(hcd); } } @@ -1279,8 +1291,10 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* Re-enable port polling. */ xhci_dbg(xhci, "%s: starting usb%d port polling.\n", __func__, hcd->self.busnum); - set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); - usb_hcd_poll_rh_status(xhci->shared_hcd); + if (xhci->shared_hcd) { + set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); + usb_hcd_poll_rh_status(xhci->shared_hcd); + } set_bit(HCD_FLAG_POLL_RH, &hcd->flags); usb_hcd_poll_rh_status(hcd); @@ -1860,9 +1874,6 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) goto done; } ep->ep_state |= EP_STOP_CMD_PENDING; - ep->stop_cmd_timer.expires = jiffies + - XHCI_STOP_EP_CMD_TIMEOUT * HZ; - add_timer(&ep->stop_cmd_timer); xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id, ep_index, 0); xhci_ring_cmd_db(xhci); @@ -3972,10 +3983,8 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) trace_xhci_free_dev(slot_ctx); /* Stop any wayward timer functions (which may grab the lock) */ - for (i = 0; i < 31; i++) { + for (i = 0; i < 31; i++) virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING; - del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); - } virt_dev->udev = NULL; xhci_disable_slot(xhci, udev->slot_id); xhci_free_virt_device(xhci, udev->slot_id); @@ -4879,9 +4888,6 @@ static int xhci_check_intel_tier_policy(struct usb_device *udev, struct usb_device *parent; unsigned int num_hubs; - if (state == USB3_LPM_U2) - return 0; - /* Don't enable U1 if the device is on a 2nd tier hub or lower. */ for (parent = udev->parent, num_hubs = 0; parent->parent; parent = parent->parent) @@ -4890,7 +4896,7 @@ static int xhci_check_intel_tier_policy(struct usb_device *udev, if (num_hubs < 2) return 0; - dev_dbg(&udev->dev, "Disabling U1 link state for device" + dev_dbg(&udev->dev, "Disabling U1/U2 link state for device" " below second-tier hub.\n"); dev_dbg(&udev->dev, "Plug device into first-tier hub " "to decrease power consumption.\n"); @@ -4931,9 +4937,6 @@ static u16 xhci_calculate_lpm_timeout(struct usb_hcd *hcd, return timeout; } - if (xhci_check_tier_policy(xhci, udev, state) < 0) - return timeout; - /* Gather some information about the currently installed configuration * and alternate interface settings. */ @@ -5040,6 +5043,9 @@ static int xhci_enable_usb3_lpm_timeout(struct usb_hcd *hcd, !xhci->devs[udev->slot_id]) return USB3_LPM_DISABLED; + if (xhci_check_tier_policy(xhci, udev, state) < 0) + return USB3_LPM_DISABLED; + hub_encoded_timeout = xhci_calculate_lpm_timeout(hcd, udev, state); mel = calculate_max_exit_latency(udev, state, hub_encoded_timeout); if (mel < 0) { @@ -5207,6 +5213,57 @@ static int xhci_get_frame(struct usb_hcd *hcd) return readl(&xhci->run_regs->microframe_index) >> 3; } +static void xhci_hcd_init_usb2_data(struct xhci_hcd *xhci, struct usb_hcd *hcd) +{ + xhci->usb2_rhub.hcd = hcd; + hcd->speed = HCD_USB2; + hcd->self.root_hub->speed = USB_SPEED_HIGH; + /* + * USB 2.0 roothub under xHCI has an integrated TT, + * (rate matching hub) as opposed to having an OHCI/UHCI + * companion controller. + */ + hcd->has_tt = 1; +} + +static void xhci_hcd_init_usb3_data(struct xhci_hcd *xhci, struct usb_hcd *hcd) +{ + unsigned int minor_rev; + + /* + * Early xHCI 1.1 spec did not mention USB 3.1 capable hosts + * should return 0x31 for sbrn, or that the minor revision + * is a two digit BCD containig minor and sub-minor numbers. + * This was later clarified in xHCI 1.2. + * + * Some USB 3.1 capable hosts therefore have sbrn 0x30, and + * minor revision set to 0x1 instead of 0x10. + */ + if (xhci->usb3_rhub.min_rev == 0x1) + minor_rev = 1; + else + minor_rev = xhci->usb3_rhub.min_rev / 0x10; + + 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; + hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x2; + break; + case 1: + hcd->speed = HCD_USB31; + hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; + hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x1; + break; + } + xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", + minor_rev, minor_rev ? "Enhanced " : ""); + + xhci->usb3_rhub.hcd = hcd; +} + int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) { struct xhci_hcd *xhci; @@ -5215,7 +5272,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) * quirks */ struct device *dev = hcd->self.sysdev; - unsigned int minor_rev; int retval; /* Accept arbitrarily long scatter-gather lists */ @@ -5229,61 +5285,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) xhci = hcd_to_xhci(hcd); - if (usb_hcd_is_primary_hcd(hcd)) { - xhci->main_hcd = hcd; - xhci->usb2_rhub.hcd = hcd; - /* Mark the first roothub as being USB 2.0. - * The xHCI driver will register the USB 3.0 roothub. - */ - hcd->speed = HCD_USB2; - hcd->self.root_hub->speed = USB_SPEED_HIGH; - /* - * USB 2.0 roothub under xHCI has an integrated TT, - * (rate matching hub) as opposed to having an OHCI/UHCI - * companion controller. - */ - hcd->has_tt = 1; - } else { - /* - * Early xHCI 1.1 spec did not mention USB 3.1 capable hosts - * should return 0x31 for sbrn, or that the minor revision - * is a two digit BCD containig minor and sub-minor numbers. - * This was later clarified in xHCI 1.2. - * - * Some USB 3.1 capable hosts therefore have sbrn 0x30, and - * minor revision set to 0x1 instead of 0x10. - */ - if (xhci->usb3_rhub.min_rev == 0x1) - minor_rev = 1; - else - minor_rev = xhci->usb3_rhub.min_rev / 0x10; - - 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; - hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x2; - break; - case 1: - hcd->speed = HCD_USB31; - hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; - hcd->self.root_hub->ssp_rate = USB_SSP_GEN_2x1; - break; - } - xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", - minor_rev, - minor_rev ? "Enhanced " : ""); - - xhci->usb3_rhub.hcd = hcd; - /* xHCI private pointer was set in xhci_pci_probe for the second - * registered roothub. - */ + if (!usb_hcd_is_primary_hcd(hcd)) { + xhci_hcd_init_usb3_data(xhci, hcd); return 0; } mutex_init(&xhci->mutex); + xhci->main_hcd = hcd; xhci->cap_regs = hcd->regs; xhci->op_regs = hcd->regs + HC_LENGTH(readl(&xhci->cap_regs->hc_capbase)); @@ -5358,6 +5366,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) return retval; xhci_dbg(xhci, "Called HCD init\n"); + if (xhci_hcd_is_usb3(hcd)) + xhci_hcd_init_usb3_data(xhci, hcd); + else + xhci_hcd_init_usb2_data(xhci, hcd); + xhci_info(xhci, "hcc params 0x%08x hci version 0x%x quirks 0x%016llx\n", xhci->hcc_params, xhci->hci_version, xhci->quirks); |