Commit 3c80c502 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

merge

parents 5c79e500 435883d2
...@@ -931,6 +931,10 @@ running once the system is up. ...@@ -931,6 +931,10 @@ running once the system is up.
enabled. enabled.
noacpi [IA-32] Do not use ACPI for IRQ routing noacpi [IA-32] Do not use ACPI for IRQ routing
or for PCI scanning. or for PCI scanning.
routeirq Do IRQ routing for all PCI devices.
This is normally done in pci_enable_device(),
so this option is a temporary workaround
for broken drivers that don't call it.
firmware [ARM] Do not re-enumerate the bus but firmware [ARM] Do not re-enumerate the bus but
instead just use the configuration instead just use the configuration
......
...@@ -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
...@@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do ...@@ -15,6 +15,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do
return pcibios_scan_root(busnum); return pcibios_scan_root(busnum);
} }
extern int pci_routeirq;
static int __init pci_acpi_init(void) static int __init pci_acpi_init(void)
{ {
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
...@@ -30,14 +31,27 @@ static int __init pci_acpi_init(void) ...@@ -30,14 +31,27 @@ static int __init pci_acpi_init(void)
pcibios_scanned++; pcibios_scanned++;
pcibios_enable_irq = acpi_pci_irq_enable; pcibios_enable_irq = acpi_pci_irq_enable;
/* if (pci_routeirq) {
* PCI IRQ routing is set up by pci_enable_device(), but we /*
* also do it here in case there are still broken drivers that * PCI IRQ routing is set up by pci_enable_device(), but we
* don't use pci_enable_device(). * also do it here in case there are still broken drivers that
*/ * don't use pci_enable_device().
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) */
acpi_pci_irq_enable(dev); printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
printk(KERN_INFO "** was specified. If this was required to make a driver work,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
acpi_pci_irq_enable(dev);
} else {
printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n");
printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n");
printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
printk(KERN_INFO "** behavior. If this argument makes the device work again,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
}
#ifdef CONFIG_X86_IO_APIC #ifdef CONFIG_X86_IO_APIC
if (acpi_ioapic) if (acpi_ioapic)
print_IO_APIC(); print_IO_APIC();
......
/*
* CHANGELOG :
* Jun 17, 1994 : Modified to accommodate the broken pre-PCI BIOS SPECIFICATION
* Revision 2.0 present on <thys@dennis.ee.up.ac.za>'s ASUS mainboard.
*
* Jan 5, 1995 : Modified to probe PCI hardware at boot time by Frederic
* Potter, potter@cao-vlsi.ibp.fr
*
* Jan 10, 1995 : Modified to store the information about configured pci
* devices into a list, which can be accessed via /proc/pci by
* Curtis Varner, cvarner@cs.ucr.edu
*
* Jan 12, 1995 : CPU-PCI bridge optimization support by Frederic Potter.
* Alpha version. Intel & UMC chipset support only.
*
* Apr 16, 1995 : Source merge with the DEC Alpha PCI support. Most of the code
* moved to drivers/pci/pci.c.
*
* Dec 7, 1996 : Added support for direct configuration access of boards
* with Intel compatible access schemes (tsbogend@alpha.franken.de)
*
* Feb 3, 1997 : Set internal functions to static, save/restore flags
* avoid dead locks reading broken PCI BIOS, werner@suse.de
*
* Apr 26, 1997 : Fixed case when there is BIOS32, but not PCI BIOS
* (mj@atrey.karlin.mff.cuni.cz)
*
* May 7, 1997 : Added some missing cli()'s. [mj]
*
* Jun 20, 1997 : Corrected problems in "conf1" type accesses.
* (paubert@iram.es)
*
* Aug 2, 1997 : Split to PCI BIOS handling and direct PCI access parts
* and cleaned it up... Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*
* Feb 6, 1998 : No longer using BIOS to find devices and device classes. [mj]
*
* May 1, 1998 : Support for peer host bridges. [mj]
*
* Jun 19, 1998 : Changed to use spinlocks, so that PCI configuration space
* can be accessed from interrupts even on SMP systems. [mj]
*
* August 1998 : Better support for peer host bridges and more paranoid
* checks for direct hardware access. Ugh, this file starts to look as
* a large gallery of common hardware bug workarounds (watch the comments)
* -- the PCI specs themselves are sane, but most implementors should be
* hit hard with \hammer scaled \magstep5. [mj]
*
* Jan 23, 1999 : More improvements to peer host bridge logic. i450NX fixup. [mj]
*
* Feb 8, 1999 : Added UM8886BF I/O address fixup. [mj]
*
* August 1999 : New resource management and configuration access stuff. [mj]
*
* Sep 19, 1999 : Use PCI IRQ routing tables for detection of peer host bridges.
* Based on ideas by Chris Frantz and David Hinds. [mj]
*
* Sep 28, 1999 : Handle unreported/unassigned IRQs. Thanks to Shuu Yamaguchi
* for a lot of patience during testing. [mj]
*
* Oct 8, 1999 : Split to pci-i386.c, pci-pc.c and pci-visws.c. [mj]
*/
\ No newline at end of file
...@@ -23,6 +23,7 @@ extern void pcibios_sort(void); ...@@ -23,6 +23,7 @@ extern void pcibios_sort(void);
unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 | unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |
PCI_PROBE_MMCONF; PCI_PROBE_MMCONF;
int pci_routeirq;
int pcibios_last_bus = -1; int pcibios_last_bus = -1;
struct pci_bus *pci_root_bus = NULL; struct pci_bus *pci_root_bus = NULL;
struct pci_raw_ops *raw_pci_ops; struct pci_raw_ops *raw_pci_ops;
...@@ -227,6 +228,9 @@ char * __devinit pcibios_setup(char *str) ...@@ -227,6 +228,9 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "assign-busses")) { } else if (!strcmp(str, "assign-busses")) {
pci_probe |= PCI_ASSIGN_ALL_BUSSES; pci_probe |= PCI_ASSIGN_ALL_BUSSES;
return NULL; return NULL;
} else if (!strcmp(str, "routeirq")) {
pci_routeirq = 1;
return NULL;
} }
return str; return str;
} }
......
...@@ -255,3 +255,132 @@ static void __init pci_fixup_nforce2(struct pci_dev *dev) ...@@ -255,3 +255,132 @@ 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 );
/*
* Fixup to mark boot BIOS video selected by BIOS before it changes
*
* From information provided by "Jon Smirl" <jonsmirl@yahoo.com>
*
* The standard boot ROM sequence for an x86 machine uses the BIOS
* to select an initial video card for boot display. This boot video
* card will have it's BIOS copied to C0000 in system RAM.
* IORESOURCE_ROM_SHADOW is used to associate the boot video
* card with this copy. On laptops this copy has to be used since
* the main ROM may be compressed or combined with another image.
* See pci_map_rom() for use of this flag. IORESOURCE_ROM_SHADOW
* is marked here since the boot video device will be the only enabled
* video device at this point.
*
*/static void __devinit pci_fixup_video(struct pci_dev *pdev)
{
struct pci_dev *bridge;
struct pci_bus *bus;
u16 l;
if ((pdev->class >> 8) != PCI_CLASS_DISPLAY_VGA)
return;
/* Is VGA routed to us? */
bus = pdev->bus;
while (bus) {
bridge = bus->self;
if (bridge) {
pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &l);
if (!(l & PCI_BRIDGE_CTL_VGA))
return;
}
bus = bus->parent;
}
pdev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_SHADOW;
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);
...@@ -460,21 +460,17 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, ...@@ -460,21 +460,17 @@ static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq,
#endif #endif
static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device) static __init int intel_router_probe(struct irq_router *r, struct pci_dev *router, u16 device)
{ {
struct pci_dev *dev1, *dev2; static struct pci_device_id pirq_440gx[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) },
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) },
{ },
};
/* 440GX has a proprietary PIRQ router -- don't use it */ /* 440GX has a proprietary PIRQ router -- don't use it */
dev1 = pci_get_device(PCI_VENDOR_ID_INTEL, if (pci_dev_present(pirq_440gx))
PCI_DEVICE_ID_INTEL_82443GX_0, NULL);
dev2 = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82443GX_2, NULL);
if ((dev1 != NULL) || (dev2 != NULL)) {
pci_dev_put(dev1);
pci_dev_put(dev2);
return 0; return 0;
}
switch(device) switch(device)
{ {
......
...@@ -30,7 +30,7 @@ static inline void pci_exp_set_dev_base(int bus, int devfn) ...@@ -30,7 +30,7 @@ static inline void pci_exp_set_dev_base(int bus, int devfn)
u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12); u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
if (dev_base != mmcfg_last_accessed_device) { if (dev_base != mmcfg_last_accessed_device) {
mmcfg_last_accessed_device = dev_base; mmcfg_last_accessed_device = dev_base;
set_fixmap(FIX_PCIE_MCFG, dev_base); set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
} }
} }
...@@ -85,9 +85,6 @@ static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 va ...@@ -85,9 +85,6 @@ static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 va
break; break;
} }
/* Dummy read to flush PCI write */
readl(mmcfg_virt_addr);
spin_unlock_irqrestore(&pci_config_lock, flags); spin_unlock_irqrestore(&pci_config_lock, flags);
return 0; return 0;
......
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#define DBG(x...) #define DBG(x...)
#endif #endif
static int pci_routeirq;
/* /*
* Low-level SAL-based PCI configuration access functions. Note that SAL * Low-level SAL-based PCI configuration access functions. Note that SAL
* calls are already serialized (via sal_lock), so we don't need another * calls are already serialized (via sal_lock), so we don't need another
...@@ -141,13 +143,28 @@ extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**); ...@@ -141,13 +143,28 @@ extern acpi_status acpi_map_iosapic (acpi_handle, u32, void*, void**);
acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL); acpi_get_devices(NULL, acpi_map_iosapic, NULL, NULL);
#endif #endif
/*
* PCI IRQ routing is set up by pci_enable_device(), but we if (pci_routeirq) {
* also do it here in case there are still broken drivers that /*
* don't use pci_enable_device(). * PCI IRQ routing is set up by pci_enable_device(), but we
*/ * also do it here in case there are still broken drivers that
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) * don't use pci_enable_device().
acpi_pci_irq_enable(dev); */
printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
printk(KERN_INFO "** was specified. If this was required to make a driver work,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
acpi_pci_irq_enable(dev);
} else {
printk(KERN_INFO "** PCI interrupts are no longer routed automatically. If this\n");
printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
printk(KERN_INFO "** driver failed to call pci_enable_device(). As a temporary\n");
printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
printk(KERN_INFO "** behavior. If this argument makes the device work again,\n");
printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
printk(KERN_INFO "** so I can fix the driver.\n");
}
return 0; return 0;
} }
...@@ -475,6 +492,8 @@ pcibios_align_resource (void *data, struct resource *res, ...@@ -475,6 +492,8 @@ pcibios_align_resource (void *data, struct resource *res,
char * __init char * __init
pcibios_setup (char *str) pcibios_setup (char *str)
{ {
if (!strcmp(str, "routeirq"))
pci_routeirq = 1;
return NULL; return NULL;
} }
......
...@@ -63,9 +63,6 @@ static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 va ...@@ -63,9 +63,6 @@ static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 va
break; break;
} }
/* Dummy read to flush PCI write */
readl(addr);
return 0; return 0;
} }
......
...@@ -3685,9 +3685,9 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id) ...@@ -3685,9 +3685,9 @@ idt77252_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
int i, err; int i, err;
if (pci_enable_device(pcidev)) { if ((err = pci_enable_device(pcidev))) {
printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev)); printk("idt77252: can't enable PCI device at %s\n", pci_name(pcidev));
return -ENODEV; return err;
} }
if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) { if (pci_read_config_word(pcidev, PCI_REVISION_ID, &revision)) {
......
...@@ -4725,7 +4725,7 @@ cy_detect_pci(void) ...@@ -4725,7 +4725,7 @@ cy_detect_pci(void)
for (i = 0; i < NR_CARDS; i++) { for (i = 0; i < NR_CARDS; i++) {
/* look for a Cyclades card by vendor and device id */ /* look for a Cyclades card by vendor and device id */
while((device_id = cy_pci_dev_id[dev_index]) != 0) { while((device_id = cy_pci_dev_id[dev_index]) != 0) {
if((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES, if((pdev = pci_get_device(PCI_VENDOR_ID_CYCLADES,
device_id, pdev)) == NULL) { device_id, pdev)) == NULL) {
dev_index++; /* try next device id */ dev_index++; /* try next device id */
} else { } else {
......
...@@ -217,6 +217,11 @@ static struct miscdevice scx200_wdt_miscdev = { ...@@ -217,6 +217,11 @@ static struct miscdevice scx200_wdt_miscdev = {
static int __init scx200_wdt_init(void) static int __init scx200_wdt_init(void)
{ {
int r; int r;
static struct pci_device_id ns_sc[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
{ },
};
printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n"); printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
...@@ -224,12 +229,7 @@ static int __init scx200_wdt_init(void) ...@@ -224,12 +229,7 @@ static int __init scx200_wdt_init(void)
* First check that this really is a NatSemi SCx200 CPU or a Geode * First check that this really is a NatSemi SCx200 CPU or a Geode
* SC1100 processor * SC1100 processor
*/ */
if ((pci_find_device(PCI_VENDOR_ID_NS, if (!pci_dev_present(ns_sc))
PCI_DEVICE_ID_NS_SCx200_BRIDGE,
NULL)) == NULL
&& (pci_find_device(PCI_VENDOR_ID_NS,
PCI_DEVICE_ID_NS_SC1100_BRIDGE,
NULL)) == NULL)
return -ENODEV; return -ENODEV;
/* More sanity checks, verify that the configuration block is there */ /* More sanity checks, verify that the configuration block is there */
......
...@@ -335,11 +335,16 @@ static void __init init_ide_data (void) ...@@ -335,11 +335,16 @@ static void __init init_ide_data (void)
int ide_system_bus_speed (void) int ide_system_bus_speed (void)
{ {
static struct pci_device_id pci_default[] = {
{ PCI_DEVICE(PCI_ANY_ID, PCI_ANY_ID) },
{ }
};
if (!system_bus_speed) { if (!system_bus_speed) {
if (idebus_parameter) { if (idebus_parameter) {
/* user supplied value */ /* user supplied value */
system_bus_speed = idebus_parameter; system_bus_speed = idebus_parameter;
} else if (pci_find_device(PCI_ANY_ID, PCI_ANY_ID, NULL) != NULL) { } else if (pci_dev_present(pci_default)) {
/* safe default value for PCI */ /* safe default value for PCI */
system_bus_speed = 33; system_bus_speed = 33;
} else { } else {
......
...@@ -88,10 +88,10 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id ...@@ -88,10 +88,10 @@ static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id
tpam_card *card, *c; tpam_card *card, *c;
int i, err; int i, err;
if (pci_enable_device(dev)) { if ((err = pci_enable_device(dev))) {
printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n", printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n",
pci_name(dev)); pci_name(dev));
return -ENODEV; return err;
} }
/* allocate memory for the board structure */ /* allocate memory for the board structure */
......
...@@ -145,14 +145,11 @@ static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = { ...@@ -145,14 +145,11 @@ static struct { const char name[8]; uint mode; uint bpp; } palette2fmt[] = {
static static
void __init handle_chipset(void) void __init handle_chipset(void)
{ {
struct pci_dev *dev = NULL;
/* Just in case some nut set this to something dangerous */ /* Just in case some nut set this to something dangerous */
if (triton1) if (triton1)
triton1 = ZORAN_VDC_TRICOM; triton1 = ZORAN_VDC_TRICOM;
while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, dev))) if (pci_pci_problems & PCIPCI_TRITON) {
{
printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n"); printk(KERN_INFO "zoran: Host bridge 82437FX Triton PIIX\n");
triton1 = ZORAN_VDC_TRICOM; triton1 = ZORAN_VDC_TRICOM;
} }
......
...@@ -59,13 +59,13 @@ ...@@ -59,13 +59,13 @@
static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static int __init ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
int result = -ENOMEM; int err, result = -ENOMEM;
struct service_processor *sp; struct service_processor *sp;
if (pci_enable_device(pdev)) { if ((err = pci_enable_device(pdev))) {
printk(KERN_ERR "%s: can't enable PCI device at %s\n", printk(KERN_ERR "%s: can't enable PCI device at %s\n",
DRIVER_NAME, pci_name(pdev)); DRIVER_NAME, pci_name(pdev));
return -ENODEV; return err;
} }
sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL); sp = kmalloc(sizeof(struct service_processor), GFP_KERNEL);
......
...@@ -2242,8 +2242,8 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev, ...@@ -2242,8 +2242,8 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
return -ENODEV; return -ENODEV;
/* Ok, the device seems to be for us. */ /* Ok, the device seems to be for us. */
if (pci_enable_device (pdev)) if ((error = pci_enable_device (pdev)))
return -ENODEV; return error;
if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) { if (!(dev = alloc_etherdev (sizeof (struct de4x5_private)))) {
error = -ENOMEM; error = -ENOMEM;
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
# #
obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \ obj-y += access.o bus.o probe.o remove.o pci.o quirks.o \
names.o pci-driver.o search.o pci-sysfs.o names.o pci-driver.o search.o pci-sysfs.o \
rom.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
ifndef CONFIG_SPARC64 ifndef CONFIG_SPARC64
...@@ -28,6 +29,11 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o ...@@ -28,6 +29,11 @@ obj-$(CONFIG_MIPS) += setup-bus.o setup-irq.o
obj-$(CONFIG_X86_VISWS) += setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o
obj-$(CONFIG_PCI_MSI) += msi.o obj-$(CONFIG_PCI_MSI) += msi.o
#
# ACPI Related PCI FW Functions
#
obj-$(CONFIG_ACPI) += pci-acpi.o
# Cardbus & CompactPCI use setup-bus # Cardbus & CompactPCI use setup-bus
obj-$(CONFIG_HOTPLUG) += setup-bus.o obj-$(CONFIG_HOTPLUG) += setup-bus.o
......
...@@ -389,7 +389,7 @@ static void add_host_bridge(acpi_handle *handle, int seg, int bus) ...@@ -389,7 +389,7 @@ static void add_host_bridge(acpi_handle *handle, int seg, int bus)
bridge->pci_bus = pci_find_bus(seg, bus); bridge->pci_bus = pci_find_bus(seg, bus);
bridge->res_lock = SPIN_LOCK_UNLOCKED; spin_lock_init(&bridge->res_lock);
/* to be overridden when we decode _CRS */ /* to be overridden when we decode _CRS */
bridge->sub = bridge->bus; bridge->sub = bridge->bus;
...@@ -457,7 +457,7 @@ static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int f ...@@ -457,7 +457,7 @@ static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int f
return; return;
} }
bridge->res_lock = SPIN_LOCK_UNLOCKED; spin_lock_init(&bridge->res_lock);
bridge->bus = bridge->pci_bus->number; bridge->bus = bridge->pci_bus->number;
bridge->sub = bridge->pci_bus->subordinate; bridge->sub = bridge->pci_bus->subordinate;
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
/* local variables */ /* local variables */
static int debug; static int debug;
static char* bridge; static char bridge[256];
static u8 bridge_busnr; static u8 bridge_busnr;
static u8 bridge_slot; static u8 bridge_slot;
static struct pci_bus *bus; static struct pci_bus *bus;
...@@ -209,7 +209,7 @@ module_exit(cpcihp_generic_exit); ...@@ -209,7 +209,7 @@ module_exit(cpcihp_generic_exit);
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(debug, bool, 0644); module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
module_param(bridge, charp, 0); module_param(bridge, charp, 0);
MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)"); MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)");
......
...@@ -227,6 +227,6 @@ module_exit(dummyphp_exit); ...@@ -227,6 +227,6 @@ module_exit(dummyphp_exit);
MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(debug, bool, 0644); module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
int ibmphp_debug; int ibmphp_debug;
static int debug; static int debug;
module_param(debug, bool, 0644); module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC (debug, "Debugging mode enabled or not"); MODULE_PARM_DESC (debug, "Debugging mode enabled or not");
MODULE_LICENSE ("GPL"); MODULE_LICENSE ("GPL");
MODULE_DESCRIPTION (DRIVER_DESC); MODULE_DESCRIPTION (DRIVER_DESC);
...@@ -838,8 +838,11 @@ static int set_bus (struct slot * slot_cur) ...@@ -838,8 +838,11 @@ static int set_bus (struct slot * slot_cur)
int rc; int rc;
u8 speed; u8 speed;
u8 cmd = 0x0; u8 cmd = 0x0;
struct pci_dev *dev = NULL;
int retval; int retval;
static struct pci_device_id ciobx[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, 0x0101) },
{ },
};
debug ("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number); debug ("%s - entry slot # %d\n", __FUNCTION__, slot_cur->number);
if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) { if (SET_BUS_STATUS (slot_cur->ctrl) && is_bus_empty (slot_cur)) {
...@@ -886,8 +889,7 @@ static int set_bus (struct slot * slot_cur) ...@@ -886,8 +889,7 @@ static int set_bus (struct slot * slot_cur)
break; break;
case BUS_SPEED_133: case BUS_SPEED_133:
/* This is to take care of the bug in CIOBX chip */ /* This is to take care of the bug in CIOBX chip */
while ((dev = pci_get_device(PCI_VENDOR_ID_SERVERWORKS, if (pci_dev_present(ciobx))
0x0101, dev)) != NULL)
ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE); ibmphp_hpc_writeslot (slot_cur, HPC_BUS_100PCIXMODE);
cmd = HPC_BUS_133PCIXMODE; cmd = HPC_BUS_133PCIXMODE;
break; break;
......
...@@ -127,8 +127,7 @@ struct controller { ...@@ -127,8 +127,7 @@ struct controller {
enum pci_bus_speed speed; enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */ u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
u8 slot_bus; /* Bus where the slots handled by this controller sit */ u8 slot_bus; /* Bus where the slots handled by this controller sit */
u8 push_flag; u8 ctrlcap;
u16 ctlrcap;
u16 vendor_id; u16 vendor_id;
}; };
...@@ -180,6 +179,21 @@ struct resource_lists { ...@@ -180,6 +179,21 @@ struct resource_lists {
#define DISABLE_CARD 1 #define DISABLE_CARD 1
/* Field definitions in Slot Capabilities Register */
#define ATTN_BUTTN_PRSN 0x00000001
#define PWR_CTRL_PRSN 0x00000002
#define MRL_SENS_PRSN 0x00000004
#define ATTN_LED_PRSN 0x00000008
#define PWR_LED_PRSN 0x00000010
#define HP_SUPR_RM_SUP 0x00000020
#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN)
#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN)
#define MRL_SENS(cap) (cap & MRL_SENS_PRSN)
#define ATTN_LED(cap) (cap & ATTN_LED_PRSN)
#define PWR_LED(cap) (cap & PWR_LED_PRSN)
#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP)
/* /*
* error Messages * error Messages
*/ */
...@@ -312,8 +326,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, ...@@ -312,8 +326,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
int *num_ctlr_slots, int *num_ctlr_slots,
int *first_device_num, int *first_device_num,
int *physical_slot_num, int *physical_slot_num,
int *updown, u8 *ctrlcap);
int *flags);
struct hpc_ops { struct hpc_ops {
int (*power_on_slot) (struct slot *slot); int (*power_on_slot) (struct slot *slot);
......
...@@ -204,11 +204,10 @@ static int get_ctlr_slot_config(struct controller *ctrl) ...@@ -204,11 +204,10 @@ static int get_ctlr_slot_config(struct controller *ctrl)
int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/ int num_ctlr_slots; /* Not needed; PCI Express has 1 slot per port*/
int first_device_num; /* Not needed */ int first_device_num; /* Not needed */
int physical_slot_num; int physical_slot_num;
int updown; /* Not needed */ u8 ctrlcap;
int rc; int rc;
int flags; /* Not needed */
rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); rc = pcie_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &ctrlcap);
if (rc) { if (rc) {
err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device);
return (-1); return (-1);
...@@ -217,10 +216,10 @@ static int get_ctlr_slot_config(struct controller *ctrl) ...@@ -217,10 +216,10 @@ static int get_ctlr_slot_config(struct controller *ctrl)
ctrl->num_slots = num_ctlr_slots; /* PCI Express has 1 slot per port */ ctrl->num_slots = num_ctlr_slots; /* PCI Express has 1 slot per port */
ctrl->slot_device_offset = first_device_num; ctrl->slot_device_offset = first_device_num;
ctrl->first_slot = physical_slot_num; ctrl->first_slot = physical_slot_num;
ctrl->slot_num_inc = updown; /* Not needed */ /* either -1 or 1 */ ctrl->ctrlcap = ctrlcap;
dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", dbg("%s: bus(0x%x) num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) ctrlcap(%x) for b:d (%x:%x)\n",
__FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, updown, __FUNCTION__, ctrl->slot_bus, num_ctlr_slots, first_device_num, physical_slot_num, ctrlcap,
ctrl->bus, ctrl->device); ctrl->bus, ctrl->device);
return (0); return (0);
...@@ -237,7 +236,9 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status) ...@@ -237,7 +236,9 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name);
hotplug_slot->info->attention_status = status; hotplug_slot->info->attention_status = status;
slot->hpc_ops->set_attention_status(slot, status);
if (ATTN_LED(slot->ctrl->ctrlcap))
slot->hpc_ops->set_attention_status(slot, status);
return 0; return 0;
} }
...@@ -451,7 +452,8 @@ static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -451,7 +452,8 @@ static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
dbg("%s: adpater value %x\n", __FUNCTION__, value); dbg("%s: adpater value %x\n", __FUNCTION__, value);
if (!value) {
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
if (rc) { if (rc) {
/* Done with exclusive hardware access */ /* Done with exclusive hardware access */
......
...@@ -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"
...@@ -51,6 +52,7 @@ static struct semaphore event_semaphore; /* mutex for process loop (up if someth ...@@ -51,6 +52,7 @@ static struct semaphore event_semaphore; /* mutex for process loop (up if someth
static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */ static struct semaphore event_exit; /* guard ensure thread has exited before calling it quits */
static int event_finished; static int event_finished;
static unsigned long pushbutton_pending; /* = 0 */ static unsigned long pushbutton_pending; /* = 0 */
static unsigned long surprise_rm_pending; /* = 0 */
u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id) u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
{ {
...@@ -1063,25 +1065,29 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot) ...@@ -1063,25 +1065,29 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
/* turn off slot, turn on Amber LED, turn off Green LED */ /* turn off slot, turn on Amber LED, turn off Green LED if supported*/
if (pslot->hpc_ops->power_off_slot(pslot)) { if (POWER_CTRL(ctrl->ctrlcap)) {
err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__); if (pslot->hpc_ops->power_off_slot(pslot)) {
up(&ctrl->crit_sect); err("%s: Issue of Slot Power Off command failed\n", __FUNCTION__);
return; up(&ctrl->crit_sect);
return;
}
wait_for_ctrl_irq (ctrl);
} }
wait_for_ctrl_irq (ctrl);
pslot->hpc_ops->green_led_off(pslot); if (PWR_LED(ctrl->ctrlcap)) {
pslot->hpc_ops->green_led_off(pslot);
wait_for_ctrl_irq (ctrl); wait_for_ctrl_irq (ctrl);
}
/* turn on Amber LED */ if (ATTN_LED(ctrl->ctrlcap)) {
if (pslot->hpc_ops->set_attention_status(pslot, 1)) { if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__); err("%s: Issue of Set Attention Led command failed\n", __FUNCTION__);
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
return; return;
}
wait_for_ctrl_irq (ctrl);
} }
wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */ /* Done with exclusive hardware access */
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
...@@ -1112,20 +1118,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) ...@@ -1112,20 +1118,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
/* Power on slot */ if (POWER_CTRL(ctrl->ctrlcap)) {
rc = p_slot->hpc_ops->power_on_slot(p_slot); /* Power on slot */
if (rc) { rc = p_slot->hpc_ops->power_on_slot(p_slot);
up(&ctrl->crit_sect); if (rc) {
return -1; up(&ctrl->crit_sect);
} return -1;
}
/* Wait for the command to complete */ /* Wait for the command to complete */
wait_for_ctrl_irq (ctrl); wait_for_ctrl_irq (ctrl);
}
p_slot->hpc_ops->green_led_blink(p_slot); if (PWR_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->green_led_blink(p_slot);
/* Wait for the command to complete */ /* Wait for the command to complete */
wait_for_ctrl_irq (ctrl); wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */ /* Done with exclusive hardware access */
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
...@@ -1212,18 +1222,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) ...@@ -1212,18 +1222,24 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
} }
} while (new_func); } while (new_func);
/* Wait for exclusive access to hardware */ /*
down(&ctrl->crit_sect); * Some PCI Express root ports require fixup after hot-plug operation.
*/
p_slot->hpc_ops->green_led_on(p_slot); if (pcie_mch_quirk)
pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl); if (PWR_LED(ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect); p_slot->hpc_ops->green_led_on(p_slot);
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
}
} else { } else {
set_slot_off(ctrl, p_slot); set_slot_off(ctrl, p_slot);
return -1; return -1;
...@@ -1289,21 +1305,25 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl) ...@@ -1289,21 +1305,25 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
/* power off slot */ if (POWER_CTRL(ctrl->ctrlcap)) {
rc = p_slot->hpc_ops->power_off_slot(p_slot); /* power off slot */
if (rc) { rc = p_slot->hpc_ops->power_off_slot(p_slot);
err("%s: Issue of Slot Disable command failed\n", __FUNCTION__); if (rc) {
up(&ctrl->crit_sect); err("%s: Issue of Slot Disable command failed\n", __FUNCTION__);
return rc; up(&ctrl->crit_sect);
return rc;
}
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
} }
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
/* turn off Green LED */ if (PWR_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->green_led_off(p_slot); /* turn off Green LED */
p_slot->hpc_ops->green_led_off(p_slot);
/* Wait for the command to complete */ /* Wait for the command to complete */
wait_for_ctrl_irq (ctrl); wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */ /* Done with exclusive hardware access */
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
...@@ -1368,7 +1388,6 @@ static void pushbutton_helper_thread(unsigned long data) ...@@ -1368,7 +1388,6 @@ static void pushbutton_helper_thread(unsigned long data)
up(&event_semaphore); up(&event_semaphore);
} }
/** /**
* pciehp_pushbutton_thread * pciehp_pushbutton_thread
* *
...@@ -1399,7 +1418,7 @@ static void pciehp_pushbutton_thread(unsigned long slot) ...@@ -1399,7 +1418,7 @@ static void pciehp_pushbutton_thread(unsigned long slot)
p_slot->state = POWERON_STATE; p_slot->state = POWERON_STATE;
dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device); dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
if (pciehp_enable_slot(p_slot)) { if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&p_slot->ctrl->crit_sect); down(&p_slot->ctrl->crit_sect);
...@@ -1417,6 +1436,55 @@ static void pciehp_pushbutton_thread(unsigned long slot) ...@@ -1417,6 +1436,55 @@ static void pciehp_pushbutton_thread(unsigned long slot)
return; return;
} }
/**
* pciehp_surprise_rm_thread
*
* Scheduled procedure to handle blocking stuff for the surprise removal
* Handles all pending events and exits.
*
*/
static void pciehp_surprise_rm_thread(unsigned long slot)
{
struct slot *p_slot = (struct slot *) slot;
u8 getstatus;
surprise_rm_pending = 0;
if (!p_slot) {
dbg("%s: Error! slot NULL\n", __FUNCTION__);
return;
}
p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (!getstatus) {
p_slot->state = POWEROFF_STATE;
dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
pciehp_disable_slot(p_slot);
p_slot->state = STATIC_STATE;
} else {
p_slot->state = POWERON_STATE;
dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */
down(&p_slot->ctrl->crit_sect);
p_slot->hpc_ops->green_led_off(p_slot);
/* Wait for the command to complete */
wait_for_ctrl_irq (p_slot->ctrl);
/* Done with exclusive hardware access */
up(&p_slot->ctrl->crit_sect);
}
p_slot->state = STATIC_STATE;
}
return;
}
/* this is the main worker thread */ /* this is the main worker thread */
static int event_thread(void* data) static int event_thread(void* data)
...@@ -1436,6 +1504,8 @@ static int event_thread(void* data) ...@@ -1436,6 +1504,8 @@ static int event_thread(void* data)
/* Do stuff here */ /* Do stuff here */
if (pushbutton_pending) if (pushbutton_pending)
pciehp_pushbutton_thread(pushbutton_pending); pciehp_pushbutton_thread(pushbutton_pending);
else if (surprise_rm_pending)
pciehp_surprise_rm_thread(surprise_rm_pending);
else else
for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next) for (ctrl = pciehp_ctrl_list; ctrl; ctrl=ctrl->next)
interrupt_event_handler(ctrl); interrupt_event_handler(ctrl);
...@@ -1528,16 +1598,18 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -1528,16 +1598,18 @@ static void interrupt_event_handler(struct controller *ctrl)
case BLINKINGOFF_STATE: case BLINKINGOFF_STATE:
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
p_slot->hpc_ops->green_led_on(p_slot); if (PWR_LED(ctrl->ctrlcap)) {
/* Wait for the command to complete */ p_slot->hpc_ops->green_led_on(p_slot);
wait_for_ctrl_irq (ctrl); /* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0); }
if (ATTN_LED(ctrl->ctrlcap)) {
/* Wait for the command to complete */ p_slot->hpc_ops->set_attention_status(p_slot, 0);
wait_for_ctrl_irq (ctrl);
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */ /* Done with exclusive hardware access */
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
break; break;
...@@ -1545,14 +1617,16 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -1545,14 +1617,16 @@ static void interrupt_event_handler(struct controller *ctrl)
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
p_slot->hpc_ops->green_led_off(p_slot); if (PWR_LED(ctrl->ctrlcap)) {
/* Wait for the command to complete */ p_slot->hpc_ops->green_led_off(p_slot);
wait_for_ctrl_irq (ctrl); /* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0); }
/* Wait for the command to complete */ if (ATTN_LED(ctrl->ctrlcap)){
wait_for_ctrl_irq (ctrl); p_slot->hpc_ops->set_attention_status(p_slot, 0);
/* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */ /* Done with exclusive hardware access */
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
...@@ -1566,59 +1640,83 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -1566,59 +1640,83 @@ static void interrupt_event_handler(struct controller *ctrl)
} }
/* ***********Button Pressed (No action on 1st press...) */ /* ***********Button Pressed (No action on 1st press...) */
else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) { else if (ctrl->event_queue[loop].event_type == INT_BUTTON_PRESS) {
dbg("Button pressed\n");
if (ATTN_BUTTN(ctrl->ctrlcap)) {
p_slot->hpc_ops->get_power_status(p_slot, &getstatus); dbg("Button pressed\n");
if (getstatus) { p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
/* slot is on */ if (getstatus) {
dbg("slot is on\n"); /* slot is on */
p_slot->state = BLINKINGOFF_STATE; dbg("slot is on\n");
info(msg_button_off, p_slot->number); p_slot->state = BLINKINGOFF_STATE;
} else { info(msg_button_off, p_slot->number);
/* slot is off */ } else {
dbg("slot is off\n"); /* slot is off */
p_slot->state = BLINKINGON_STATE; dbg("slot is off\n");
info(msg_button_on, p_slot->number); p_slot->state = BLINKINGON_STATE;
} info(msg_button_on, p_slot->number);
}
/* Wait for exclusive access to hardware */ /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
/* blink green LED and turn off amber */ /* blink green LED and turn off amber */
p_slot->hpc_ops->green_led_blink(p_slot); if (PWR_LED(ctrl->ctrlcap)) {
/* Wait for the command to complete */ p_slot->hpc_ops->green_led_blink(p_slot);
wait_for_ctrl_irq (ctrl); /* Wait for the command to complete */
wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->set_attention_status(p_slot, 0); }
if (ATTN_LED(ctrl->ctrlcap)) {
p_slot->hpc_ops->set_attention_status(p_slot, 0);
/* Wait for the command to complete */ /* Wait for the command to complete */
wait_for_ctrl_irq (ctrl); wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */ /* Done with exclusive hardware access */
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
init_timer(&p_slot->task_event); init_timer(&p_slot->task_event);
p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */ p_slot->task_event.expires = jiffies + 5 * HZ; /* 5 second delay */
p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread; p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
p_slot->task_event.data = (unsigned long) p_slot; p_slot->task_event.data = (unsigned long) p_slot;
dbg("add_timer p_slot = %p\n", (void *) p_slot); dbg("add_timer p_slot = %p\n", (void *) p_slot);
add_timer(&p_slot->task_event); add_timer(&p_slot->task_event);
}
} }
/***********POWER FAULT********************/ /***********POWER FAULT********************/
else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) { else if (ctrl->event_queue[loop].event_type == INT_POWER_FAULT) {
dbg("power fault\n"); if (POWER_CTRL(ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */ dbg("power fault\n");
down(&ctrl->crit_sect); /* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
p_slot->hpc_ops->set_attention_status(p_slot, 1); if (ATTN_LED(ctrl->ctrlcap)) {
wait_for_ctrl_irq (ctrl); p_slot->hpc_ops->set_attention_status(p_slot, 1);
wait_for_ctrl_irq (ctrl);
p_slot->hpc_ops->green_led_off(p_slot); }
wait_for_ctrl_irq (ctrl);
/* Done with exclusive hardware access */ if (PWR_LED(ctrl->ctrlcap)) {
up(&ctrl->crit_sect); p_slot->hpc_ops->green_led_off(p_slot);
wait_for_ctrl_irq (ctrl);
}
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
}
}
/***********SURPRISE REMOVAL********************/
else if ((ctrl->event_queue[loop].event_type == INT_PRESENCE_ON) ||
(ctrl->event_queue[loop].event_type == INT_PRESENCE_OFF)) {
if (HP_SUPR_RM(ctrl->ctrlcap)) {
dbg("Surprise Removal\n");
if (p_slot) {
surprise_rm_pending = (unsigned long) p_slot;
up(&event_semaphore);
update_slot_info(p_slot);
}
}
} else { } else {
/* refresh notification */ /* refresh notification */
if (p_slot) if (p_slot)
...@@ -1648,25 +1746,29 @@ int pciehp_enable_slot(struct slot *p_slot) ...@@ -1648,25 +1746,29 @@ int pciehp_enable_slot(struct slot *p_slot)
/* Check to see if (latch closed, card present, power off) */ /* Check to see if (latch closed, card present, power off) */
down(&p_slot->ctrl->crit_sect); down(&p_slot->ctrl->crit_sect);
rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); rc = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (rc || !getstatus) { if (rc || !getstatus) {
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect); up(&p_slot->ctrl->crit_sect);
return 1; return 1;
} }
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (rc || getstatus) { if (rc || getstatus) {
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
up(&p_slot->ctrl->crit_sect); up(&p_slot->ctrl->crit_sect);
return 1; return 1;
}
} }
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
if (rc || getstatus) { rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number); if (rc || getstatus) {
up(&p_slot->ctrl->crit_sect); info("%s: already enabled on slot(%x)\n", __FUNCTION__, p_slot->number);
return 1; up(&p_slot->ctrl->crit_sect);
return 1;
}
} }
up(&p_slot->ctrl->crit_sect); up(&p_slot->ctrl->crit_sect);
...@@ -1735,26 +1837,33 @@ int pciehp_disable_slot(struct slot *p_slot) ...@@ -1735,26 +1837,33 @@ int pciehp_disable_slot(struct slot *p_slot)
/* Check to see if (latch closed, card present, power on) */ /* Check to see if (latch closed, card present, power on) */
down(&p_slot->ctrl->crit_sect); down(&p_slot->ctrl->crit_sect);
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus); if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
if (ret || !getstatus) { ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number); if (ret || !getstatus) {
up(&p_slot->ctrl->crit_sect); info("%s: no adapter on slot(%x)\n", __FUNCTION__, p_slot->number);
return 1; up(&p_slot->ctrl->crit_sect);
return 1;
}
} }
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus); if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
if (ret || getstatus) { ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number); if (ret || getstatus) {
up(&p_slot->ctrl->crit_sect); info("%s: latch open on slot(%x)\n", __FUNCTION__, p_slot->number);
return 1; up(&p_slot->ctrl->crit_sect);
return 1;
}
} }
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus); if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
if (ret || !getstatus) { ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number); if (ret || !getstatus) {
up(&p_slot->ctrl->crit_sect); info("%s: already disabled slot(%x)\n", __FUNCTION__, p_slot->number);
return 1; up(&p_slot->ctrl->crit_sect);
return 1;
}
} }
up(&p_slot->ctrl->crit_sect); up(&p_slot->ctrl->crit_sect);
func = pciehp_slot_find(p_slot->bus, p_slot->device, index++); func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
......
...@@ -182,7 +182,7 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct ...@@ -182,7 +182,7 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct
#define MRL_SENS_PRSN 0x00000004 #define MRL_SENS_PRSN 0x00000004
#define ATTN_LED_PRSN 0x00000008 #define ATTN_LED_PRSN 0x00000008
#define PWR_LED_PRSN 0x00000010 #define PWR_LED_PRSN 0x00000010
#define HP_SUPR_RM 0x00000020 #define HP_SUPR_RM_SUP 0x00000020
#define HP_CAP 0x00000040 #define HP_CAP 0x00000040
#define SLOT_PWR_VALUE 0x000003F8 #define SLOT_PWR_VALUE 0x000003F8
#define SLOT_PWR_LIMIT 0x00000C00 #define SLOT_PWR_LIMIT 0x00000C00
...@@ -237,8 +237,8 @@ struct php_ctlr_state_s { ...@@ -237,8 +237,8 @@ struct php_ctlr_state_s {
static spinlock_t hpc_event_lock; static spinlock_t hpc_event_lock;
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */ DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
static struct php_ctlr_state_s *php_ctlr_list_head; /* HPC state linked list */ static struct php_ctlr_state_s *php_ctlr_list_head = 0; /* HPC state linked list */
static int ctlr_seq_num; /* Controller sequence # */ static int ctlr_seq_num = 0; /* Controller sequence # */
static spinlock_t list_lock; static spinlock_t list_lock;
static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs); static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
...@@ -691,8 +691,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, ...@@ -691,8 +691,7 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */ int *num_ctlr_slots, /* number of slots in this HPC; only 1 in PCIE */
int *first_device_num, /* PCI dev num of the first slot in this PCIE */ int *first_device_num, /* PCI dev num of the first slot in this PCIE */
int *physical_slot_num, /* phy slot num of the first slot in this PCIE */ int *physical_slot_num, /* phy slot num of the first slot in this PCIE */
int *updown, /* physical_slot_num increament: 1 or -1 */ u8 *ctrlcap)
int *flags)
{ {
struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle; struct php_ctlr_state_s *php_ctlr = ctrl->hpc_ctlr_handle;
u32 slot_cap; u32 slot_cap;
...@@ -716,8 +715,9 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl, ...@@ -716,8 +715,9 @@ int pcie_get_ctlr_slot_config(struct controller *ctrl,
} }
*physical_slot_num = slot_cap >> 19; *physical_slot_num = slot_cap >> 19;
dbg("%s: PSN %d \n", __FUNCTION__, *physical_slot_num);
*updown = -1;
*ctrlcap = slot_cap & 0x0000007f;
DBG_LEAVE_ROUTINE DBG_LEAVE_ROUTINE
return 0; return 0;
...@@ -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)
...@@ -1259,7 +1261,7 @@ int pcie_init(struct controller * ctrl, ...@@ -1259,7 +1261,7 @@ int pcie_init(struct controller * ctrl,
static int first = 1; static int first = 1;
u16 temp_word; u16 temp_word;
u16 cap_reg; u16 cap_reg;
u16 intr_enable; u16 intr_enable = 0;
u32 slot_cap; u32 slot_cap;
int cap_base, saved_cap_base; int cap_base, saved_cap_base;
u16 slot_status, slot_ctrl; u16 slot_status, slot_ctrl;
...@@ -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");
...@@ -1412,6 +1414,7 @@ int pcie_init(struct controller * ctrl, ...@@ -1412,6 +1414,7 @@ int pcie_init(struct controller * ctrl,
} else } else
php_ctlr->irq = pdev->irq; php_ctlr->irq = pdev->irq;
} }
rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl); rc = request_irq(php_ctlr->irq, pcie_isr, SA_SHIRQ, MY_NAME, (void *) ctrl);
dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc); dbg("%s: request_irq %d for hpc%d (returns %d)\n", __FUNCTION__, php_ctlr->irq, ctlr_seq_num, rc);
if (rc) { if (rc) {
...@@ -1426,9 +1429,18 @@ int pcie_init(struct controller * ctrl, ...@@ -1426,9 +1429,18 @@ int pcie_init(struct controller * ctrl,
goto abort_free_ctlr; goto abort_free_ctlr;
} }
dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word); dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL, temp_word);
dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
intr_enable = ATTN_BUTTN_ENABLE | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | intr_enable = intr_enable | PRSN_DETECT_ENABLE;
PRSN_DETECT_ENABLE;
if (ATTN_BUTTN(slot_cap))
intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
if (POWER_CTRL(slot_cap))
intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
if (MRL_SENS(slot_cap))
intr_enable = intr_enable | MRL_DETECT_ENABLE;
temp_word = (temp_word & ~intr_enable) | intr_enable; temp_word = (temp_word & ~intr_enable) | intr_enable;
......
...@@ -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;
} }
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/acpi.h> #include <linux/acpi.h>
#include <linux/efi.h> #include <linux/efi.h>
#include <linux/pci-acpi.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/system.h> #include <asm/system.h>
#ifdef CONFIG_IA64 #ifdef CONFIG_IA64
...@@ -50,6 +51,14 @@ ...@@ -50,6 +51,14 @@
#define METHOD_NAME__HPP "_HPP" #define METHOD_NAME__HPP "_HPP"
#define METHOD_NAME_OSHP "OSHP" #define METHOD_NAME_OSHP "OSHP"
/* Status code for running acpi method to gain native control */
#define NC_NOT_RUN 0
#define OSC_NOT_EXIST 1
#define OSC_RUN_FAILED 2
#define OSHP_NOT_EXIST 3
#define OSHP_RUN_FAILED 4
#define NC_RUN_SUCCESS 5
#define PHP_RES_BUS 0xA0 #define PHP_RES_BUS 0xA0
#define PHP_RES_IO 0xA1 #define PHP_RES_IO 0xA1
#define PHP_RES_MEM 0xA2 #define PHP_RES_MEM 0xA2
...@@ -125,7 +134,9 @@ static u8 * acpi_path_name( acpi_handle handle) ...@@ -125,7 +134,9 @@ static u8 * acpi_path_name( acpi_handle handle)
} }
static void acpi_get__hpp ( struct acpi_bridge *ab); static void acpi_get__hpp ( struct acpi_bridge *ab);
static void acpi_run_oshp ( struct acpi_bridge *ab); static int acpi_run_oshp ( struct acpi_bridge *ab);
static int osc_run_status = NC_NOT_RUN;
static int oshp_run_status = NC_NOT_RUN;
static int acpi_add_slot_to_php_slots( static int acpi_add_slot_to_php_slots(
struct acpi_bridge *ab, struct acpi_bridge *ab,
...@@ -158,8 +169,9 @@ static int acpi_add_slot_to_php_slots( ...@@ -158,8 +169,9 @@ static int acpi_add_slot_to_php_slots(
ab->scanned += 1; ab->scanned += 1;
if (!ab->_hpp) if (!ab->_hpp)
acpi_get__hpp(ab); acpi_get__hpp(ab);
acpi_run_oshp(ab); if (osc_run_status == OSC_NOT_EXIST)
oshp_run_status = acpi_run_oshp(ab);
if (sun != samesun) { if (sun != samesun) {
info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n", info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n",
...@@ -238,7 +250,7 @@ static void acpi_get__hpp ( struct acpi_bridge *ab) ...@@ -238,7 +250,7 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
kfree(ret_buf.pointer); kfree(ret_buf.pointer);
} }
static void acpi_run_oshp ( struct acpi_bridge *ab) static int acpi_run_oshp ( struct acpi_bridge *ab)
{ {
acpi_status status; acpi_status status;
u8 *path_name = acpi_path_name(ab->handle); u8 *path_name = acpi_path_name(ab->handle);
...@@ -248,9 +260,13 @@ static void acpi_run_oshp ( struct acpi_bridge *ab) ...@@ -248,9 +260,13 @@ static void acpi_run_oshp ( struct acpi_bridge *ab)
status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf); status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, &ret_buf);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status); err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
} else oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED;
} else {
oshp_run_status = NC_RUN_SUCCESS;
dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status); dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
return; dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status);
}
return oshp_run_status;
} }
static acpi_status acpi_evaluate_crs( static acpi_status acpi_evaluate_crs(
...@@ -1056,6 +1072,16 @@ static struct acpi_bridge * add_host_bridge( ...@@ -1056,6 +1072,16 @@ static struct acpi_bridge * add_host_bridge(
kfree(ab); kfree(ab);
return NULL; return NULL;
} }
status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
if (ACPI_FAILURE(status)) {
err("%s: status %x\n", __FUNCTION__, status);
osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED;
} else {
osc_run_status = NC_RUN_SUCCESS;
}
dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status);
build_a_bridge(ab, ab); build_a_bridge(ab, ab);
return ab; return ab;
...@@ -1141,6 +1167,11 @@ int pciehprm_init(enum php_ctlr_type ctlr_type) ...@@ -1141,6 +1167,11 @@ int pciehprm_init(enum php_ctlr_type ctlr_type)
if (rc) if (rc)
return rc; return rc;
if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) {
err("Fails to gain control of native hot-plug\n");
rc = -ENODEV;
}
dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success"); dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success");
return rc; return rc;
} }
......
...@@ -1157,6 +1157,40 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) ...@@ -1157,6 +1157,40 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
return -1; return -1;
} }
if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {
if (slots_not_empty)
return WRONG_BUS_FREQUENCY;
if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {
err("%s: Issue of set bus speed mode command failed\n", __FUNCTION__);
up(&ctrl->crit_sect);
return WRONG_BUS_FREQUENCY;
}
wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Can't set bus speed/mode in the case of adapter & bus mismatch\n",
__FUNCTION__);
err("%s: Error code (%d)\n", __FUNCTION__, rc);
up(&ctrl->crit_sect);
return WRONG_BUS_FREQUENCY;
}
/* turn on board, blink green LED, turn off Amber LED */
if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {
err("%s: Issue of Slot Enable command failed\n", __FUNCTION__);
up(&ctrl->crit_sect);
return rc;
}
wait_for_ctrl_irq (ctrl);
if ((rc = p_slot->hpc_ops->check_cmd_status(ctrl))) {
err("%s: Failed to enable slot, error code(%d)\n", __FUNCTION__, rc);
up(&ctrl->crit_sect);
return rc;
}
}
rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed); rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &adapter_speed);
/* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */ /* 0 = PCI 33Mhz, 1 = PCI 66 Mhz, 2 = PCI-X 66 PA, 4 = PCI-X 66 ECC, */
/* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */ /* 5 = PCI-X 133 PA, 7 = PCI-X 133 ECC, 0xa = PCI-X 133 Mhz 266, */
......
...@@ -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) {
......
/*
* File: pci-acpi.c
* Purpose: Provide PCI supports in ACPI
*
* Copyright (C) 2004 Intel
* Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
*/
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/module.h>
#include <acpi/acpi.h>
#include <acpi/acnamesp.h>
#include <acpi/acresrc.h>
#include <acpi/acpi_bus.h>
#include <linux/pci-acpi.h>
static u32 ctrlset_buf[3] = {0, 0, 0};
static u32 global_ctrlsets = 0;
u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
static acpi_status
acpi_query_osc (
acpi_handle handle,
u32 level,
void *context,
void **retval )
{
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[4];
struct acpi_buffer output;
union acpi_object out_obj;
u32 osc_dw0;
/* Setting up output buffer */
output.length = sizeof(out_obj) + 3*sizeof(u32);
output.pointer = &out_obj;
/* Setting up input parameters */
input.count = 4;
input.pointer = in_params;
in_params[0].type = ACPI_TYPE_BUFFER;
in_params[0].buffer.length = 16;
in_params[0].buffer.pointer = OSC_UUID;
in_params[1].type = ACPI_TYPE_INTEGER;
in_params[1].integer.value = 1;
in_params[2].type = ACPI_TYPE_INTEGER;
in_params[2].integer.value = 3;
in_params[3].type = ACPI_TYPE_BUFFER;
in_params[3].buffer.length = 12;
in_params[3].buffer.pointer = (u8 *)context;
status = acpi_evaluate_object(handle, "_OSC", &input, &output);
if (ACPI_FAILURE (status)) {
printk(KERN_DEBUG
"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
return status;
}
if (out_obj.type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG
"Evaluate _OSC returns wrong type\n");
return AE_TYPE;
}
osc_dw0 = *((u32 *) out_obj.buffer.pointer);
if (osc_dw0) {
if (osc_dw0 & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n");
if (osc_dw0 & OSC_INVALID_UUID_ERROR)
printk(KERN_DEBUG "_OSC invalid UUID\n");
if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
printk(KERN_DEBUG "_OSC invalid revision\n");
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
/* Update Global Control Set */
global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8));
return AE_OK;
}
return AE_ERROR;
}
/* Update Global Control Set */
global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8));
return AE_OK;
}
static acpi_status
acpi_run_osc (
acpi_handle handle,
u32 level,
void *context,
void **retval )
{
acpi_status status;
struct acpi_object_list input;
union acpi_object in_params[4];
struct acpi_buffer output;
union acpi_object out_obj;
u32 osc_dw0;
/* Setting up output buffer */
output.length = sizeof(out_obj) + 3*sizeof(u32);
output.pointer = &out_obj;
/* Setting up input parameters */
input.count = 4;
input.pointer = in_params;
in_params[0].type = ACPI_TYPE_BUFFER;
in_params[0].buffer.length = 16;
in_params[0].buffer.pointer = OSC_UUID;
in_params[1].type = ACPI_TYPE_INTEGER;
in_params[1].integer.value = 1;
in_params[2].type = ACPI_TYPE_INTEGER;
in_params[2].integer.value = 3;
in_params[3].type = ACPI_TYPE_BUFFER;
in_params[3].buffer.length = 12;
in_params[3].buffer.pointer = (u8 *)context;
status = acpi_evaluate_object(handle, "_OSC", &input, &output);
if (ACPI_FAILURE (status)) {
printk(KERN_DEBUG
"Evaluate _OSC Set fails. Status = 0x%04x\n", status);
return status;
}
if (out_obj.type != ACPI_TYPE_BUFFER) {
printk(KERN_DEBUG
"Evaluate _OSC returns wrong type\n");
return AE_TYPE;
}
osc_dw0 = *((u32 *) out_obj.buffer.pointer);
if (osc_dw0) {
if (osc_dw0 & OSC_REQUEST_ERROR)
printk(KERN_DEBUG "_OSC request fails\n");
if (osc_dw0 & OSC_INVALID_UUID_ERROR)
printk(KERN_DEBUG "_OSC invalid UUID\n");
if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
printk(KERN_DEBUG "_OSC invalid revision\n");
if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
printk(KERN_DEBUG "_OSC FW not grant req. control\n");
return AE_SUPPORT;
}
return AE_ERROR;
}
return AE_OK;
}
/**
* pci_osc_support_set - register OS support to Firmware
* @flags: OS support bits
*
* Update OS support fields and doing a _OSC Query to obtain an update
* from Firmware on supported control bits.
**/
acpi_status pci_osc_support_set(u32 flags)
{
u32 temp;
if (!(flags & OSC_SUPPORT_MASKS)) {
return AE_TYPE;
}
ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS);
/* do _OSC query for all possible controls */
temp = ctrlset_buf[OSC_CONTROL_TYPE];
ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
acpi_get_devices ( PCI_ROOT_HID_STRING,
acpi_query_osc,
ctrlset_buf,
NULL );
ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE;
ctrlset_buf[OSC_CONTROL_TYPE] = temp;
return AE_OK;
}
EXPORT_SYMBOL(pci_osc_support_set);
/**
* pci_osc_control_set - commit requested control to Firmware
* @flags: driver's requested control bits
*
* Attempt to take control from Firmware on requested control bits.
**/
acpi_status pci_osc_control_set(u32 flags)
{
acpi_status status;
u32 ctrlset;
ctrlset = (flags & OSC_CONTROL_MASKS);
if (!ctrlset) {
return AE_TYPE;
}
if (ctrlset_buf[OSC_SUPPORT_TYPE] &&
((global_ctrlsets & ctrlset) != ctrlset)) {
return AE_SUPPORT;
}
ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
status = acpi_get_devices ( PCI_ROOT_HID_STRING,
acpi_run_osc,
ctrlset_buf,
NULL );
if (ACPI_FAILURE (status)) {
ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
}
return status;
}
EXPORT_SYMBOL(pci_osc_control_set);
...@@ -271,17 +271,14 @@ static int pci_device_remove(struct device * dev) ...@@ -271,17 +271,14 @@ static int pci_device_remove(struct device * dev)
pci_dev->driver = NULL; pci_dev->driver = NULL;
} }
#ifdef CONFIG_DEBUG_KERNEL
/* /*
* If the driver decides to stop using the device, it should * We would love to complain here if pci_dev->is_enabled is set, that
* call pci_disable_device(). * the driver should have called pci_disable_device(), but the
* unfortunate fact is there are too many odd BIOS and bridge setups
* that don't like drivers doing that all of the time.
* Oh well, we can dream of sane hardware when we sleep, no matter how
* horrible the crap we have to deal with is when we are awake...
*/ */
if (pci_dev->is_enabled) {
dev_warn(&pci_dev->dev, "Device was removed without properly "
"calling pci_disable_device(). This may need fixing.\n");
/* WARN_ON(1); */
}
#endif /* CONFIG_DEBUG_KERNEL */
pci_dev_put(pci_dev); pci_dev_put(pci_dev);
return 0; return 0;
......
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
* (C) Copyright 2002-2004 IBM Corp. * (C) Copyright 2002-2004 IBM Corp.
* (C) Copyright 2003 Matthew Wilcox * (C) Copyright 2003 Matthew Wilcox
* (C) Copyright 2003 Hewlett-Packard * (C) Copyright 2003 Hewlett-Packard
* (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
* (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
* *
* File attributes for PCI devices * File attributes for PCI devices
* *
...@@ -20,6 +22,8 @@ ...@@ -20,6 +22,8 @@
#include "pci.h" #include "pci.h"
static int sysfs_initialized; /* = 0 */
/* show configuration fields */ /* show configuration fields */
#define pci_config_attr(field, format_string) \ #define pci_config_attr(field, format_string) \
static ssize_t \ static ssize_t \
...@@ -164,6 +168,65 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count) ...@@ -164,6 +168,65 @@ pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
return count; return count;
} }
/**
* pci_write_rom - used to enable access to the PCI ROM display
* @kobj: kernel object handle
* @buf: user input
* @off: file offset
* @count: number of byte in input
*
* writing anything except 0 enables it
*/
static ssize_t
pci_write_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
if ((off == 0) && (*buf == '0') && (count == 2))
pdev->rom_attr_enabled = 0;
else
pdev->rom_attr_enabled = 1;
return count;
}
/**
* pci_read_rom - read a PCI ROM
* @kobj: kernel object handle
* @buf: where to put the data we read from the ROM
* @off: file offset
* @count: number of bytes to read
*
* Put @count bytes starting at @off into @buf from the ROM in the PCI
* device corresponding to @kobj.
*/
static ssize_t
pci_read_rom(struct kobject *kobj, char *buf, loff_t off, size_t count)
{
struct pci_dev *pdev = to_pci_dev(container_of(kobj, struct device, kobj));
void __iomem *rom;
size_t size;
if (!pdev->rom_attr_enabled)
return -EINVAL;
rom = pci_map_rom(pdev, &size); /* size starts out as PCI window size */
if (!rom)
return 0;
if (off >= size)
count = 0;
else {
if (off + count > size)
count = size - off;
memcpy_fromio(buf, rom + off, count);
}
pci_unmap_rom(pdev, rom);
return count;
}
static struct bin_attribute pci_config_attr = { static struct bin_attribute pci_config_attr = {
.attr = { .attr = {
.name = "config", .name = "config",
...@@ -186,13 +249,68 @@ static struct bin_attribute pcie_config_attr = { ...@@ -186,13 +249,68 @@ static struct bin_attribute pcie_config_attr = {
.write = pci_write_config, .write = pci_write_config,
}; };
void pci_create_sysfs_dev_files (struct pci_dev *pdev) int pci_create_sysfs_dev_files (struct pci_dev *pdev)
{ {
if (!sysfs_initialized)
return -EACCES;
if (pdev->cfg_size < 4096) if (pdev->cfg_size < 4096)
sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr); sysfs_create_bin_file(&pdev->dev.kobj, &pci_config_attr);
else else
sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr); sysfs_create_bin_file(&pdev->dev.kobj, &pcie_config_attr);
/* If the device has a ROM, try to expose it in sysfs. */
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
struct bin_attribute *rom_attr;
rom_attr = kmalloc(sizeof(*rom_attr), GFP_ATOMIC);
if (rom_attr) {
pdev->rom_attr = rom_attr;
rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
rom_attr->attr.name = "rom";
rom_attr->attr.mode = S_IRUSR;
rom_attr->attr.owner = THIS_MODULE;
rom_attr->read = pci_read_rom;
rom_attr->write = pci_write_rom;
sysfs_create_bin_file(&pdev->dev.kobj, rom_attr);
}
}
/* add platform-specific attributes */ /* add platform-specific attributes */
pcibios_add_platform_entries(pdev); pcibios_add_platform_entries(pdev);
return 0;
}
/**
* pci_remove_sysfs_dev_files - cleanup PCI specific sysfs files
* @pdev: device whose entries we should free
*
* Cleanup when @pdev is removed from sysfs.
*/
void pci_remove_sysfs_dev_files(struct pci_dev *pdev)
{
if (pdev->cfg_size < 4096)
sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr);
else
sysfs_remove_bin_file(&pdev->dev.kobj, &pcie_config_attr);
if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) {
if (pdev->rom_attr) {
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
kfree(pdev->rom_attr);
}
}
} }
static int __init pci_sysfs_init(void)
{
struct pci_dev *pdev = NULL;
sysfs_initialized = 1;
while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL)
pci_create_sysfs_dev_files(pdev);
return 0;
}
__initcall(pci_sysfs_init);
...@@ -374,6 +374,16 @@ pci_enable_device(struct pci_dev *dev) ...@@ -374,6 +374,16 @@ pci_enable_device(struct pci_dev *dev)
return 0; return 0;
} }
/**
* pcibios_disable_device - disable arch specific PCI resources for device dev
* @dev: the PCI device to disable
*
* Disables architecture specific PCI resources for the device. This
* is the default implementation. Architecture implementations can
* override this.
*/
void __attribute__ ((weak)) pcibios_disable_device (struct pci_dev *dev) {}
/** /**
* pci_disable_device - Disable PCI device after use * pci_disable_device - Disable PCI device after use
* @dev: PCI device to be disabled * @dev: PCI device to be disabled
...@@ -394,6 +404,8 @@ pci_disable_device(struct pci_dev *dev) ...@@ -394,6 +404,8 @@ pci_disable_device(struct pci_dev *dev)
pci_command &= ~PCI_COMMAND_MASTER; pci_command &= ~PCI_COMMAND_MASTER;
pci_write_config_word(dev, PCI_COMMAND, pci_command); pci_write_config_word(dev, PCI_COMMAND, pci_command);
} }
pcibios_disable_device(dev);
} }
/** /**
......
...@@ -2,7 +2,9 @@ ...@@ -2,7 +2,9 @@
extern int pci_hotplug (struct device *dev, char **envp, int num_envp, extern int pci_hotplug (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size); char *buffer, int buffer_size);
extern void pci_create_sysfs_dev_files(struct pci_dev *pdev); extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
extern void pci_cleanup_rom(struct pci_dev *dev);
extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res, extern int pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
unsigned long size, unsigned long align, unsigned long size, unsigned long align,
unsigned long min, unsigned int type_mask, unsigned long min, unsigned int type_mask,
...@@ -61,7 +63,7 @@ extern int pci_visit_dev(struct pci_visit *fn, ...@@ -61,7 +63,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[];
/** /**
......
...@@ -170,7 +170,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) ...@@ -170,7 +170,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
if (sz && sz != 0xffffffff) { if (sz && sz != 0xffffffff) {
sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK); sz = pci_size(l, sz, PCI_ROM_ADDRESS_MASK);
if (sz) { if (sz) {
res->flags = (l & PCI_ROM_ADDRESS_ENABLE) | res->flags = (l & IORESOURCE_ROM_ENABLE) |
IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_MEM | IORESOURCE_PREFETCH |
IORESOURCE_READONLY | IORESOURCE_CACHEABLE; IORESOURCE_READONLY | IORESOURCE_CACHEABLE;
res->start = l & PCI_ROM_ADDRESS_MASK; res->start = l & PCI_ROM_ADDRESS_MASK;
...@@ -478,6 +478,9 @@ static int pci_setup_device(struct pci_dev * dev) ...@@ -478,6 +478,9 @@ static int pci_setup_device(struct pci_dev * dev)
/* "Unknown power state" */ /* "Unknown power state" */
dev->current_state = 4; dev->current_state = 4;
/* Early fixups, before probing the BARs */
pci_fixup_device(pci_fixup_early, dev);
switch (dev->hdr_type) { /* header type */ switch (dev->hdr_type) { /* header type */
case PCI_HEADER_TYPE_NORMAL: /* standard header */ case PCI_HEADER_TYPE_NORMAL: /* standard header */
if (class == PCI_CLASS_BRIDGE_PCI) if (class == PCI_CLASS_BRIDGE_PCI)
......
...@@ -1136,7 +1136,7 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EESSC, quirk_a ...@@ -1136,7 +1136,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;
...@@ -1210,14 +1210,15 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_intel_ide_co ...@@ -1210,14 +1210,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)
{ {
...@@ -1266,4 +1267,7 @@ void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev) ...@@ -1266,4 +1267,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
...@@ -16,6 +16,7 @@ static void pci_free_resources(struct pci_dev *dev) ...@@ -16,6 +16,7 @@ static void pci_free_resources(struct pci_dev *dev)
msi_remove_pci_irq_vectors(dev); msi_remove_pci_irq_vectors(dev);
pci_cleanup_rom(dev);
for (i = 0; i < PCI_NUM_RESOURCES; i++) { for (i = 0; i < PCI_NUM_RESOURCES; i++) {
struct resource *res = dev->resource + i; struct resource *res = dev->resource + i;
if (res->parent) if (res->parent)
...@@ -26,6 +27,7 @@ static void pci_free_resources(struct pci_dev *dev) ...@@ -26,6 +27,7 @@ static void pci_free_resources(struct pci_dev *dev)
static void pci_destroy_dev(struct pci_dev *dev) static void pci_destroy_dev(struct pci_dev *dev)
{ {
pci_proc_detach_device(dev); pci_proc_detach_device(dev);
pci_remove_sysfs_dev_files(dev);
device_unregister(&dev->dev); device_unregister(&dev->dev);
/* Remove the device from the device lists, and prevent any further /* Remove the device from the device lists, and prevent any further
......
/*
* drivers/pci/rom.c
*
* (C) Copyright 2004 Jon Smirl <jonsmirl@yahoo.com>
* (C) Copyright 2004 Silicon Graphics, Inc. Jesse Barnes <jbarnes@sgi.com>
*
* PCI ROM access routines
*
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include "pci.h"
/**
* pci_enable_rom - enable ROM decoding for a PCI device
* @dev: PCI device to enable
*
* Enable ROM decoding on @dev. This involves simply turning on the last
* bit of the PCI ROM BAR. Note that some cards may share address decoders
* between the ROM and other resources, so enabling it may disable access
* to MMIO registers or other card memory.
*/
static void
pci_enable_rom(struct pci_dev *pdev)
{
u32 rom_addr;
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
rom_addr |= PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
}
/**
* pci_disable_rom - disable ROM decoding for a PCI device
* @dev: PCI device to disable
*
* Disable ROM decoding on a PCI device by turning off the last bit in the
* ROM BAR.
*/
static void
pci_disable_rom(struct pci_dev *pdev)
{
u32 rom_addr;
pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
rom_addr &= ~PCI_ROM_ADDRESS_ENABLE;
pci_write_config_dword(pdev, pdev->rom_base_reg, rom_addr);
}
/**
* pci_map_rom - map a PCI ROM to kernel space
* @dev: pointer to pci device struct
* @size: pointer to receive size of pci window over ROM
* @return: kernel virtual pointer to image of ROM
*
* Map a PCI ROM into kernel space. If ROM is boot video ROM,
* the shadow BIOS copy will be returned instead of the
* actual ROM.
*/
void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
loff_t start;
void __iomem *rom;
void __iomem *image;
int last_image;
if (res->flags & IORESOURCE_ROM_SHADOW) { /* IORESOURCE_ROM_SHADOW only set on x86 */
start = (loff_t)0xC0000; /* primary video rom always starts here */
*size = 0x20000; /* cover C000:0 through E000:0 */
} else {
if (res->flags & IORESOURCE_ROM_COPY) {
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
return (void __iomem *)pci_resource_start(pdev, PCI_ROM_RESOURCE);
} else {
/* assign the ROM an address if it doesn't have one */
if (res->parent == NULL)
pci_assign_resource(pdev, PCI_ROM_RESOURCE);
start = pci_resource_start(pdev, PCI_ROM_RESOURCE);
*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
if (*size == 0)
return NULL;
/* Enable ROM space decodes */
pci_enable_rom(pdev);
}
}
rom = ioremap(start, *size);
if (!rom) {
/* restore enable if ioremap fails */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW | IORESOURCE_ROM_COPY)))
pci_disable_rom(pdev);
return NULL;
}
/* Try to find the true size of the ROM since sometimes the PCI window */
/* size is much larger than the actual size of the ROM. */
/* True size is important if the ROM is going to be copied. */
image = rom;
do {
void __iomem *pds;
/* Standard PCI ROMs start out with these bytes 55 AA */
if (readb(image) != 0x55)
break;
if (readb(image + 1) != 0xAA)
break;
/* get the PCI data structure and check its signature */
pds = image + readw(image + 24);
if (readb(pds) != 'P')
break;
if (readb(pds + 1) != 'C')
break;
if (readb(pds + 2) != 'I')
break;
if (readb(pds + 3) != 'R')
break;
last_image = readb(pds + 21) & 0x80;
/* this length is reliable */
image += readw(pds + 16) * 512;
} while (!last_image);
*size = image - rom;
return rom;
}
/**
* pci_map_rom_copy - map a PCI ROM to kernel space, create a copy
* @dev: pointer to pci device struct
* @size: pointer to receive size of pci window over ROM
* @return: kernel virtual pointer to image of ROM
*
* Map a PCI ROM into kernel space. If ROM is boot video ROM,
* the shadow BIOS copy will be returned instead of the
* actual ROM.
*/
void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
void __iomem *rom;
rom = pci_map_rom(pdev, size);
if (!rom)
return NULL;
if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW))
return rom;
res->start = (unsigned long)kmalloc(*size, GFP_KERNEL);
if (!res->start)
return rom;
res->end = res->start + *size;
memcpy_fromio((void*)res->start, rom, *size);
pci_unmap_rom(pdev, rom);
res->flags |= IORESOURCE_ROM_COPY;
return (void __iomem *)res->start;
}
/**
* pci_unmap_rom - unmap the ROM from kernel space
* @dev: pointer to pci device struct
* @rom: virtual address of the previous mapping
*
* Remove a mapping of a previously mapped ROM
*/
void
pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
if (res->flags & IORESOURCE_ROM_COPY)
return;
iounmap(rom);
/* Disable again before continuing, leave enabled if pci=rom */
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
pci_disable_rom(pdev);
}
/**
* pci_remove_rom - disable the ROM and remove its sysfs attribute
* @dev: pointer to pci device struct
*
*/
void
pci_remove_rom(struct pci_dev *pdev)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
if (pci_resource_len(pdev, PCI_ROM_RESOURCE))
sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW | IORESOURCE_ROM_COPY)))
pci_disable_rom(pdev);
}
/**
* pci_cleanup_rom - internal routine for freeing the ROM copy created
* by pci_map_rom_copy called from remove.c
* @dev: pointer to pci device struct
*
*/
void
pci_cleanup_rom(struct pci_dev *pdev)
{
struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
if (res->flags & IORESOURCE_ROM_COPY) {
kfree((void*)res->start);
res->flags &= ~IORESOURCE_ROM_COPY;
res->start = 0;
res->end = 0;
}
}
EXPORT_SYMBOL(pci_map_rom);
EXPORT_SYMBOL(pci_map_rom_copy);
EXPORT_SYMBOL(pci_unmap_rom);
EXPORT_SYMBOL(pci_remove_rom);
...@@ -56,7 +56,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno) ...@@ -56,7 +56,7 @@ pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
if (resno < 6) { if (resno < 6) {
reg = PCI_BASE_ADDRESS_0 + 4 * resno; reg = PCI_BASE_ADDRESS_0 + 4 * resno;
} else if (resno == PCI_ROM_RESOURCE) { } else if (resno == PCI_ROM_RESOURCE) {
new |= res->flags & PCI_ROM_ADDRESS_ENABLE; new |= res->flags & IORESOURCE_ROM_ENABLE;
reg = dev->rom_base_reg; reg = dev->rom_base_reg;
} else { } else {
/* Hmm, non-standard resource. */ /* Hmm, non-standard resource. */
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
\ \
/* PCI quirks */ \ /* PCI quirks */ \
.pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \ .pci_fixup : AT(ADDR(.pci_fixup) - LOAD_OFFSET) { \
VMLINUX_SYMBOL(__start_pci_fixups_early) = .; \
*(.pci_fixup_early) \
VMLINUX_SYMBOL(__end_pci_fixups_early) = .; \
VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \ VMLINUX_SYMBOL(__start_pci_fixups_header) = .; \
*(.pci_fixup_header) \ *(.pci_fixup_header) \
VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \ VMLINUX_SYMBOL(__end_pci_fixups_header) = .; \
......
...@@ -82,6 +82,11 @@ struct resource_list { ...@@ -82,6 +82,11 @@ struct resource_list {
#define IORESOURCE_MEM_SHADOWABLE (1<<5) /* dup: IORESOURCE_SHADOWABLE */ #define IORESOURCE_MEM_SHADOWABLE (1<<5) /* dup: IORESOURCE_SHADOWABLE */
#define IORESOURCE_MEM_EXPANSIONROM (1<<6) #define IORESOURCE_MEM_EXPANSIONROM (1<<6)
/* PCI ROM control bits (IORESOURCE_BITS) */
#define IORESOURCE_ROM_ENABLE (1<<0) /* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
#define IORESOURCE_ROM_SHADOW (1<<1) /* ROM is copy at C000:0 */
#define IORESOURCE_ROM_COPY (1<<2) /* ROM is alloc'd copy, resource field overlaid */
/* PC/ISA/whatever - the normal PC address spaces: IO and memory */ /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
extern struct resource ioport_resource; extern struct resource ioport_resource;
extern struct resource iomem_resource; extern struct resource iomem_resource;
......
/*
* File pci-acpi.h
*
* Copyright (C) 2004 Intel
* Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
*/
#ifndef _PCI_ACPI_H_
#define _PCI_ACPI_H_
#define OSC_QUERY_TYPE 0
#define OSC_SUPPORT_TYPE 1
#define OSC_CONTROL_TYPE 2
#define OSC_SUPPORT_MASKS 0x1f
/*
* _OSC DW0 Definition
*/
#define OSC_QUERY_ENABLE 1
#define OSC_REQUEST_ERROR 2
#define OSC_INVALID_UUID_ERROR 4
#define OSC_INVALID_REVISION_ERROR 8
#define OSC_CAPABILITIES_MASK_ERROR 16
/*
* _OSC DW1 Definition (OS Support Fields)
*/
#define OSC_EXT_PCI_CONFIG_SUPPORT 1
#define OSC_ACTIVE_STATE_PWR_SUPPORT 2
#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4
#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8
#define OSC_MSI_SUPPORT 16
/*
* _OSC DW1 Definition (OS Control Fields)
*/
#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1
#define OSC_SHPC_NATIVE_HP_CONTROL 2
#define OSC_PCI_EXPRESS_PME_CONTROL 4
#define OSC_PCI_EXPRESS_AER_CONTROL 8
#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16
#define OSC_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \
OSC_SHPC_NATIVE_HP_CONTROL | \
OSC_PCI_EXPRESS_PME_CONTROL | \
OSC_PCI_EXPRESS_AER_CONTROL | \
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL)
#ifdef CONFIG_ACPI
extern acpi_status pci_osc_control_set(u32 flags);
extern acpi_status pci_osc_support_set(u32 flags);
#else
#if !defined(acpi_status)
typedef u32 acpi_status;
#define AE_ERROR (acpi_status) (0x0001)
#endif
static inline acpi_status pci_osc_control_set(u32 flags) {return AE_ERROR;}
static inline acpi_status pci_osc_support_set(u32 flags) {return AE_ERROR;}
#endif
#endif /* _PCI_ACPI_H_ */
...@@ -537,6 +537,8 @@ struct pci_dev { ...@@ -537,6 +537,8 @@ struct pci_dev {
unsigned int is_busmaster:1; /* device is busmaster */ unsigned int is_busmaster:1; /* device is busmaster */
u32 saved_config_space[16]; /* config space saved at suspend time */ u32 saved_config_space[16]; /* config space saved at suspend time */
struct bin_attribute *rom_attr; /* attribute descriptor for sysfs ROM entry */
int rom_attr_enabled; /* has display of the rom attribute been enabled? */
#ifdef CONFIG_PCI_NAMES #ifdef CONFIG_PCI_NAMES
#define PCI_NAME_SIZE 96 #define PCI_NAME_SIZE 96
#define PCI_NAME_HALF __stringify(43) /* less than half to handle slop */ #define PCI_NAME_HALF __stringify(43) /* less than half to handle slop */
...@@ -785,6 +787,12 @@ int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask); ...@@ -785,6 +787,12 @@ int pci_dac_set_dma_mask(struct pci_dev *dev, u64 mask);
int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask); int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask);
int pci_assign_resource(struct pci_dev *dev, int i); int pci_assign_resource(struct pci_dev *dev, int i);
/* ROM control related routines */
void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size);
void __iomem *pci_map_rom_copy(struct pci_dev *pdev, size_t *size);
void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
void pci_remove_rom(struct pci_dev *pdev);
/* Power management related routines */ /* Power management related routines */
int pci_save_state(struct pci_dev *dev); int pci_save_state(struct pci_dev *dev);
int pci_restore_state(struct pci_dev *dev); int pci_restore_state(struct pci_dev *dev);
...@@ -989,31 +997,33 @@ static inline char *pci_name(struct pci_dev *pdev) ...@@ -989,31 +997,33 @@ static inline char *pci_name(struct pci_dev *pdev)
*/ */
struct pci_fixup { struct pci_fixup {
u16 vendor, device; /* You can use PCI_ANY_ID here of course */ u16 vendor, device; /* You can use PCI_ANY_ID here of course */
void (*hook)(struct pci_dev *dev); void (*hook)(struct pci_dev *dev);
}; };
enum pci_fixup_pass { enum pci_fixup_pass {
pci_fixup_header, /* Called immediately after reading configuration header */ pci_fixup_early, /* Before probing BARs */
pci_fixup_header, /* After reading configuration header */
pci_fixup_final, /* Final phase of device fixups */ pci_fixup_final, /* Final phase of device fixups */
pci_fixup_enable, /* pci_enable_device() time */ pci_fixup_enable, /* pci_enable_device() time */
}; };
/* Anonymous variables would be nice... */ /* Anonymous variables would be nice... */
#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook) \ #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook) \
static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \ static struct pci_fixup __pci_fixup_##name __attribute_used__ \
__attribute__((__section__(".pci_fixup_header"))) = { \ __attribute__((__section__(#section))) = { vendor, device, hook };
vendor, device, hook }; #define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook) \
DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early, \
#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook) \ vendor##device##hook, vendor, device, hook)
static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \ #define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook) \
__attribute__((__section__(".pci_fixup_final"))) = { \ DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header, \
vendor, device, hook }; vendor##device##hook, vendor, device, hook)
#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook) \
#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \ DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final, \
static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__ \ vendor##device##hook, vendor, device, hook)
__attribute__((__section__(".pci_fixup_enable"))) = { \ #define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook) \
vendor, device, hook }; DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable, \
vendor##device##hook, vendor, device, hook)
void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
......
...@@ -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