From e636c8d336489bf3eed5878299e6cc045bbad077 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Tue, 20 Feb 2024 01:17:29 +0000
Subject: [PATCH] debug lk
---
kernel/drivers/usb/host/xhci.c | 638 ++++++++++++++++++++++++++++-----------------------------
1 files changed, 311 insertions(+), 327 deletions(-)
diff --git a/kernel/drivers/usb/host/xhci.c b/kernel/drivers/usb/host/xhci.c
index d614382..f16dcdd 100644
--- a/kernel/drivers/usb/host/xhci.c
+++ b/kernel/drivers/usb/host/xhci.c
@@ -9,6 +9,9 @@
*/
#include <linux/pci.h>
+#ifndef __GENKSYMS__ /* ANDROID: KABI CRC preservation hack */
+#include <linux/iommu.h>
+#endif
#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/log2.h>
@@ -17,11 +20,9 @@
#include <linux/slab.h>
#include <linux/dmi.h>
#include <linux/dma-mapping.h>
-#include <linux/usb/quirks.h>
#include "xhci.h"
#include "xhci-trace.h"
-#include "xhci-mtk.h"
#include "xhci-debugfs.h"
#include "xhci-dbgcap.h"
@@ -67,7 +68,7 @@
* handshake done). There are two failure modes: "usec" have passed (major
* hardware flakeout), or the register reads as all-ones (hardware removed).
*/
-int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
+int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us)
{
u32 result;
int ret;
@@ -75,7 +76,7 @@
ret = readl_poll_timeout_atomic(ptr, result,
(result & mask) == done ||
result == U32_MAX,
- 1, usec);
+ 1, timeout_us);
if (result == U32_MAX) /* card removed */
return -ENODEV;
@@ -164,11 +165,11 @@
* Transactions will be terminated immediately, and operational registers
* will be set to their defaults.
*/
-int xhci_reset(struct xhci_hcd *xhci)
+int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us)
{
u32 command;
u32 state;
- int ret, i;
+ int ret;
state = readl(&xhci->op_regs->status);
@@ -197,8 +198,7 @@
if (xhci->quirks & XHCI_INTEL_HOST)
udelay(1000);
- ret = xhci_handshake(&xhci->op_regs->command,
- CMD_RESET, 0, 10 * 1000 * 1000);
+ ret = xhci_handshake(&xhci->op_regs->command, CMD_RESET, 0, timeout_us);
if (ret)
return ret;
@@ -211,14 +211,14 @@
* xHCI cannot write to any doorbells or operational registers other
* than status until the "Controller Not Ready" flag is cleared.
*/
- ret = xhci_handshake(&xhci->op_regs->status,
- STS_CNR, 0, 10 * 1000 * 1000);
+ ret = xhci_handshake(&xhci->op_regs->status, STS_CNR, 0, timeout_us);
- 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;
}
@@ -226,6 +226,7 @@
static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+ struct iommu_domain *domain;
int err, i;
u64 val;
u32 intrs;
@@ -244,7 +245,9 @@
* an iommu. Doing anything when there is no iommu is definitely
* unsafe...
*/
- if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !dev->iommu_group)
+ domain = iommu_get_domain_for_dev(dev);
+ if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !domain ||
+ domain->type == IOMMU_DOMAIN_IDENTITY)
return;
xhci_info(xhci, "Zeroing 64bit base registers, expecting fault\n");
@@ -696,6 +699,8 @@
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Finished xhci_run for USB2 roothub");
+ set_bit(HCD_FLAG_DEFER_RH_REGISTER, &hcd->flags);
+
xhci_dbc_init(xhci);
xhci_debugfs_init(xhci);
@@ -732,7 +737,7 @@
xhci->xhc_state |= XHCI_STATE_HALTED;
xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
xhci_halt(xhci);
- xhci_reset(xhci);
+ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
spin_unlock_irq(&xhci->lock);
xhci_cleanup_msix(xhci);
@@ -778,23 +783,31 @@
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- if (!hcd->rh_registered)
- return;
-
- /* Don't poll the roothubs on shutdown */
- 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->quirks & XHCI_SPURIOUS_REBOOT)
usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev));
+ /* Don't poll the roothubs after shutdown. */
+ xhci_dbg(xhci, "%s: stopping usb%d port polling.\n",
+ __func__, hcd->self.busnum);
+ clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+ del_timer_sync(&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);
+ }
+
spin_lock_irq(&xhci->lock);
xhci_halt(xhci);
- /* Workaround for spurious wakeups at shutdown with HSW */
- if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
- xhci_reset(xhci);
+
+ /*
+ * Workaround for spurious wakeps at shutdown with HSW, and for boot
+ * firmware delay in ADL-P PCH if port are left in U3 at shutdown
+ */
+ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP ||
+ xhci->quirks & XHCI_RESET_TO_DEFAULT)
+ xhci_reset(xhci, XHCI_RESET_SHORT_USEC);
+
spin_unlock_irq(&xhci->lock);
xhci_cleanup_msix(xhci);
@@ -896,37 +909,44 @@
xhci_set_cmd_ring_deq(xhci);
}
-static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
+/*
+ * Disable port wake bits if do_wakeup is not set.
+ *
+ * Also clear a possible internal port wake state left hanging for ports that
+ * detected termination but never successfully enumerated (trained to 0U).
+ * Internal wake causes immediate xHCI wake after suspend. PORT_CSC write done
+ * at enumeration clears this wake, force one here as well for unconnected ports
+ */
+
+static void xhci_disable_hub_port_wake(struct xhci_hcd *xhci,
+ struct xhci_hub *rhub,
+ bool do_wakeup)
{
- struct xhci_port **ports;
- int port_index;
unsigned long flags;
- u32 t1, t2;
+ u32 t1, t2, portsc;
+ int i;
spin_lock_irqsave(&xhci->lock, flags);
- /* disable usb3 ports Wake bits */
- port_index = xhci->usb3_rhub.num_ports;
- ports = xhci->usb3_rhub.ports;
- while (port_index--) {
- t1 = readl(ports[port_index]->addr);
- t1 = xhci_port_state_to_neutral(t1);
- t2 = t1 & ~PORT_WAKE_BITS;
- if (t1 != t2)
- writel(t2, ports[port_index]->addr);
- }
+ for (i = 0; i < rhub->num_ports; i++) {
+ portsc = readl(rhub->ports[i]->addr);
+ t1 = xhci_port_state_to_neutral(portsc);
+ t2 = t1;
- /* disable usb2 ports Wake bits */
- port_index = xhci->usb2_rhub.num_ports;
- ports = xhci->usb2_rhub.ports;
- while (port_index--) {
- t1 = readl(ports[port_index]->addr);
- t1 = xhci_port_state_to_neutral(t1);
- t2 = t1 & ~PORT_WAKE_BITS;
- if (t1 != t2)
- writel(t2, ports[port_index]->addr);
- }
+ /* clear wake bits if do_wake is not set */
+ if (!do_wakeup)
+ t2 &= ~PORT_WAKE_BITS;
+ /* Don't touch csc bit if connected or connect change is set */
+ if (!(portsc & (PORT_CSC | PORT_CONNECT)))
+ t2 |= PORT_CSC;
+
+ if (t1 != t2) {
+ writel(t2, rhub->ports[i]->addr);
+ xhci_dbg(xhci, "config port %d-%d wake bits, portsc: 0x%x, write: 0x%x\n",
+ rhub->hcd->self.busnum, i + 1, portsc, t2);
+ }
+ }
spin_unlock_irqrestore(&xhci->lock, flags);
}
@@ -965,26 +985,6 @@
return false;
}
-static void xhci_warm_port_reset_quirk(struct xhci_hcd *xhci)
-{
- struct xhci_port **ports;
- int port_index;
- u32 portsc;
-
- port_index = xhci->usb3_rhub.num_ports;
- ports = xhci->usb3_rhub.ports;
- while (port_index--) {
- portsc = readl(ports[port_index]->addr);
- /* Do warm port reset if no USB3 device connected */
- if (!(portsc & PORT_CONNECT)) {
- portsc |= PORT_WR;
- writel(portsc, ports[port_index]->addr);
- /* flush write */
- readl(ports[port_index]->addr);
- }
- }
-}
-
/*
* Stop HC (not bus-specific)
*
@@ -1007,15 +1007,8 @@
return -EINVAL;
/* Clear root port wake on bits if wakeup not allowed. */
- if (!do_wakeup)
- xhci_disable_port_wake_on_bits(xhci);
-
- /*
- * Do a warm reset for USB3 port to resets the USB3 link,
- * forcing the link to enter the Rx.Detect state.
- */
- if (xhci->quirks & XHCI_WARM_RESET_ON_SUSPEND)
- xhci_warm_port_reset_quirk(xhci);
+ xhci_disable_hub_port_wake(xhci, &xhci->usb3_rhub, do_wakeup);
+ xhci_disable_hub_port_wake(xhci, &xhci->usb2_rhub, do_wakeup);
if (!HCD_HW_ACCESSIBLE(hcd))
return 0;
@@ -1023,7 +1016,8 @@
xhci_dbc_suspend(xhci);
/* Don't poll the roothubs on bus suspend. */
- xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
+ xhci_dbg(xhci, "%s: stopping usb%d port polling.\n",
+ __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);
@@ -1128,9 +1122,9 @@
/* 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);
@@ -1181,7 +1175,8 @@
/* re-initialize the HC on Restore Error, or Host Controller Error */
if (temp & (STS_SRE | STS_HCE)) {
reinit_xhc = true;
- xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp);
+ if (!xhci->broken_suspend)
+ xhci_warn(xhci, "xHC error in resume, USBSTS 0x%x, Reinit\n", temp);
}
if (reinit_xhc) {
@@ -1199,7 +1194,7 @@
xhci_dbg(xhci, "Stop HCD\n");
xhci_halt(xhci);
xhci_zero_64b_regs(xhci);
- retval = xhci_reset(xhci);
+ retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
spin_unlock_irq(&xhci->lock);
if (retval)
return retval;
@@ -1271,7 +1266,7 @@
* the first wake signalling failed, give it that chance.
*/
pending_portevent = xhci_pending_portevent(xhci);
- if (!pending_portevent) {
+ if (!pending_portevent && !IS_ENABLED(CONFIG_ARCH_ROCKCHIP)) {
msleep(120);
pending_portevent = xhci_pending_portevent(xhci);
}
@@ -1294,7 +1289,8 @@
usb_asmedia_modifyflowcontrol(to_pci_dev(hcd->self.controller));
/* Re-enable port polling. */
- xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+ 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);
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
@@ -1307,7 +1303,22 @@
/*-------------------------------------------------------------------------*/
-/**
+/*
+ * Bypass the DMA mapping if URB is suitable for Immediate Transfer (IDT),
+ * we'll copy the actual data into the TRB address register. This is limited to
+ * transfers up to 8 bytes on output endpoints of any kind with wMaxPacketSize
+ * >= 8 bytes. If suitable for IDT only one Transfer TRB per TD is allowed.
+ */
+static int xhci_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
+ gfp_t mem_flags)
+{
+ if (xhci_urb_suitable_for_idt(urb))
+ return 0;
+
+ return usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
+}
+
+/*
* xhci_get_endpoint_index - Used for passing endpoint bitmasks between the core and
* HCDs. Find the index for an endpoint given its descriptor. Use the return
* value to right shift 1 for the bitmask.
@@ -1327,6 +1338,7 @@
(usb_endpoint_dir_in(desc) ? 1 : 0) - 1;
return index;
}
+EXPORT_SYMBOL_GPL(xhci_get_endpoint_index);
/* The reverse operation to xhci_get_endpoint_index. Calculate the USB endpoint
* address from the XHCI endpoint index.
@@ -1345,15 +1357,6 @@
static unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc)
{
return 1 << (xhci_get_endpoint_index(desc) + 1);
-}
-
-/* Find the flag for this endpoint (for use in the control context). Use the
- * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is
- * bit 1, etc.
- */
-static unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index)
-{
- return 1 << (ep_index + 1);
}
/* Compute the last valid endpoint context index. Basically, this is the
@@ -1522,6 +1525,11 @@
return -ENODEV;
}
+ if (xhci_vendor_usb_offload_skip_urb(xhci, urb)) {
+ xhci_dbg(xhci, "skip urb for usb offload\n");
+ return -EOPNOTSUPP;
+ }
+
if (usb_endpoint_xfer_isoc(&urb->ep->desc))
num_tds = urb->number_of_packets;
else if (usb_endpoint_is_bulk_out(&urb->ep->desc) &&
@@ -1532,8 +1540,7 @@
else
num_tds = 1;
- urb_priv = kzalloc(sizeof(struct urb_priv) +
- num_tds * sizeof(struct xhci_td), mem_flags);
+ urb_priv = kzalloc(struct_size(urb_priv, td, num_tds), mem_flags);
if (!urb_priv)
return -ENOMEM;
@@ -1723,7 +1730,12 @@
for (; i < urb_priv->num_tds; i++) {
td = &urb_priv->td[i];
- list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
+ /* TD can already be on cancelled list if ep halted on it */
+ if (list_empty(&td->cancelled_td_list)) {
+ td->cancel_status = TD_DIRTY;
+ list_add_tail(&td->cancelled_td_list,
+ &ep->cancelled_td_list);
+ }
}
/* Queue a stop endpoint command, but only if this is
@@ -1769,8 +1781,8 @@
* disabled, so there's no need for mutual exclusion to protect
* the xhci->devs[slot_id] structure.
*/
-static int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep)
+int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
struct xhci_container_ctx *in_ctx, *out_ctx;
@@ -1830,9 +1842,6 @@
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
- if (xhci->quirks & XHCI_MTK_HOST)
- xhci_mtk_drop_ep_quirk(hcd, udev, ep);
-
xhci_dbg(xhci, "drop ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
(unsigned int) ep->desc.bEndpointAddress,
udev->slot_id,
@@ -1840,6 +1849,7 @@
(unsigned int) new_add_flags);
return 0;
}
+EXPORT_SYMBOL_GPL(xhci_drop_endpoint);
/* Add an endpoint to a new possible bandwidth configuration for this device.
* Only one call to this function is allowed per endpoint before
@@ -1854,13 +1864,14 @@
* configuration or alt setting is installed in the device, so there's no need
* for mutual exclusion to protect the xhci->devs[slot_id] structure.
*/
-static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
- struct usb_host_endpoint *ep)
+int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
struct xhci_container_ctx *in_ctx;
unsigned int ep_index;
struct xhci_input_control_ctx *ctrl_ctx;
+ struct xhci_ep_ctx *ep_ctx;
u32 added_ctxs;
u32 new_add_flags, new_drop_flags;
struct xhci_virt_device *virt_dev;
@@ -1928,15 +1939,6 @@
return -ENOMEM;
}
- if (xhci->quirks & XHCI_MTK_HOST) {
- ret = xhci_mtk_add_ep_quirk(hcd, udev, ep);
- if (ret < 0) {
- xhci_ring_free(xhci, virt_dev->eps[ep_index].new_ring);
- virt_dev->eps[ep_index].new_ring = NULL;
- return ret;
- }
- }
-
ctrl_ctx->add_flags |= cpu_to_le32(added_ctxs);
new_add_flags = le32_to_cpu(ctrl_ctx->add_flags);
@@ -1951,7 +1953,8 @@
/* Store the usb_device pointer for later use */
ep->hcpriv = udev;
- xhci_debugfs_create_endpoint(xhci, virt_dev, ep_index);
+ ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index);
+ trace_xhci_add_endpoint(ep_ctx);
xhci_dbg(xhci, "add ep 0x%x, slot id %d, new drop flags = %#x, new add flags = %#x\n",
(unsigned int) ep->desc.bEndpointAddress,
@@ -1960,6 +1963,7 @@
(unsigned int) new_add_flags);
return 0;
}
+EXPORT_SYMBOL_GPL(xhci_add_endpoint);
static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev)
{
@@ -2825,6 +2829,8 @@
}
slot_ctx = xhci_get_slot_ctx(xhci, command->in_ctx);
+
+ trace_xhci_configure_endpoint_ctrl_ctx(ctrl_ctx);
trace_xhci_configure_endpoint(slot_ctx);
if (!ctx_change)
@@ -2867,6 +2873,14 @@
xhci_finish_resource_reservation(xhci, ctrl_ctx);
spin_unlock_irqrestore(&xhci->lock, flags);
}
+ if (ret)
+ goto failed;
+
+ ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+ if (ret)
+ xhci_warn(xhci, "sync device context failed, ret=%d", ret);
+
+failed:
return ret;
}
@@ -2894,7 +2908,7 @@
* else should be touching the xhci->devs[slot_id] structure, so we
* don't need to take the xhci->lock for manipulating that.
*/
-static int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
int i;
int ret = 0;
@@ -2983,6 +2997,7 @@
xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
virt_dev->eps[i].new_ring = NULL;
+ xhci_debugfs_create_endpoint(xhci, virt_dev, i);
}
command_cleanup:
kfree(command->completion);
@@ -2990,8 +3005,9 @@
return ret;
}
+EXPORT_SYMBOL_GPL(xhci_check_bandwidth);
-static void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd *xhci;
struct xhci_virt_device *virt_dev;
@@ -3008,12 +3024,17 @@
for (i = 0; i < 31; i++) {
if (virt_dev->eps[i].new_ring) {
xhci_debugfs_remove_endpoint(xhci, virt_dev, i);
- xhci_ring_free(xhci, virt_dev->eps[i].new_ring);
+ if (xhci_vendor_is_usb_offload_enabled(xhci, virt_dev, i))
+ xhci_vendor_free_transfer_ring(xhci, virt_dev, i);
+ else
+ xhci_ring_free(xhci, virt_dev->eps[i].new_ring);
+
virt_dev->eps[i].new_ring = NULL;
}
}
xhci_zero_in_ctx(xhci, virt_dev);
}
+EXPORT_SYMBOL_GPL(xhci_reset_bandwidth);
static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
struct xhci_container_ctx *in_ctx,
@@ -3027,82 +3048,46 @@
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
}
-static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
- unsigned int slot_id, unsigned int ep_index,
- struct xhci_dequeue_state *deq_state)
+static void xhci_endpoint_disable(struct usb_hcd *hcd,
+ struct usb_host_endpoint *host_ep)
{
- struct xhci_input_control_ctx *ctrl_ctx;
- struct xhci_container_ctx *in_ctx;
- struct xhci_ep_ctx *ep_ctx;
- u32 added_ctxs;
- dma_addr_t addr;
+ struct xhci_hcd *xhci;
+ struct xhci_virt_device *vdev;
+ struct xhci_virt_ep *ep;
+ struct usb_device *udev;
+ unsigned long flags;
+ unsigned int ep_index;
- in_ctx = xhci->devs[slot_id]->in_ctx;
- ctrl_ctx = xhci_get_input_control_ctx(in_ctx);
- if (!ctrl_ctx) {
- xhci_warn(xhci, "%s: Could not get input context, bad type.\n",
- __func__);
- return;
+ xhci = hcd_to_xhci(hcd);
+rescan:
+ spin_lock_irqsave(&xhci->lock, flags);
+
+ udev = (struct usb_device *)host_ep->hcpriv;
+ if (!udev || !udev->slot_id)
+ goto done;
+
+ vdev = xhci->devs[udev->slot_id];
+ if (!vdev)
+ goto done;
+
+ ep_index = xhci_get_endpoint_index(&host_ep->desc);
+ ep = &vdev->eps[ep_index];
+ if (!ep)
+ goto done;
+
+ /* wait for hub_tt_work to finish clearing hub TT */
+ if (ep->ep_state & EP_CLEARING_TT) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ schedule_timeout_uninterruptible(1);
+ goto rescan;
}
- xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
- xhci->devs[slot_id]->out_ctx, ep_index);
- ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
- addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg,
- deq_state->new_deq_ptr);
- if (addr == 0) {
- xhci_warn(xhci, "WARN Cannot submit config ep after "
- "reset ep command\n");
- xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n",
- deq_state->new_deq_seg,
- deq_state->new_deq_ptr);
- return;
- }
- ep_ctx->deq = cpu_to_le64(addr | deq_state->new_cycle_state);
-
- added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
- xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx,
- xhci->devs[slot_id]->out_ctx, ctrl_ctx,
- added_ctxs, added_ctxs);
-}
-
-void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int ep_index,
- unsigned int stream_id, struct xhci_td *td)
-{
- struct xhci_dequeue_state deq_state;
- struct usb_device *udev = td->urb->dev;
-
- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
- "Cleaning up stalled endpoint ring");
- /* We need to move the HW's dequeue pointer past this TD,
- * or it will attempt to resend it on the next doorbell ring.
- */
- xhci_find_new_dequeue_state(xhci, udev->slot_id,
- ep_index, stream_id, td, &deq_state);
-
- if (!deq_state.new_deq_ptr || !deq_state.new_deq_seg)
- return;
-
- /* HW with the reset endpoint quirk will use the saved dequeue state to
- * issue a configure endpoint command later.
- */
- if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) {
- xhci_dbg_trace(xhci, trace_xhci_dbg_reset_ep,
- "Queueing new dequeue state");
- xhci_queue_new_dequeue_state(xhci, udev->slot_id,
- ep_index, &deq_state);
- } else {
- /* Better hope no one uses the input context between now and the
- * reset endpoint completion!
- * XXX: No idea how this hardware will react when stream rings
- * are enabled.
- */
- xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
- "Setting up input context for "
- "configure endpoint command");
- xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id,
- ep_index, &deq_state);
- }
+ if (ep->ep_state)
+ xhci_dbg(xhci, "endpoint disable with ep_state 0x%x\n",
+ ep->ep_state);
+done:
+ host_ep->hcpriv = NULL;
+ spin_unlock_irqrestore(&xhci->lock, flags);
}
/*
@@ -3136,8 +3121,18 @@
return;
udev = (struct usb_device *) host_ep->hcpriv;
vdev = xhci->devs[udev->slot_id];
+
+ /*
+ * vdev may be lost due to xHC restore error and re-initialization
+ * during S3/S4 resume. A new vdev will be allocated later by
+ * xhci_discover_or_reset_device()
+ */
+ if (!udev->slot_id || !vdev)
+ return;
ep_index = xhci_get_endpoint_index(&host_ep->desc);
ep = &vdev->eps[ep_index];
+ if (!ep)
+ return;
/* Bail out if toggle is already being cleared by a endpoint reset */
spin_lock_irqsave(&xhci->lock, flags);
@@ -3198,6 +3193,13 @@
wait_for_completion(stop_cmd->completion);
+ err = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+ if (err) {
+ xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+ __func__, err);
+ goto cleanup;
+ }
+
spin_lock_irqsave(&xhci->lock, flags);
/* config ep command clears toggle if add and drop ep flags are set */
@@ -3228,6 +3230,11 @@
spin_unlock_irqrestore(&xhci->lock, flags);
wait_for_completion(cfg_cmd->completion);
+
+ err = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+ if (err)
+ xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+ __func__, err);
xhci_free_command(xhci, cfg_cmd);
cleanup:
@@ -3530,6 +3537,10 @@
xhci_free_command(xhci, config_cmd);
spin_unlock_irqrestore(&xhci->lock, flags);
+ for (i = 0; i < num_eps; i++) {
+ ep_index = xhci_get_endpoint_index(&eps[i]->desc);
+ xhci_debugfs_create_stream_files(xhci, vdev, ep_index);
+ }
/* Subtract 1 for stream 0, which drivers can't use */
return num_streams - 1;
@@ -3770,6 +3781,13 @@
/* Wait for the Reset Device command to finish */
wait_for_completion(reset_device_cmd->completion);
+ ret = xhci_vendor_sync_dev_ctx(xhci, slot_id);
+ if (ret) {
+ xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+ __func__, ret);
+ goto command_cleanup;
+ }
+
/* The Reset Device command can't fail, according to the 0.95/0.96 spec,
* unless we tried to reset a slot ID that wasn't enabled,
* or the device wasn't in the addressed or configured state.
@@ -3855,6 +3873,7 @@
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_virt_device *virt_dev;
struct xhci_slot_ctx *slot_ctx;
+ unsigned long flags;
int i, ret;
/*
@@ -3881,10 +3900,13 @@
virt_dev->eps[i].ep_state &= ~EP_STOP_CMD_PENDING;
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
}
- xhci_debugfs_remove_slot(xhci, udev->slot_id);
virt_dev->udev = NULL;
xhci_disable_slot(xhci, udev->slot_id);
+
+ spin_lock_irqsave(&xhci->lock, flags);
xhci_free_virt_device(xhci, udev->slot_id);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
}
int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id)
@@ -3897,6 +3919,8 @@
command = xhci_alloc_command(xhci, true, GFP_KERNEL);
if (!command)
return -ENOMEM;
+
+ xhci_debugfs_remove_slot(xhci, slot_id);
spin_lock_irqsave(&xhci->lock, flags);
/* Don't disable the slot if the host controller is dead. */
@@ -4014,6 +4038,14 @@
xhci_warn(xhci, "Could not allocate xHCI USB device data structures\n");
goto disable_slot;
}
+
+ ret = xhci_vendor_sync_dev_ctx(xhci, slot_id);
+ if (ret) {
+ xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+ __func__, ret);
+ goto disable_slot;
+ }
+
vdev = xhci->devs[slot_id];
slot_ctx = xhci_get_slot_ctx(xhci, vdev->out_ctx);
trace_xhci_alloc_dev(slot_ctx);
@@ -4127,6 +4159,7 @@
trace_xhci_address_ctx(xhci, virt_dev->in_ctx,
le32_to_cpu(slot_ctx->dev_info) >> 27);
+ trace_xhci_address_ctrl_ctx(ctrl_ctx);
spin_lock_irqsave(&xhci->lock, flags);
trace_xhci_setup_device(virt_dev);
ret = xhci_queue_address_device(xhci, command, virt_dev->in_ctx->dma,
@@ -4142,6 +4175,13 @@
/* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */
wait_for_completion(command->completion);
+
+ ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+ if (ret) {
+ xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+ __func__, ret);
+ goto out;
+ }
/* FIXME: From section 4.3.4: "Software shall be responsible for timing
* the SetAddress() "recovery interval" required by USB and aborting the
@@ -4212,6 +4252,8 @@
/* Zero the input context control for later use */
ctrl_ctx->add_flags = 0;
ctrl_ctx->drop_flags = 0;
+ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
+ udev->devaddr = (u8)(le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK);
xhci_dbg_trace(xhci, trace_xhci_dbg_address,
"Internal device address = %d",
@@ -4225,10 +4267,11 @@
return ret;
}
-static int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
+int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
{
return xhci_setup_device(hcd, udev, SETUP_CONTEXT_ADDRESS);
}
+EXPORT_SYMBOL_GPL(xhci_address_device);
static int xhci_enable_device(struct usb_hcd *hcd, struct usb_device *udev)
{
@@ -4288,6 +4331,14 @@
return -ENOMEM;
}
+ ret = xhci_vendor_sync_dev_ctx(xhci, udev->slot_id);
+ if (ret) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+ __func__, ret);
+ return ret;
+ }
+
xhci_slot_copy(xhci, command->in_ctx, virt_dev->out_ctx);
spin_unlock_irqrestore(&xhci->lock, flags);
@@ -4310,6 +4361,30 @@
spin_unlock_irqrestore(&xhci->lock, flags);
}
return ret;
+}
+
+struct xhci_vendor_ops *xhci_vendor_get_ops(struct xhci_hcd *xhci)
+{
+ return xhci->vendor_ops;
+}
+EXPORT_SYMBOL_GPL(xhci_vendor_get_ops);
+
+int xhci_vendor_sync_dev_ctx(struct xhci_hcd *xhci, unsigned int slot_id)
+{
+ struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+ if (ops && ops->sync_dev_ctx)
+ return ops->sync_dev_ctx(xhci, slot_id);
+ return 0;
+}
+
+bool xhci_vendor_usb_offload_skip_urb(struct xhci_hcd *xhci, struct urb *urb)
+{
+ struct xhci_vendor_ops *ops = xhci_vendor_get_ops(xhci);
+
+ if (ops && ops->usb_offload_skip_urb)
+ return ops->usb_offload_skip_urb(xhci, urb);
+ return false;
}
#ifdef CONFIG_PM
@@ -4510,8 +4585,7 @@
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 */
@@ -4615,7 +4689,7 @@
break;
}
/* Otherwise the calculation is the same as isoc eps */
- /* fall through */
+ fallthrough;
case USB_ENDPOINT_XFER_ISOC:
timeout_ns = xhci_service_interval_to_ns(desc);
timeout_ns = DIV_ROUND_UP_ULL(timeout_ns * 105, 100);
@@ -5052,6 +5126,15 @@
return -ENOMEM;
}
+ ret = xhci_vendor_sync_dev_ctx(xhci, hdev->slot_id);
+ if (ret) {
+ xhci_warn(xhci, "%s: Failed to sync device context failed, err=%d",
+ __func__, ret);
+ xhci_free_command(xhci, config_cmd);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ return ret;
+ }
+
xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx);
ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
@@ -5188,9 +5271,6 @@
/* xHCI private pointer was set in xhci_pci_probe for the second
* registered roothub.
*/
- if (xhci->quirks & XHCI_DIS_AUTOSUSPEND)
- xhci->shared_hcd->self.root_hub->quirks |=
- USB_QUIRK_AUTO_SUSPEND;
return 0;
}
@@ -5230,7 +5310,7 @@
xhci_dbg(xhci, "Resetting HCD\n");
/* Reset the internal HC memory state and registers. */
- retval = xhci_reset(xhci);
+ retval = xhci_reset(xhci, XHCI_RESET_LONG_USEC);
if (retval)
return retval;
xhci_dbg(xhci, "Reset complete\n");
@@ -5277,134 +5357,25 @@
}
EXPORT_SYMBOL_GPL(xhci_gen_setup);
-static phys_addr_t xhci_get_sec_event_ring_phys_addr(struct usb_hcd *hcd,
- unsigned int intr_num, dma_addr_t *dma)
-{
- struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- struct device *dev = hcd->self.sysdev;
- struct sg_table sgt;
- phys_addr_t pa;
-
- if (intr_num > xhci->max_interrupters) {
- xhci_err(xhci, "intr num %d > max intrs %d\n", intr_num,
- xhci->max_interrupters);
- return 0;
- }
-
- if (!(xhci->xhc_state & XHCI_STATE_HALTED) &&
- xhci->sec_event_ring && xhci->sec_event_ring[intr_num]
- && xhci->sec_event_ring[intr_num]->first_seg) {
-
- dma_get_sgtable(dev, &sgt,
- xhci->sec_event_ring[intr_num]->first_seg->trbs,
- xhci->sec_event_ring[intr_num]->first_seg->dma,
- TRB_SEGMENT_SIZE);
-
- *dma = xhci->sec_event_ring[intr_num]->first_seg->dma;
-
- pa = page_to_phys(sg_page(sgt.sgl));
- sg_free_table(&sgt);
-
- return pa;
- }
-
- return 0;
-}
-
-static phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_hcd *hcd,
- struct usb_device *udev, struct usb_host_endpoint *ep, dma_addr_t *dma)
-{
- int ret;
- unsigned int ep_index;
- struct xhci_virt_device *virt_dev;
- struct device *dev = hcd->self.sysdev;
- struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- struct sg_table sgt;
- phys_addr_t pa;
-
- ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
- if (ret <= 0) {
- xhci_err(xhci, "%s: invalid args\n", __func__);
- return 0;
- }
-
- virt_dev = xhci->devs[udev->slot_id];
- ep_index = xhci_get_endpoint_index(&ep->desc);
-
- if (virt_dev->eps[ep_index].ring &&
- virt_dev->eps[ep_index].ring->first_seg) {
-
- dma_get_sgtable(dev, &sgt,
- virt_dev->eps[ep_index].ring->first_seg->trbs,
- virt_dev->eps[ep_index].ring->first_seg->dma,
- TRB_SEGMENT_SIZE);
-
- *dma = virt_dev->eps[ep_index].ring->first_seg->dma;
-
- pa = page_to_phys(sg_page(sgt.sgl));
- sg_free_table(&sgt);
-
- return pa;
- }
-
- return 0;
-}
-
-static int xhci_stop_endpoint(struct usb_hcd *hcd,
- struct usb_device *udev, struct usb_host_endpoint *ep)
+static void xhci_clear_tt_buffer_complete(struct usb_hcd *hcd,
+ struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
+ struct usb_device *udev;
+ unsigned int slot_id;
unsigned int ep_index;
- struct xhci_virt_device *virt_dev;
- struct xhci_command *cmd;
unsigned long flags;
- int ret = 0;
-
- if (!hcd || !udev || !ep)
- return -EINVAL;
xhci = hcd_to_xhci(hcd);
- cmd = xhci_alloc_command(xhci, true, GFP_NOIO);
- if (!cmd)
- return -ENOMEM;
spin_lock_irqsave(&xhci->lock, flags);
- virt_dev = xhci->devs[udev->slot_id];
- if (!virt_dev) {
- ret = -ENODEV;
- goto err;
- }
-
+ udev = (struct usb_device *)ep->hcpriv;
+ slot_id = udev->slot_id;
ep_index = xhci_get_endpoint_index(&ep->desc);
- if (virt_dev->eps[ep_index].ring &&
- virt_dev->eps[ep_index].ring->dequeue) {
- ret = xhci_queue_stop_endpoint(xhci, cmd, udev->slot_id,
- ep_index, 0);
- if (ret)
- goto err;
- xhci_ring_cmd_db(xhci);
- spin_unlock_irqrestore(&xhci->lock, flags);
-
- /* Wait for stop endpoint command to finish */
- wait_for_completion(cmd->completion);
-
- if (cmd->status == COMP_COMMAND_ABORTED ||
- cmd->status == COMP_STOPPED) {
- xhci_warn(xhci,
- "stop endpoint command timeout for ep%d%s\n",
- usb_endpoint_num(&ep->desc),
- usb_endpoint_dir_in(&ep->desc) ? "in" : "out");
- ret = -ETIME;
- }
- goto free_cmd;
- }
-
-err:
+ xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_CLEARING_TT;
+ xhci_ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
spin_unlock_irqrestore(&xhci->lock, flags);
-free_cmd:
- xhci_free_command(xhci, cmd);
- return ret;
}
static const struct hc_driver xhci_hc_driver = {
@@ -5416,7 +5387,8 @@
* generic hardware linkage
*/
.irq = xhci_irq,
- .flags = HCD_MEMORY | HCD_USB3 | HCD_SHARED,
+ .flags = HCD_MEMORY | HCD_DMA | HCD_USB3 | HCD_SHARED |
+ HCD_BH,
/*
* basic lifecycle operations
@@ -5429,6 +5401,7 @@
/*
* managing i/o requests and associated device resources
*/
+ .map_urb_for_dma = xhci_map_urb_for_dma,
.urb_enqueue = xhci_urb_enqueue,
.urb_dequeue = xhci_urb_dequeue,
.alloc_dev = xhci_alloc_dev,
@@ -5437,6 +5410,7 @@
.free_streams = xhci_free_streams,
.add_endpoint = xhci_add_endpoint,
.drop_endpoint = xhci_drop_endpoint,
+ .endpoint_disable = xhci_endpoint_disable,
.endpoint_reset = xhci_endpoint_reset,
.check_bandwidth = xhci_check_bandwidth,
.reset_bandwidth = xhci_reset_bandwidth,
@@ -5467,11 +5441,7 @@
.enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout,
.disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout,
.find_raw_port_number = xhci_find_raw_port_number,
- .sec_event_ring_setup = xhci_sec_event_ring_setup,
- .sec_event_ring_cleanup = xhci_sec_event_ring_cleanup,
- .get_sec_event_ring_phys_addr = xhci_get_sec_event_ring_phys_addr,
- .get_xfer_ring_phys_addr = xhci_get_xfer_ring_phys_addr,
- .stop_endpoint = xhci_stop_endpoint,
+ .clear_tt_buffer_complete = xhci_clear_tt_buffer_complete,
};
void xhci_init_driver(struct hc_driver *drv,
@@ -5488,6 +5458,20 @@
drv->reset = over->reset;
if (over->start)
drv->start = over->start;
+ if (over->add_endpoint)
+ drv->add_endpoint = over->add_endpoint;
+ if (over->drop_endpoint)
+ drv->drop_endpoint = over->drop_endpoint;
+ if (over->check_bandwidth)
+ drv->check_bandwidth = over->check_bandwidth;
+ if (over->reset_bandwidth)
+ drv->reset_bandwidth = over->reset_bandwidth;
+ if (over->address_device)
+ drv->address_device = over->address_device;
+ if (over->bus_suspend)
+ drv->bus_suspend = over->bus_suspend;
+ if (over->bus_resume)
+ drv->bus_resume = over->bus_resume;
}
}
EXPORT_SYMBOL_GPL(xhci_init_driver);
--
Gitblit v1.6.2