PCI: PCIe: Disable PCIe port services during port initialization
authorRafael J. Wysocki <rjw@sisk.pl>
Fri, 20 Aug 2010 23:57:39 +0000 (01:57 +0200)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Tue, 24 Aug 2010 20:47:47 +0000 (13:47 -0700)
In principle PCIe port services may be enabled by the BIOS, so it's
better to disable them during port initialization to avoid spurious
events from being generated.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reviewed-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/pci/pcie/portdrv_core.c

index d0245c8..a9c222d 100644 (file)
@@ -259,20 +259,43 @@ static int get_port_device_capability(struct pci_dev *dev)
        /* Hot-Plug Capable */
        if ((cap_mask & PCIE_PORT_SERVICE_HP) && (reg16 & PCI_EXP_FLAGS_SLOT)) {
                pci_read_config_dword(dev, pos + PCI_EXP_SLTCAP, &reg32);
-               if (reg32 & PCI_EXP_SLTCAP_HPC)
+               if (reg32 & PCI_EXP_SLTCAP_HPC) {
                        services |= PCIE_PORT_SERVICE_HP;
+                       /*
+                        * Disable hot-plug interrupts in case they have been
+                        * enabled by the BIOS and the hot-plug service driver
+                        * is not loaded.
+                        */
+                       pos += PCI_EXP_SLTCTL;
+                       pci_read_config_word(dev, pos, &reg16);
+                       reg16 &= ~(PCI_EXP_SLTCTL_CCIE | PCI_EXP_SLTCTL_HPIE);
+                       pci_write_config_word(dev, pos, reg16);
+               }
        }
        /* AER capable */
        if ((cap_mask & PCIE_PORT_SERVICE_AER)
-           && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR))
+           && pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR)) {
                services |= PCIE_PORT_SERVICE_AER;
+               /*
+                * Disable AER on this port in case it's been enabled by the
+                * BIOS (the AER service driver will enable it when necessary).
+                */
+               pci_disable_pcie_error_reporting(dev);
+       }
        /* VC support */
        if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_VC))
                services |= PCIE_PORT_SERVICE_VC;
        /* Root ports are capable of generating PME too */
        if ((cap_mask & PCIE_PORT_SERVICE_PME)
-           && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT)
+           && dev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
                services |= PCIE_PORT_SERVICE_PME;
+               /*
+                * Disable PME interrupt on this port in case it's been enabled
+                * by the BIOS (the PME service driver will enable it when
+                * necessary).
+                */
+               pcie_pme_interrupt_enable(dev, false);
+       }
 
        return services;
 }