Skip to content

Commit 12de0a3

Browse files
Marc Zyngiergregkh
authored andcommitted
xhci: Add quirk to zero 64bit registers on Renesas PCIe controllers
Some Renesas controllers get into a weird state if they are reset while programmed with 64bit addresses (they will preserve the top half of the address in internal, non visible registers). You end up with half the address coming from the kernel, and the other half coming from the firmware. Also, changing the programming leads to extra accesses even if the controller is supposed to be halted. The controller ends up with a fatal fault, and is then ripe for being properly reset. On the flip side, this is completely unsafe if the defvice isn't behind an IOMMU, so we have to make sure that this is the case. Can you say "broken"? This is an alternative method to the one introduced in 8466489 ("xhci: Reset Renesas uPD72020x USB controller for 32-bit DMA issue"), which will subsequently be removed. Tested-by: Domenico Andreoli <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Tested-by: Faiz Abbas <[email protected]> Tested-by: Domenico Andreoli <[email protected]> Acked-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 36b6857 commit 12de0a3

File tree

3 files changed

+72
-2
lines changed

3 files changed

+72
-2
lines changed

drivers/usb/host/xhci-pci.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,15 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
196196
xhci->quirks |= XHCI_BROKEN_STREAMS;
197197
}
198198
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
199-
pdev->device == 0x0014)
199+
pdev->device == 0x0014) {
200200
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
201+
xhci->quirks |= XHCI_ZERO_64B_REGS;
202+
}
201203
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
202-
pdev->device == 0x0015)
204+
pdev->device == 0x0015) {
203205
xhci->quirks |= XHCI_RESET_ON_RESUME;
206+
xhci->quirks |= XHCI_ZERO_64B_REGS;
207+
}
204208
if (pdev->vendor == PCI_VENDOR_ID_VIA)
205209
xhci->quirks |= XHCI_RESET_ON_RESUME;
206210

drivers/usb/host/xhci.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,68 @@ int xhci_reset(struct xhci_hcd *xhci)
209209
return ret;
210210
}
211211

212+
static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
213+
{
214+
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
215+
int err, i;
216+
u64 val;
217+
218+
/*
219+
* Some Renesas controllers get into a weird state if they are
220+
* reset while programmed with 64bit addresses (they will preserve
221+
* the top half of the address in internal, non visible
222+
* registers). You end up with half the address coming from the
223+
* kernel, and the other half coming from the firmware. Also,
224+
* changing the programming leads to extra accesses even if the
225+
* controller is supposed to be halted. The controller ends up with
226+
* a fatal fault, and is then ripe for being properly reset.
227+
*
228+
* Special care is taken to only apply this if the device is behind
229+
* an iommu. Doing anything when there is no iommu is definitely
230+
* unsafe...
231+
*/
232+
if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !dev->iommu_group)
233+
return;
234+
235+
xhci_info(xhci, "Zeroing 64bit base registers, expecting fault\n");
236+
237+
/* Clear HSEIE so that faults do not get signaled */
238+
val = readl(&xhci->op_regs->command);
239+
val &= ~CMD_HSEIE;
240+
writel(val, &xhci->op_regs->command);
241+
242+
/* Clear HSE (aka FATAL) */
243+
val = readl(&xhci->op_regs->status);
244+
val |= STS_FATAL;
245+
writel(val, &xhci->op_regs->status);
246+
247+
/* Now zero the registers, and brace for impact */
248+
val = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
249+
if (upper_32_bits(val))
250+
xhci_write_64(xhci, 0, &xhci->op_regs->dcbaa_ptr);
251+
val = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
252+
if (upper_32_bits(val))
253+
xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring);
254+
255+
for (i = 0; i < HCS_MAX_INTRS(xhci->hcs_params1); i++) {
256+
struct xhci_intr_reg __iomem *ir;
257+
258+
ir = &xhci->run_regs->ir_set[i];
259+
val = xhci_read_64(xhci, &ir->erst_base);
260+
if (upper_32_bits(val))
261+
xhci_write_64(xhci, 0, &ir->erst_base);
262+
val= xhci_read_64(xhci, &ir->erst_dequeue);
263+
if (upper_32_bits(val))
264+
xhci_write_64(xhci, 0, &ir->erst_dequeue);
265+
}
266+
267+
/* Wait for the fault to appear. It will be cleared on reset */
268+
err = xhci_handshake(&xhci->op_regs->status,
269+
STS_FATAL, STS_FATAL,
270+
XHCI_MAX_HALT_USEC);
271+
if (!err)
272+
xhci_info(xhci, "Fault detected\n");
273+
}
212274

213275
#ifdef CONFIG_USB_PCI
214276
/*
@@ -1006,6 +1068,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
10061068

10071069
xhci_dbg(xhci, "Stop HCD\n");
10081070
xhci_halt(xhci);
1071+
xhci_zero_64b_regs(xhci);
10091072
xhci_reset(xhci);
10101073
spin_unlock_irq(&xhci->lock);
10111074
xhci_cleanup_msix(xhci);
@@ -4917,6 +4980,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
49174980
if (retval)
49184981
return retval;
49194982

4983+
xhci_zero_64b_regs(xhci);
4984+
49204985
xhci_dbg(xhci, "Resetting HCD\n");
49214986
/* Reset the internal HC memory state and registers. */
49224987
retval = xhci_reset(xhci);

drivers/usb/host/xhci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,7 @@ struct xhci_hcd {
18411841
#define XHCI_HW_LPM_DISABLE BIT_ULL(29)
18421842
#define XHCI_SUSPEND_DELAY BIT_ULL(30)
18431843
#define XHCI_INTEL_USB_ROLE_SW BIT_ULL(31)
1844+
#define XHCI_ZERO_64B_REGS BIT_ULL(32)
18441845

18451846
unsigned int num_active_eps;
18461847
unsigned int limit_active_eps;

0 commit comments

Comments
 (0)