diff options
author | Josue David Hernandez Gutierrez <josue.d.hernandez.gutierrez@intel.com> | 2023-03-17 17:47:12 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2023-03-23 17:25:22 +0100 |
commit | ed526ba2ecdfb77bcdbcf4331b8380b646252c20 (patch) | |
tree | 40462ab813b6921a1800f61bf42e06d66ce11618 /drivers/usb/host | |
parent | fabbd95cc47cc412e68d03476367046f4cdbd838 (diff) | |
download | linux-stable-ed526ba2ecdfb77bcdbcf4331b8380b646252c20.tar.gz linux-stable-ed526ba2ecdfb77bcdbcf4331b8380b646252c20.tar.bz2 linux-stable-ed526ba2ecdfb77bcdbcf4331b8380b646252c20.zip |
xhci: move PCI specific MSI/MSIX cleanup away from generic xhci functions
Call the PCI specific MSI/MSIX interrupt freeing code from the xhci-pci
callbacks instead of generic xhci code, decoupling PCI parts from
generic xhci functions.
Adds xhci_pci_stop() that overrides xhci_stop() for PCI xHC controllers.
This will free MSIX interrupts a bit later in the hc_driver stop
callback, but is still earlier than usb core frees "legacy" interrupts,
or interrupts for other hosts.
Signed-off-by: Josue David Hernandez Gutierrez <josue.d.hernandez.gutierrez@intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20230317154715.535523-12-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/xhci-pci.c | 12 | ||||
-rw-r--r-- | drivers/usb/host/xhci.c | 10 | ||||
-rw-r--r-- | drivers/usb/host/xhci.h | 2 |
3 files changed, 18 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 2d56b7477fcd..b6cfc028f8f7 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -230,6 +230,16 @@ static int xhci_pci_run(struct usb_hcd *hcd) return xhci_run(hcd); } +static void xhci_pci_stop(struct usb_hcd *hcd) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + + xhci_stop(hcd); + + if (usb_hcd_is_primary_hcd(hcd)) + xhci_cleanup_msix(xhci); +} + /* called after powerup, by probe or system-pm "wakeup" */ static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev) { @@ -868,6 +878,7 @@ static void xhci_pci_shutdown(struct usb_hcd *hcd) struct pci_dev *pdev = to_pci_dev(hcd->self.controller); xhci_shutdown(hcd); + xhci_cleanup_msix(xhci); /* Yet another workaround for spurious wakeups at shutdown with HSW */ if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) @@ -932,6 +943,7 @@ static int __init xhci_pci_init(void) xhci_pci_hc_driver.pci_poweroff_late = xhci_pci_poweroff_late; xhci_pci_hc_driver.shutdown = xhci_pci_shutdown; #endif + xhci_pci_hc_driver.stop = xhci_pci_stop; return pci_register_driver(&xhci_pci_driver); } module_init(xhci_pci_init); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9be84e635e1b..cf90751125ed 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -321,7 +321,7 @@ static int xhci_disable_interrupter(struct xhci_interrupter *ir) #ifdef CONFIG_USB_PCI /* Free any IRQs and disable MSI-X */ -static void xhci_cleanup_msix(struct xhci_hcd *xhci) +void xhci_cleanup_msix(struct xhci_hcd *xhci) { struct usb_hcd *hcd = xhci_to_hcd(xhci); struct pci_dev *pdev = to_pci_dev(hcd->self.controller); @@ -345,6 +345,7 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) pci_free_irq_vectors(pdev); hcd->msix_enabled = 0; } +EXPORT_SYMBOL_GPL(xhci_cleanup_msix); static void __maybe_unused xhci_msix_sync_irqs(struct xhci_hcd *xhci) { @@ -617,7 +618,7 @@ EXPORT_SYMBOL_GPL(xhci_run); * Disable device contexts, disable IRQs, and quiesce the HC. * Reset the HC, finish any completed transactions, and cleanup memory. */ -static void xhci_stop(struct usb_hcd *hcd) +void xhci_stop(struct usb_hcd *hcd) { u32 temp; struct xhci_hcd *xhci = hcd_to_xhci(hcd); @@ -640,8 +641,6 @@ static void xhci_stop(struct usb_hcd *hcd) xhci_reset(xhci, XHCI_RESET_SHORT_USEC); spin_unlock_irq(&xhci->lock); - xhci_cleanup_msix(xhci); - /* Deleting Compliance Mode Recovery Timer */ if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && (!(xhci_all_ports_seen_u0(xhci)))) { @@ -668,6 +667,7 @@ static void xhci_stop(struct usb_hcd *hcd) readl(&xhci->op_regs->status)); mutex_unlock(&xhci->mutex); } +EXPORT_SYMBOL_GPL(xhci_stop); /* * Shutdown HC (not bus-specific) @@ -709,8 +709,6 @@ void xhci_shutdown(struct usb_hcd *hcd) spin_unlock_irq(&xhci->lock); - xhci_cleanup_msix(xhci); - xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_shutdown completed - status = %x", readl(&xhci->op_regs->status)); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 786002bb35db..a9111260632c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -2125,6 +2125,7 @@ int xhci_reset(struct xhci_hcd *xhci, u64 timeout_us); int xhci_run(struct usb_hcd *hcd); int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); void xhci_shutdown(struct usb_hcd *hcd); +void xhci_stop(struct usb_hcd *hcd); void xhci_init_driver(struct hc_driver *drv, const struct xhci_driver_overrides *over); int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, @@ -2143,6 +2144,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated); irqreturn_t xhci_irq(struct usb_hcd *hcd); irqreturn_t xhci_msi_irq(int irq, void *hcd); +void xhci_cleanup_msix(struct xhci_hcd *xhci); int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); int xhci_alloc_tt_info(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, |