PCI: skip ISA ioresource alignment on some systems
Skip ISA ioresource alignment on some systems To conserve limited PCI i/o resource on some IBM multi-node systems, the BIOS allocates (via _CRS) and expects the kernel to use addresses in ranges currently excluded by pcibios_align_resource() [i386/pci/i386.c]. This change allows the kernel to use the currently excluded address ranges on the IBM x3800, x3850, and x3950. Signed-off-by: Gary Hade <gary.hade@us.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
8fa5913d54
commit
036fff4cf7
4 changed files with 58 additions and 2 deletions
|
@ -2,15 +2,57 @@
|
|||
#include <linux/acpi.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <asm/numa.h>
|
||||
#include "pci.h"
|
||||
|
||||
static int __devinit can_skip_ioresource_align(struct dmi_system_id *d)
|
||||
{
|
||||
pci_probe |= PCI_CAN_SKIP_ISA_ALIGN;
|
||||
printk(KERN_INFO "PCI: %s detected, can skip ISA alignment\n", d->ident);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dmi_system_id acpi_pciprobe_dmi_table[] = {
|
||||
/*
|
||||
* Systems where PCI IO resource ISA alignment can be skipped
|
||||
* when the ISA enable bit in the bridge control is not set
|
||||
*/
|
||||
{
|
||||
.callback = can_skip_ioresource_align,
|
||||
.ident = "IBM System x3800",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "x3800"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = can_skip_ioresource_align,
|
||||
.ident = "IBM System x3850",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "x3850"),
|
||||
},
|
||||
},
|
||||
{
|
||||
.callback = can_skip_ioresource_align,
|
||||
.ident = "IBM System x3950",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "IBM"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "x3950"),
|
||||
},
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum)
|
||||
{
|
||||
struct pci_bus *bus;
|
||||
struct pci_sysdata *sd;
|
||||
int pxm;
|
||||
|
||||
dmi_check_system(acpi_pciprobe_dmi_table);
|
||||
|
||||
/* Allocate per-root-bus (not per bus) arch-specific data.
|
||||
* TODO: leak; this memory is never freed.
|
||||
* It's arguable whether it's worth the trouble to care.
|
||||
|
|
|
@ -33,6 +33,15 @@
|
|||
|
||||
#include "pci.h"
|
||||
|
||||
static int
|
||||
skip_isa_ioresource_align(struct pci_dev *dev) {
|
||||
|
||||
if ((pci_probe & PCI_CAN_SKIP_ISA_ALIGN) &&
|
||||
(dev->bus->bridge_ctl & PCI_BRIDGE_CTL_NO_ISA))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to avoid collisions with `mirrored' VGA ports
|
||||
* and other strange ISA hardware, so we always want the
|
||||
|
@ -50,9 +59,13 @@ void
|
|||
pcibios_align_resource(void *data, struct resource *res,
|
||||
resource_size_t size, resource_size_t align)
|
||||
{
|
||||
struct pci_dev *dev = data;
|
||||
|
||||
if (res->flags & IORESOURCE_IO) {
|
||||
resource_size_t start = res->start;
|
||||
|
||||
if (skip_isa_ioresource_align(dev))
|
||||
return;
|
||||
if (start & 0x300) {
|
||||
start = (start + 0x3ff) & ~0x3ff;
|
||||
res->start = start;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define PCI_ASSIGN_ROMS 0x1000
|
||||
#define PCI_BIOS_IRQ_SCAN 0x2000
|
||||
#define PCI_ASSIGN_ALL_BUSSES 0x4000
|
||||
#define PCI_CAN_SKIP_ISA_ALIGN 0x8000
|
||||
|
||||
extern unsigned int pci_probe;
|
||||
extern unsigned long pirq_table_addr;
|
||||
|
|
|
@ -544,7 +544,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
|
|||
goto out;
|
||||
child->primary = buses & 0xFF;
|
||||
child->subordinate = (buses >> 16) & 0xFF;
|
||||
child->bridge_ctl = bctl;
|
||||
child->bridge_ctl = bctl ^ PCI_BRIDGE_CTL_NO_ISA;
|
||||
|
||||
cmax = pci_scan_child_bus(child);
|
||||
if (cmax > max)
|
||||
|
@ -597,7 +597,7 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass
|
|||
pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
|
||||
|
||||
if (!is_cardbus) {
|
||||
child->bridge_ctl = bctl | PCI_BRIDGE_CTL_NO_ISA;
|
||||
child->bridge_ctl = bctl ^ PCI_BRIDGE_CTL_NO_ISA;
|
||||
/*
|
||||
* Adjust subordinate busnr in parent buses.
|
||||
* We do this before scanning for children because
|
||||
|
|
Loading…
Reference in a new issue