[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20231011002146.1821-2-quic_wcheng@quicinc.com>
Date: Tue, 10 Oct 2023 17:21:13 -0700
From: Wesley Cheng <quic_wcheng@...cinc.com>
To: <mathias.nyman@...el.com>, <gregkh@...uxfoundation.org>,
<lgirdwood@...il.com>, <broonie@...nel.org>, <perex@...ex.cz>,
<tiwai@...e.com>, <agross@...nel.org>, <andersson@...nel.org>,
<konrad.dybcio@...aro.org>, <robh+dt@...nel.org>,
<krzysztof.kozlowski+dt@...aro.org>, <conor+dt@...nel.org>,
<srinivas.kandagatla@...aro.org>, <bgoswami@...cinc.com>,
<Thinh.Nguyen@...opsys.com>
CC: <linux-usb@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
<alsa-devel@...a-project.org>, <linux-arm-msm@...r.kernel.org>,
<devicetree@...r.kernel.org>,
Mathias Nyman <mathias.nyman@...ux.intel.com>,
Wesley Cheng <quic_wcheng@...cinc.com>
Subject: [PATCH v8 01/34] xhci: split free interrupter into separate remove and free parts
From: Mathias Nyman <mathias.nyman@...ux.intel.com>
The current function that both removes and frees an interrupter isn't
optimal when using several interrupters. The array of interrupters need
to be protected with a lock while removing interrupters, but the default
xhci spin lock can't be used while freeing the interrupters event ring
segment table as dma_free_coherent() should be called with IRQs enabled.
There is no need to free the interrupter under the lock, so split this
code into separate unlocked free part, and a lock protected remove part.
Signed-off-by: Mathias Nyman <mathias.nyman@...ux.intel.com>
Signed-off-by: Wesley Cheng <quic_wcheng@...cinc.com>
---
drivers/usb/host/xhci-mem.c | 32 +++++++++++++++++++++-----------
1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 8714ab5bf04d..a54f74933437 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1797,23 +1797,14 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
}
static void
-xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
+xhci_remove_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
{
- struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
- size_t erst_size;
u64 tmp64;
u32 tmp;
if (!ir)
return;
- erst_size = sizeof(struct xhci_erst_entry) * ir->erst.num_entries;
- if (ir->erst.entries)
- dma_free_coherent(dev, erst_size,
- ir->erst.entries,
- ir->erst.erst_dma_addr);
- ir->erst.entries = NULL;
-
/*
* Clean out interrupter registers except ERSTBA. Clearing either the
* low or high 32 bits of ERSTBA immediately causes the controller to
@@ -1828,10 +1819,28 @@ xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
tmp64 &= (u64) ERST_PTR_MASK;
xhci_write_64(xhci, tmp64, &ir->ir_set->erst_dequeue);
}
+}
+
+static void
+xhci_free_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir)
+{
+ struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
+ size_t erst_size;
+
+ if (!ir)
+ return;
+
+ erst_size = sizeof(struct xhci_erst_entry) * ir->erst.num_entries;
+ if (ir->erst.entries)
+ dma_free_coherent(dev, erst_size,
+ ir->erst.entries,
+ ir->erst.erst_dma_addr);
+ ir->erst.entries = NULL;
- /* free interrrupter event ring */
+ /* free interrupter event ring */
if (ir->event_ring)
xhci_ring_free(xhci, ir->event_ring);
+
ir->event_ring = NULL;
kfree(ir);
@@ -1844,6 +1853,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
cancel_delayed_work_sync(&xhci->cmd_timer);
+ xhci_remove_interrupter(xhci, xhci->interrupter);
xhci_free_interrupter(xhci, xhci->interrupter);
xhci->interrupter = NULL;
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed primary event ring");
Powered by blists - more mailing lists