Commit 7570a333d8b00e7fd4b05d898e353000a70210ce

Authored by MUNEDA Takahiro
Committed by Jesse Barnes
1 parent 34a4876e30

PCI: Add pcie_hp=nomsi to disable MSI/MSI-X for pciehp driver

Add a parameter to avoid using MSI/MSI-X for PCIe native hotplug; it's
known to be buggy on some platforms.

In my environment, while shutting down, following stack trace is shown
sometimes.

  irq 16: nobody cared (try booting with the "irqpoll" option)
  Pid: 1081, comm: reboot Not tainted 3.2.0 #1
  Call Trace:
   <IRQ>  [<ffffffff810cec1d>] __report_bad_irq+0x3d/0xe0
   [<ffffffff810cee1c>] note_interrupt+0x15c/0x210
   [<ffffffff810cc485>] handle_irq_event_percpu+0xb5/0x210
   [<ffffffff810cc621>] handle_irq_event+0x41/0x70
   [<ffffffff810cf675>] handle_fasteoi_irq+0x55/0xc0
   [<ffffffff81015356>] handle_irq+0x46/0xb0
   [<ffffffff814fbe9d>] do_IRQ+0x5d/0xe0
   [<ffffffff814f146e>] common_interrupt+0x6e/0x6e
   [<ffffffff8106b040>] ? __do_softirq+0x60/0x210
   [<ffffffff8108aeb1>] ? hrtimer_interrupt+0x151/0x240
   [<ffffffff814fb5ec>] call_softirq+0x1c/0x30
   [<ffffffff810152d5>] do_softirq+0x65/0xa0
   [<ffffffff8106ae9d>] irq_exit+0xbd/0xe0
   [<ffffffff814fbf8e>] smp_apic_timer_interrupt+0x6e/0x99
   [<ffffffff814f9e5e>] apic_timer_interrupt+0x6e/0x80
   <EOI>  [<ffffffff814f0fb1>] ? _raw_spin_unlock_irqrestore+0x11/0x20
   [<ffffffff812629fc>] pci_bus_write_config_word+0x6c/0x80
   [<ffffffff81266fc2>] pci_intx+0x52/0xa0
   [<ffffffff8127de3d>] pci_intx_for_msi+0x1d/0x30
  [<ffffffff8127e4fb>] pci_msi_shutdown+0x7b/0x110
   [<ffffffff81269d34>] pci_device_shutdown+0x34/0x50
   [<ffffffff81326c4f>] device_shutdown+0x2f/0x140
   [<ffffffff8107b981>] kernel_restart_prepare+0x31/0x40
   [<ffffffff8107b9e6>] kernel_restart+0x16/0x60
   [<ffffffff8107bbfd>] sys_reboot+0x1ad/0x220
   [<ffffffff814f4b90>] ? do_page_fault+0x1e0/0x460
   [<ffffffff811942d0>] ? __sync_filesystem+0x90/0x90
   [<ffffffff8105c9aa>] ? __cond_resched+0x2a/0x40
   [<ffffffff814ef090>] ? _cond_resched+0x30/0x40
   [<ffffffff81169e17>] ? iterate_supers+0xb7/0xd0
   [<ffffffff814f9382>] system_call_fastpath+0x16/0x1b
  handlers:
  [<ffffffff8138a0f0>] usb_hcd_irq
  [<ffffffff8138a0f0>] usb_hcd_irq
  [<ffffffff8138a0f0>] usb_hcd_irq
  Disabling IRQ #16

An un-wanted interrupt is generated when PCI driver switches from
MSI/MSI-X to INTx while shutting down the device.  The interrupt does
not happen if MSI/MSI-X is not used on the device.
I confirmed that this problem does not happen if pcie_hp=nomsi was
specified and hotplug operation worked fine as usual.

v2: Automatically disable MSI/MSI-X against following device:
    PCI bridge: Integrated Device Technology, Inc. Device 807f (rev 02)
v3: Based on the review comment, combile the if statements.
v4: Removed module parameter.
    Move some code to build pciehp as a module.
    Move device specific code to driver/pci/quirks.c.
v5: Drop a device specific code until getting a vendor statement.

Reviewed-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

Showing 3 changed files with 30 additions and 2 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -2118,6 +2118,10 @@
2118 2118 force Enable ASPM even on devices that claim not to support it.
2119 2119 WARNING: Forcing ASPM on may cause system lockups.
2120 2120  
  2121 + pcie_hp= [PCIE] PCI Express Hotplug driver options:
  2122 + nomsi Do not use MSI for PCI Express Native Hotplug (this
  2123 + makes all PCIe ports use INTx for hotplug services).
  2124 +
2121 2125 pcie_ports= [PCIE] PCIe ports handling:
2122 2126 auto Ask the BIOS whether or not to use native PCIe services
2123 2127 associated with PCIe ports (PME, hot-plug, AER). Use
drivers/pci/pcie/portdrv.h
... ... @@ -34,6 +34,18 @@
34 34  
35 35 extern void pcie_clear_root_pme_status(struct pci_dev *dev);
36 36  
  37 +#ifdef CONFIG_HOTPLUG_PCI_PCIE
  38 +extern bool pciehp_msi_disabled;
  39 +
  40 +static inline bool pciehp_no_msi(void)
  41 +{
  42 + return pciehp_msi_disabled;
  43 +}
  44 +
  45 +#else /* !CONFIG_HOTPLUG_PCI_PCIE */
  46 +static inline bool pciehp_no_msi(void) { return false; }
  47 +#endif /* !CONFIG_HOTPLUG_PCI_PCIE */
  48 +
37 49 #ifdef CONFIG_PCIE_PME
38 50 extern bool pcie_pme_msi_disabled;
39 51  
drivers/pci/pcie/portdrv_core.c
... ... @@ -19,6 +19,17 @@
19 19 #include "../pci.h"
20 20 #include "portdrv.h"
21 21  
  22 +bool pciehp_msi_disabled;
  23 +
  24 +static int __init pciehp_setup(char *str)
  25 +{
  26 + if (!strncmp(str, "nomsi", 5))
  27 + pciehp_msi_disabled = true;
  28 +
  29 + return 1;
  30 +}
  31 +__setup("pcie_hp=", pciehp_setup);
  32 +
22 33 /**
23 34 * release_pcie_device - free PCI Express port service device structure
24 35 * @dev: Port service device to release
... ... @@ -189,8 +200,9 @@
189 200 {
190 201 int i, irq = -1;
191 202  
192   - /* We have to use INTx if MSI cannot be used for PCIe PME. */
193   - if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) {
  203 + /* We have to use INTx if MSI cannot be used for PCIe PME or pciehp. */
  204 + if (((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) ||
  205 + ((mask & PCIE_PORT_SERVICE_HP) && pciehp_no_msi())) {
194 206 if (dev->pin)
195 207 irq = dev->irq;
196 208 goto no_msi;