Skip to content

Commit

Permalink
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
Browse files Browse the repository at this point in the history
  • Loading branch information
Linus Torvalds committed Jun 28, 2005
2 parents f340c0d + 8644d2a commit adb2705
Show file tree
Hide file tree
Showing 69 changed files with 1,492 additions and 1,833 deletions.
4 changes: 4 additions & 0 deletions Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,10 @@ running once the system is up.
irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned
automatically to PCI devices. You can make the kernel
exclude IRQs of your ISA cards this way.
pirqaddr=0xAAAAA [IA-32] Specify the physical address
of the PIRQ table (normally generated
by the BIOS) if it is outside the
F0000h-100000h range.
lastbus=N [IA-32] Scan all buses till bus #N. Can be useful
if the kernel is unable to find your secondary buses
and you want to tell it explicitly which ones they are.
Expand Down
57 changes: 49 additions & 8 deletions arch/i386/kernel/acpi/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,15 @@ char *__acpi_map_table(unsigned long phys, unsigned long size)
#endif

#ifdef CONFIG_PCI_MMCONFIG
static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
struct acpi_table_mcfg_config *pci_mmcfg_config;
int pci_mmcfg_config_num;

int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
{
struct acpi_table_mcfg *mcfg;
unsigned long i;
int config_size;

if (!phys_addr || !size)
return -EINVAL;
Expand All @@ -172,18 +178,38 @@ static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
return -ENODEV;
}

if (mcfg->base_reserved) {
printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");
/* how many config structures do we have */
pci_mmcfg_config_num = 0;
i = size - sizeof(struct acpi_table_mcfg);
while (i >= sizeof(struct acpi_table_mcfg_config)) {
++pci_mmcfg_config_num;
i -= sizeof(struct acpi_table_mcfg_config);
};
if (pci_mmcfg_config_num == 0) {
printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");
return -ENODEV;
}

pci_mmcfg_base_addr = mcfg->base_address;
config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);
pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);
if (!pci_mmcfg_config) {
printk(KERN_WARNING PREFIX
"No memory for MCFG config tables\n");
return -ENOMEM;
}

memcpy(pci_mmcfg_config, &mcfg->config, config_size);
for (i = 0; i < pci_mmcfg_config_num; ++i) {
if (mcfg->config[i].base_reserved) {
printk(KERN_ERR PREFIX
"MMCONFIG not in low 4GB of memory\n");
return -ENODEV;
}
}

return 0;
}
#else
#define acpi_parse_mcfg NULL
#endif /* !CONFIG_PCI_MMCONFIG */
#endif /* CONFIG_PCI_MMCONFIG */

#ifdef CONFIG_X86_LOCAL_APIC
static int __init
Expand Down Expand Up @@ -507,6 +533,22 @@ acpi_unmap_lsapic(int cpu)
EXPORT_SYMBOL(acpi_unmap_lsapic);
#endif /* CONFIG_ACPI_HOTPLUG_CPU */

int
acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)
{
/* TBD */
return -EINVAL;
}
EXPORT_SYMBOL(acpi_register_ioapic);

int
acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)
{
/* TBD */
return -EINVAL;
}
EXPORT_SYMBOL(acpi_unregister_ioapic);

static unsigned long __init
acpi_scan_rsdp (
unsigned long start,
Expand Down Expand Up @@ -1123,7 +1165,6 @@ int __init acpi_boot_init(void)
acpi_process_madt();

acpi_table_parse(ACPI_HPET, acpi_parse_hpet);
acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);

return 0;
}
Expand Down
8 changes: 6 additions & 2 deletions arch/i386/pci/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1 | PCI_PROBE_CONF2 |

int pci_routeirq;
int pcibios_last_bus = -1;
struct pci_bus *pci_root_bus = NULL;
unsigned long pirq_table_addr;
struct pci_bus *pci_root_bus;
struct pci_raw_ops *raw_pci_ops;

static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value)
Expand Down Expand Up @@ -133,7 +134,7 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum)

printk("PCI: Probing PCI hardware (bus %02x)\n", busnum);

return pci_scan_bus(busnum, &pci_root_ops, NULL);
return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, NULL);
}

extern u8 pci_cache_line_size;
Expand Down Expand Up @@ -188,6 +189,9 @@ char * __devinit pcibios_setup(char *str)
} else if (!strcmp(str, "biosirq")) {
pci_probe |= PCI_BIOS_IRQ_SCAN;
return NULL;
} else if (!strncmp(str, "pirqaddr=", 9)) {
pirq_table_addr = simple_strtoul(str+9, NULL, 0);
return NULL;
}
#endif
#ifdef CONFIG_PCI_DIRECT
Expand Down
51 changes: 37 additions & 14 deletions arch/i386/pci/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,35 @@ struct irq_router_handler {

int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;

/*
* Check passed address for the PCI IRQ Routing Table signature
* and perform checksum verification.
*/

static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
{
struct irq_routing_table *rt;
int i;
u8 sum;

rt = (struct irq_routing_table *) addr;
if (rt->signature != PIRQ_SIGNATURE ||
rt->version != PIRQ_VERSION ||
rt->size % 16 ||
rt->size < sizeof(struct irq_routing_table))
return NULL;
sum = 0;
for (i=0; i < rt->size; i++)
sum += addr[i];
if (!sum) {
DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
return rt;
}
return NULL;
}



/*
* Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
*/
Expand All @@ -65,23 +94,17 @@ static struct irq_routing_table * __init pirq_find_routing_table(void)
{
u8 *addr;
struct irq_routing_table *rt;
int i;
u8 sum;

if (pirq_table_addr) {
rt = pirq_check_routing_table((u8 *) __va(pirq_table_addr));
if (rt)
return rt;
printk(KERN_WARNING "PCI: PIRQ table NOT found at pirqaddr\n");
}
for(addr = (u8 *) __va(0xf0000); addr < (u8 *) __va(0x100000); addr += 16) {
rt = (struct irq_routing_table *) addr;
if (rt->signature != PIRQ_SIGNATURE ||
rt->version != PIRQ_VERSION ||
rt->size % 16 ||
rt->size < sizeof(struct irq_routing_table))
continue;
sum = 0;
for(i=0; i<rt->size; i++)
sum += addr[i];
if (!sum) {
DBG("PCI: Interrupt Routing Table found at 0x%p\n", rt);
rt = pirq_check_routing_table(addr);
if (rt)
return rt;
}
}
return NULL;
}
Expand Down
2 changes: 2 additions & 0 deletions arch/i386/pci/legacy.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ static int __init pci_legacy_init(void)

printk("PCI: Probing PCI hardware\n");
pci_root_bus = pcibios_scan_root(0);
if (pci_root_bus)
pci_bus_add_devices(pci_root_bus);

pcibios_fixup_peer_bridges();

Expand Down
39 changes: 31 additions & 8 deletions arch/i386/pci/mmconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@

#include <linux/pci.h>
#include <linux/init.h>
#include <linux/acpi.h>
#include "pci.h"

/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
u32 pci_mmcfg_base_addr;

#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))

/* The base address of the last MMCONFIG device accessed */
Expand All @@ -24,10 +22,31 @@ static u32 mmcfg_last_accessed_device;
/*
* Functions for accessing PCI configuration space with MMCONFIG accesses
*/
static u32 get_base_addr(unsigned int seg, int bus)
{
int cfg_num = -1;
struct acpi_table_mcfg_config *cfg;

while (1) {
++cfg_num;
if (cfg_num >= pci_mmcfg_config_num) {
/* something bad is going on, no cfg table is found. */
/* so we fall back to the old way we used to do this */
/* and just rely on the first entry to be correct. */
return pci_mmcfg_config[0].base_address;
}
cfg = &pci_mmcfg_config[cfg_num];
if (cfg->pci_segment_group_number != seg)
continue;
if ((cfg->start_bus_number <= bus) &&
(cfg->end_bus_number >= bus))
return cfg->base_address;
}
}

static inline void pci_exp_set_dev_base(int bus, int devfn)
static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn)
{
u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12);
if (dev_base != mmcfg_last_accessed_device) {
mmcfg_last_accessed_device = dev_base;
set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);
Expand All @@ -44,7 +63,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,

spin_lock_irqsave(&pci_config_lock, flags);

pci_exp_set_dev_base(bus, devfn);
pci_exp_set_dev_base(seg, bus, devfn);

switch (len) {
case 1:
Expand Down Expand Up @@ -73,7 +92,7 @@ static int pci_mmcfg_write(unsigned int seg, unsigned int bus,

spin_lock_irqsave(&pci_config_lock, flags);

pci_exp_set_dev_base(bus, devfn);
pci_exp_set_dev_base(seg, bus, devfn);

switch (len) {
case 1:
Expand Down Expand Up @@ -101,7 +120,11 @@ static int __init pci_mmcfg_init(void)
{
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
goto out;
if (!pci_mmcfg_base_addr)

acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);
if ((pci_mmcfg_config_num == 0) ||
(pci_mmcfg_config == NULL) ||
(pci_mmcfg_config[0].base_address == 0))
goto out;

/* Kludge for now. Don't use mmconfig on AMD systems because
Expand Down
2 changes: 2 additions & 0 deletions arch/i386/pci/numa.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ static int __init pci_numa_init(void)
return 0;

pci_root_bus = pcibios_scan_root(0);
if (pci_root_bus)
pci_bus_add_devices(pci_root_bus);
if (num_online_nodes() > 1)
for_each_online_node(quad) {
if (quad == 0)
Expand Down
1 change: 1 addition & 0 deletions arch/i386/pci/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define PCI_ASSIGN_ALL_BUSSES 0x4000

extern unsigned int pci_probe;
extern unsigned long pirq_table_addr;

/* pci-i386.c */

Expand Down
30 changes: 26 additions & 4 deletions arch/ia64/kernel/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,9 +236,7 @@ acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
if (BAD_MADT_ENTRY(iosapic, end))
return -EINVAL;

iosapic_init(iosapic->address, iosapic->global_irq_base);

return 0;
return iosapic_init(iosapic->address, iosapic->global_irq_base);
}


Expand Down Expand Up @@ -772,7 +770,7 @@ EXPORT_SYMBOL(acpi_unmap_lsapic);


#ifdef CONFIG_ACPI_NUMA
acpi_status __init
acpi_status __devinit
acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
{
struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
Expand Down Expand Up @@ -825,4 +823,28 @@ acpi_map_iosapic (acpi_handle handle, u32 depth, void *context, void **ret)
return AE_OK;
}
#endif /* CONFIG_NUMA */

int
acpi_register_ioapic (acpi_handle handle, u64 phys_addr, u32 gsi_base)
{
int err;

if ((err = iosapic_init(phys_addr, gsi_base)))
return err;

#if CONFIG_ACPI_NUMA
acpi_map_iosapic(handle, 0, NULL, NULL);
#endif /* CONFIG_ACPI_NUMA */

return 0;
}
EXPORT_SYMBOL(acpi_register_ioapic);

int
acpi_unregister_ioapic (acpi_handle handle, u32 gsi_base)
{
return iosapic_remove(gsi_base);
}
EXPORT_SYMBOL(acpi_unregister_ioapic);

#endif /* CONFIG_ACPI_BOOT */
Loading

0 comments on commit adb2705

Please sign in to comment.