Commit 67f4660b authored by Dely Sy's avatar Dely Sy Committed by Greg Kroah-Hartman

[PATCH] PCI: ASPM patch for

This is the ASPM patch against 2.6.10-rc1-mm2.

As mentioned in my last email, this patch has a slight difference than
the one for 2.6.10-rc1,  because the irqbalance quirk was moved from
drivers/pci/quirks.c in 2.6.10-rc1 to arch/i386/kernel/quirks.c in
2.6.10-rc1-mm2.
Signed-off-by: default avatarDely Sy <dely.l.sy@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent eb7a87e8
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP)
void __init quirk_intel_irqbalance(struct pci_dev *dev) void __devinit quirk_intel_irqbalance(struct pci_dev *dev)
{ {
u8 config, rev; u8 config, rev;
u32 word; u32 word;
...@@ -45,5 +45,5 @@ void __init quirk_intel_irqbalance(struct pci_dev *dev) ...@@ -45,5 +45,5 @@ void __init quirk_intel_irqbalance(struct pci_dev *dev)
} }
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance);
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_intel_irqbalance); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance);
#endif #endif
...@@ -255,3 +255,94 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev) ...@@ -255,3 +255,94 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2, pci_fixup_nforce2);
/* Max PCI Express root ports */
#define MAX_PCIEROOT 6
static int quirk_aspm_offset[MAX_PCIEROOT << 3];
#define GET_INDEX(a, b) (((a - PCI_DEVICE_ID_INTEL_MCH_PA) << 3) + b)
static int quirk_pcie_aspm_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
{
return raw_pci_ops->read(0, bus->number, devfn, where, size, value);
}
/*
* Replace the original pci bus ops for write with a new one that will filter
* the request to insure ASPM cannot be enabled.
*/
static int quirk_pcie_aspm_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value)
{
u8 offset;
offset = quirk_aspm_offset[GET_INDEX(bus->self->device, devfn)];
if ((offset) && (where == offset))
value = value & 0xfffffffc;
return raw_pci_ops->write(0, bus->number, devfn, where, size, value);
}
struct pci_ops quirk_pcie_aspm_ops = {
.read = quirk_pcie_aspm_read,
.write = quirk_pcie_aspm_write,
};
/*
* Prevents PCI Express ASPM (Active State Power Management) being enabled.
*
* Save the register offset, where the ASPM control bits are located,
* for each PCI Express device that is in the device list of
* the root port in an array for fast indexing. Replace the bus ops
* with the modified one.
*/
void pcie_rootport_aspm_quirk(struct pci_dev *pdev)
{
int cap_base, i;
struct pci_bus *pbus;
struct pci_dev *dev;
if ((pbus = pdev->subordinate) == NULL)
return;
/*
* Check if the DID of pdev matches one of the six root ports. This
* check is needed in the case this function is called directly by the
* hot-plug driver.
*/
if ((pdev->device < PCI_DEVICE_ID_INTEL_MCH_PA) ||
(pdev->device > PCI_DEVICE_ID_INTEL_MCH_PC1))
return;
if (list_empty(&pbus->devices)) {
/*
* If no device is attached to the root port at power-up or
* after hot-remove, the pbus->devices is empty and this code
* will set the offsets to zero and the bus ops to parent's bus
* ops, which is unmodified.
*/
for (i= GET_INDEX(pdev->device, 0); i <= GET_INDEX(pdev->device, 7); ++i)
quirk_aspm_offset[i] = 0;
pbus->ops = pbus->parent->ops;
} else {
/*
* If devices are attached to the root port at power-up or
* after hot-add, the code loops through the device list of
* each root port to save the register offsets and replace the
* bus ops.
*/
list_for_each_entry(dev, &pbus->devices, bus_list) {
/* There are 0 to 8 devices attached to this bus */
cap_base = pci_find_capability(dev, PCI_CAP_ID_EXP);
quirk_aspm_offset[GET_INDEX(pdev->device, dev->devfn)]= cap_base + 0x10;
}
pbus->ops = &quirk_pcie_aspm_ops;
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA, pcie_rootport_aspm_quirk );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PA1, pcie_rootport_aspm_quirk );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB, pcie_rootport_aspm_quirk );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PB1, pcie_rootport_aspm_quirk );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC, pcie_rootport_aspm_quirk );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MCH_PC1, pcie_rootport_aspm_quirk );
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/pci.h> #include <linux/pci.h>
#include "../pci.h"
#include "pciehp.h" #include "pciehp.h"
#include "pciehprm.h" #include "pciehprm.h"
...@@ -1221,6 +1222,12 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) ...@@ -1221,6 +1222,12 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
} }
} while (new_func); } while (new_func);
/*
* Some PCI Express root ports require fixup after hot-plug operation.
*/
if (pcie_mch_quirk)
pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
if (PWR_LED(ctrl->ctrlcap)) { if (PWR_LED(ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
......
...@@ -741,6 +741,8 @@ static void hpc_release_ctlr(struct controller *ctrl) ...@@ -741,6 +741,8 @@ static void hpc_release_ctlr(struct controller *ctrl)
if (php_ctlr->irq) { if (php_ctlr->irq) {
free_irq(php_ctlr->irq, ctrl); free_irq(php_ctlr->irq, ctrl);
php_ctlr->irq = 0; php_ctlr->irq = 0;
if (!pcie_mch_quirk)
pci_disable_msi(php_ctlr->pci_dev);
} }
} }
if (php_ctlr->pci_dev) if (php_ctlr->pci_dev)
...@@ -1402,8 +1404,8 @@ int pcie_init(struct controller * ctrl, ...@@ -1402,8 +1404,8 @@ int pcie_init(struct controller * ctrl,
start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */ start_int_poll_timer( php_ctlr, 10 ); /* start with 10 second delay */
} else { } else {
/* Installs the interrupt handler */ /* Installs the interrupt handler */
dbg("%s: pciehp_msi_quirk = %x\n", __FUNCTION__, pciehp_msi_quirk); dbg("%s: pcie_mch_quirk = %x\n", __FUNCTION__, pcie_mch_quirk);
if (!pciehp_msi_quirk) { if (!pcie_mch_quirk) {
rc = pci_enable_msi(pdev); rc = pci_enable_msi(pdev);
if (rc) { if (rc) {
info("Can't get msi for the hotplug controller\n"); info("Can't get msi for the hotplug controller\n");
......
...@@ -82,9 +82,11 @@ int pciehp_unconfigure_device(struct pci_func* func) ...@@ -82,9 +82,11 @@ int pciehp_unconfigure_device(struct pci_func* func)
{ {
int rc = 0; int rc = 0;
int j; int j;
struct pci_bus *pbus;
dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus, dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
func->device, func->function); func->device, func->function);
pbus = func->pci_dev->bus;
for (j=0; j<8 ; j++) { for (j=0; j<8 ; j++) {
struct pci_dev* temp = pci_find_slot(func->bus, struct pci_dev* temp = pci_find_slot(func->bus,
...@@ -93,6 +95,12 @@ int pciehp_unconfigure_device(struct pci_func* func) ...@@ -93,6 +95,12 @@ int pciehp_unconfigure_device(struct pci_func* func)
pci_remove_bus_device(temp); pci_remove_bus_device(temp);
} }
} }
/*
* Some PCI Express root ports require fixup after hot-plug operation.
*/
if (pcie_mch_quirk)
pci_fixup_device(pci_fixup_final, pbus->self);
return rc; return rc;
} }
......
...@@ -792,6 +792,7 @@ static void hpc_release_ctlr(struct controller *ctrl) ...@@ -792,6 +792,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
if (php_ctlr->irq) { if (php_ctlr->irq) {
free_irq(php_ctlr->irq, ctrl); free_irq(php_ctlr->irq, ctrl);
php_ctlr->irq = 0; php_ctlr->irq = 0;
pci_disable_msi(php_ctlr->pci_dev);
} }
} }
if (php_ctlr->pci_dev) { if (php_ctlr->pci_dev) {
......
...@@ -61,7 +61,7 @@ extern int pci_visit_dev(struct pci_visit *fn, ...@@ -61,7 +61,7 @@ extern int pci_visit_dev(struct pci_visit *fn,
/* Lock for read/write access to pci device and bus lists */ /* Lock for read/write access to pci device and bus lists */
extern spinlock_t pci_bus_lock; extern spinlock_t pci_bus_lock;
extern int pciehp_msi_quirk; extern int pcie_mch_quirk;
extern struct device_attribute pci_dev_attrs[]; extern struct device_attribute pci_dev_attrs[];
/** /**
......
...@@ -1135,7 +1135,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_a ...@@ -1135,7 +1135,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_a
#endif #endif
#ifdef CONFIG_SCSI_SATA #ifdef CONFIG_SCSI_SATA
static void __init quirk_intel_ide_combined(struct pci_dev *pdev) static void __devinit quirk_intel_ide_combined(struct pci_dev *pdev)
{ {
u8 prog, comb, tmp; u8 prog, comb, tmp;
int ich = 0; int ich = 0;
...@@ -1209,14 +1209,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co ...@@ -1209,14 +1209,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co
#endif /* CONFIG_SCSI_SATA */ #endif /* CONFIG_SCSI_SATA */
int pciehp_msi_quirk; int pcie_mch_quirk;
static void __devinit quirk_pciehp_msi(struct pci_dev *pdev) static void __devinit quirk_pcie_mch(struct pci_dev *pdev)
{ {
pciehp_msi_quirk = 1; pcie_mch_quirk = 1;
} }
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SMCH, quirk_pciehp_msi ); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_pcie_mch );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_pcie_mch );
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_pcie_mch );
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
{ {
...@@ -1265,4 +1266,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) ...@@ -1265,4 +1266,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev)
pci_do_fixups(dev, start, end); pci_do_fixups(dev, start, end);
} }
EXPORT_SYMBOL(pciehp_msi_quirk); EXPORT_SYMBOL(pcie_mch_quirk);
#ifdef CONFIG_HOTPLUG
EXPORT_SYMBOL(pci_fixup_device);
#endif
...@@ -2206,8 +2206,14 @@ ...@@ -2206,8 +2206,14 @@
#define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577 #define PCI_DEVICE_ID_INTEL_82830_CGC 0x3577
#define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580 #define PCI_DEVICE_ID_INTEL_82855GM_HB 0x3580
#define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582 #define PCI_DEVICE_ID_INTEL_82855GM_IG 0x3582
#define PCI_DEVICE_ID_INTEL_SMCH 0x3590 #define PCI_DEVICE_ID_INTEL_E7520_MCH 0x3590
#define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592 #define PCI_DEVICE_ID_INTEL_E7320_MCH 0x3592
#define PCI_DEVICE_ID_INTEL_MCH_PA 0x3595
#define PCI_DEVICE_ID_INTEL_MCH_PA1 0x3596
#define PCI_DEVICE_ID_INTEL_MCH_PB 0x3597
#define PCI_DEVICE_ID_INTEL_MCH_PB1 0x3598
#define PCI_DEVICE_ID_INTEL_MCH_PC 0x3599
#define PCI_DEVICE_ID_INTEL_MCH_PC1 0x359a
#define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e #define PCI_DEVICE_ID_INTEL_E7525_MCH 0x359e
#define PCI_DEVICE_ID_INTEL_80310 0x530d #define PCI_DEVICE_ID_INTEL_80310 0x530d
#define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment