You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
@@ -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
|
||||
|
||||
+37
-14
@@ -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.
|
||||
*/
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -24,10 +22,31 @@ static u32 mmcfg_last_accessed_device;
|
||||
/*
|
||||
* Functions for accessing PCI configuration space with MMCONFIG accesses
|
||||
*/
|
||||
|
||||
static inline void pci_exp_set_dev_base(int bus, int devfn)
|
||||
static u32 get_base_addr(unsigned int seg, int bus)
|
||||
{
|
||||
u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);
|
||||
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(unsigned int seg, int bus, int devfn)
|
||||
{
|
||||
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);
|
||||
@@ -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:
|
||||
@@ -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:
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#define PCI_ASSIGN_ALL_BUSSES 0x4000
|
||||
|
||||
extern unsigned int pci_probe;
|
||||
extern unsigned long pirq_table_addr;
|
||||
|
||||
/* pci-i386.c */
|
||||
|
||||
|
||||
+26
-4
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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};
|
||||
@@ -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 */
|
||||
|
||||
+113
-21
@@ -129,14 +129,13 @@ static struct iosapic {
|
||||
char __iomem *addr; /* base address of IOSAPIC */
|
||||
unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */
|
||||
unsigned short num_rte; /* number of RTE in this IOSAPIC */
|
||||
int rtes_inuse; /* # of RTEs in use on this IOSAPIC */
|
||||
#ifdef CONFIG_NUMA
|
||||
unsigned short node; /* numa node association via pxm */
|
||||
#endif
|
||||
} iosapic_lists[NR_IOSAPICS];
|
||||
|
||||
static int num_iosapic;
|
||||
|
||||
static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */
|
||||
static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */
|
||||
|
||||
static int iosapic_kmalloc_ok;
|
||||
static LIST_HEAD(free_rte_list);
|
||||
@@ -149,7 +148,7 @@ find_iosapic (unsigned int gsi)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_iosapic; i++) {
|
||||
for (i = 0; i < NR_IOSAPICS; i++) {
|
||||
if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)
|
||||
return i;
|
||||
}
|
||||
@@ -598,6 +597,7 @@ register_intr (unsigned int gsi, int vector, unsigned char delivery,
|
||||
rte->refcnt++;
|
||||
list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes);
|
||||
iosapic_intr_info[vector].count++;
|
||||
iosapic_lists[index].rtes_inuse++;
|
||||
}
|
||||
else if (vector_is_shared(vector)) {
|
||||
struct iosapic_intr_info *info = &iosapic_intr_info[vector];
|
||||
@@ -778,7 +778,7 @@ void
|
||||
iosapic_unregister_intr (unsigned int gsi)
|
||||
{
|
||||
unsigned long flags;
|
||||
int irq, vector;
|
||||
int irq, vector, index;
|
||||
irq_desc_t *idesc;
|
||||
u32 low32;
|
||||
unsigned long trigger, polarity;
|
||||
@@ -819,6 +819,9 @@ iosapic_unregister_intr (unsigned int gsi)
|
||||
list_del(&rte->rte_list);
|
||||
iosapic_intr_info[vector].count--;
|
||||
iosapic_free_rte(rte);
|
||||
index = find_iosapic(gsi);
|
||||
iosapic_lists[index].rtes_inuse--;
|
||||
WARN_ON(iosapic_lists[index].rtes_inuse < 0);
|
||||
|
||||
trigger = iosapic_intr_info[vector].trigger;
|
||||
polarity = iosapic_intr_info[vector].polarity;
|
||||
@@ -952,30 +955,86 @@ iosapic_system_init (int system_pcat_compat)
|
||||
}
|
||||
}
|
||||
|
||||
void __init
|
||||
static inline int
|
||||
iosapic_alloc (void)
|
||||
{
|
||||
int index;
|
||||
|
||||
for (index = 0; index < NR_IOSAPICS; index++)
|
||||
if (!iosapic_lists[index].addr)
|
||||
return index;
|
||||
|
||||
printk(KERN_WARNING "%s: failed to allocate iosapic\n", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
iosapic_free (int index)
|
||||
{
|
||||
memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));
|
||||
}
|
||||
|
||||
static inline int
|
||||
iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)
|
||||
{
|
||||
int index;
|
||||
unsigned int gsi_end, base, end;
|
||||
|
||||
/* check gsi range */
|
||||
gsi_end = gsi_base + ((ver >> 16) & 0xff);
|
||||
for (index = 0; index < NR_IOSAPICS; index++) {
|
||||
if (!iosapic_lists[index].addr)
|
||||
continue;
|
||||
|
||||
base = iosapic_lists[index].gsi_base;
|
||||
end = base + iosapic_lists[index].num_rte - 1;
|
||||
|
||||
if (gsi_base < base && gsi_end < base)
|
||||
continue;/* OK */
|
||||
|
||||
if (gsi_base > end && gsi_end > end)
|
||||
continue; /* OK */
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __devinit
|
||||
iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
|
||||
{
|
||||
int num_rte;
|
||||
int num_rte, err, index;
|
||||
unsigned int isa_irq, ver;
|
||||
char __iomem *addr;
|
||||
unsigned long flags;
|
||||
|
||||
addr = ioremap(phys_addr, 0);
|
||||
ver = iosapic_version(addr);
|
||||
spin_lock_irqsave(&iosapic_lock, flags);
|
||||
{
|
||||
addr = ioremap(phys_addr, 0);
|
||||
ver = iosapic_version(addr);
|
||||
|
||||
/*
|
||||
* The MAX_REDIR register holds the highest input pin
|
||||
* number (starting from 0).
|
||||
* We add 1 so that we can use it for number of pins (= RTEs)
|
||||
*/
|
||||
num_rte = ((ver >> 16) & 0xff) + 1;
|
||||
if ((err = iosapic_check_gsi_range(gsi_base, ver))) {
|
||||
iounmap(addr);
|
||||
spin_unlock_irqrestore(&iosapic_lock, flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
iosapic_lists[num_iosapic].addr = addr;
|
||||
iosapic_lists[num_iosapic].gsi_base = gsi_base;
|
||||
iosapic_lists[num_iosapic].num_rte = num_rte;
|
||||
/*
|
||||
* The MAX_REDIR register holds the highest input pin
|
||||
* number (starting from 0).
|
||||
* We add 1 so that we can use it for number of pins (= RTEs)
|
||||
*/
|
||||
num_rte = ((ver >> 16) & 0xff) + 1;
|
||||
|
||||
index = iosapic_alloc();
|
||||
iosapic_lists[index].addr = addr;
|
||||
iosapic_lists[index].gsi_base = gsi_base;
|
||||
iosapic_lists[index].num_rte = num_rte;
|
||||
#ifdef CONFIG_NUMA
|
||||
iosapic_lists[num_iosapic].node = MAX_NUMNODES;
|
||||
iosapic_lists[index].node = MAX_NUMNODES;
|
||||
#endif
|
||||
num_iosapic++;
|
||||
}
|
||||
spin_unlock_irqrestore(&iosapic_lock, flags);
|
||||
|
||||
if ((gsi_base == 0) && pcat_compat) {
|
||||
/*
|
||||
@@ -986,10 +1045,43 @@ iosapic_init (unsigned long phys_addr, unsigned int gsi_base)
|
||||
for (isa_irq = 0; isa_irq < 16; ++isa_irq)
|
||||
iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
int
|
||||
iosapic_remove (unsigned int gsi_base)
|
||||
{
|
||||
int index, err = 0;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&iosapic_lock, flags);
|
||||
{
|
||||
index = find_iosapic(gsi_base);
|
||||
if (index < 0) {
|
||||
printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",
|
||||
__FUNCTION__, gsi_base);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (iosapic_lists[index].rtes_inuse) {
|
||||
err = -EBUSY;
|
||||
printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",
|
||||
__FUNCTION__, gsi_base);
|
||||
goto out;
|
||||
}
|
||||
|
||||
iounmap(iosapic_lists[index].addr);
|
||||
iosapic_free(index);
|
||||
}
|
||||
out:
|
||||
spin_unlock_irqrestore(&iosapic_lock, flags);
|
||||
return err;
|
||||
}
|
||||
#endif /* CONFIG_HOTPLUG */
|
||||
|
||||
#ifdef CONFIG_NUMA
|
||||
void __init
|
||||
void __devinit
|
||||
map_iosapic_to_node(unsigned int gsi_base, int node)
|
||||
{
|
||||
int index;
|
||||
|
||||
+33
-5
@@ -312,7 +312,7 @@ pci_acpi_scan_root(struct acpi_device *device, int domain, int bus)
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,
|
||||
&info);
|
||||
|
||||
pbus = pci_scan_bus(bus, &pci_root_ops, controller);
|
||||
pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller);
|
||||
if (pbus)
|
||||
pcibios_setup_root_windows(pbus, controller);
|
||||
|
||||
@@ -373,6 +373,25 @@ void pcibios_bus_to_resource(struct pci_dev *dev,
|
||||
res->end = region->end + offset;
|
||||
}
|
||||
|
||||
static int __devinit is_valid_resource(struct pci_dev *dev, int idx)
|
||||
{
|
||||
unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;
|
||||
struct resource *devr = &dev->resource[idx];
|
||||
|
||||
if (!dev->bus)
|
||||
return 0;
|
||||
for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) {
|
||||
struct resource *busr = dev->bus->resource[i];
|
||||
|
||||
if (!busr || ((busr->flags ^ devr->flags) & type_mask))
|
||||
continue;
|
||||
if ((devr->start) && (devr->start >= busr->start) &&
|
||||
(devr->end <= busr->end))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
|
||||
{
|
||||
struct pci_bus_region region;
|
||||
@@ -386,7 +405,8 @@ static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
|
||||
region.start = dev->resource[i].start;
|
||||
region.end = dev->resource[i].end;
|
||||
pcibios_bus_to_resource(dev, &dev->resource[i], ®ion);
|
||||
pci_claim_resource(dev, i);
|
||||
if ((is_valid_resource(dev, i)))
|
||||
pci_claim_resource(dev, i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,6 +418,10 @@ pcibios_fixup_bus (struct pci_bus *b)
|
||||
{
|
||||
struct pci_dev *dev;
|
||||
|
||||
if (b->self) {
|
||||
pci_read_bridge_bases(b);
|
||||
pcibios_fixup_device_resources(b->self);
|
||||
}
|
||||
list_for_each_entry(dev, &b->devices, bus_list)
|
||||
pcibios_fixup_device_resources(dev);
|
||||
|
||||
@@ -418,18 +442,24 @@ pcibios_enable_resources (struct pci_dev *dev, int mask)
|
||||
u16 cmd, old_cmd;
|
||||
int idx;
|
||||
struct resource *r;
|
||||
unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
|
||||
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||
old_cmd = cmd;
|
||||
for (idx=0; idx<6; idx++) {
|
||||
for (idx=0; idx<PCI_NUM_RESOURCES; idx++) {
|
||||
/* Only set up the desired resources. */
|
||||
if (!(mask & (1 << idx)))
|
||||
continue;
|
||||
|
||||
r = &dev->resource[idx];
|
||||
if (!(r->flags & type_mask))
|
||||
continue;
|
||||
if ((idx == PCI_ROM_RESOURCE) &&
|
||||
(!(r->flags & IORESOURCE_ROM_ENABLE)))
|
||||
continue;
|
||||
if (!r->start && r->end) {
|
||||
printk(KERN_ERR
|
||||
"PCI: Device %s not available because of resource collisions\n",
|
||||
@@ -441,8 +471,6 @@ pcibios_enable_resources (struct pci_dev *dev, int mask)
|
||||
if (r->flags & IORESOURCE_MEM)
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
if (dev->resource[PCI_ROM_RESOURCE].start)
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
if (cmd != old_cmd) {
|
||||
printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);
|
||||
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
||||
|
||||
+19
-2
@@ -1495,7 +1495,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
|
||||
*offset += hose->pci_mem_offset;
|
||||
res_bit = IORESOURCE_MEM;
|
||||
} else {
|
||||
io_offset = (unsigned long)hose->io_base_virt;
|
||||
io_offset = hose->io_base_virt - ___IO_BASE;
|
||||
*offset += io_offset;
|
||||
res_bit = IORESOURCE_IO;
|
||||
}
|
||||
@@ -1522,7 +1522,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
|
||||
|
||||
/* found it! construct the final physical address */
|
||||
if (mmap_state == pci_mmap_io)
|
||||
*offset += hose->io_base_phys - _IO_BASE;
|
||||
*offset += hose->io_base_phys - io_offset;
|
||||
return rp;
|
||||
}
|
||||
|
||||
@@ -1739,6 +1739,23 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
|
||||
return result;
|
||||
}
|
||||
|
||||
void pci_resource_to_user(const struct pci_dev *dev, int bar,
|
||||
const struct resource *rsrc,
|
||||
u64 *start, u64 *end)
|
||||
{
|
||||
struct pci_controller *hose = pci_bus_to_hose(dev->bus->number);
|
||||
unsigned long offset = 0;
|
||||
|
||||
if (hose == NULL)
|
||||
return;
|
||||
|
||||
if (rsrc->flags & IORESOURCE_IO)
|
||||
offset = ___IO_BASE - hose->io_base_virt + hose->io_base_phys;
|
||||
|
||||
*start = rsrc->start + offset;
|
||||
*end = rsrc->end + offset;
|
||||
}
|
||||
|
||||
void __init
|
||||
pci_init_resource(struct resource *res, unsigned long start, unsigned long end,
|
||||
int flags, char *name)
|
||||
|
||||
+20
-2
@@ -351,7 +351,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
|
||||
*offset += hose->pci_mem_offset;
|
||||
res_bit = IORESOURCE_MEM;
|
||||
} else {
|
||||
io_offset = (unsigned long)hose->io_base_virt;
|
||||
io_offset = (unsigned long)hose->io_base_virt - pci_io_base;
|
||||
*offset += io_offset;
|
||||
res_bit = IORESOURCE_IO;
|
||||
}
|
||||
@@ -378,7 +378,7 @@ static struct resource *__pci_mmap_make_offset(struct pci_dev *dev,
|
||||
|
||||
/* found it! construct the final physical address */
|
||||
if (mmap_state == pci_mmap_io)
|
||||
*offset += hose->io_base_phys - io_offset;
|
||||
*offset += hose->io_base_phys - io_offset;
|
||||
return rp;
|
||||
}
|
||||
|
||||
@@ -944,4 +944,22 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
|
||||
}
|
||||
EXPORT_SYMBOL(pci_read_irq_line);
|
||||
|
||||
void pci_resource_to_user(const struct pci_dev *dev, int bar,
|
||||
const struct resource *rsrc,
|
||||
u64 *start, u64 *end)
|
||||
{
|
||||
struct pci_controller *hose = pci_bus_to_host(dev->bus);
|
||||
unsigned long offset = 0;
|
||||
|
||||
if (hose == NULL)
|
||||
return;
|
||||
|
||||
if (rsrc->flags & IORESOURCE_IO)
|
||||
offset = pci_io_base - (unsigned long)hose->io_base_virt +
|
||||
hose->io_base_phys;
|
||||
|
||||
*start = rsrc->start + offset;
|
||||
*end = rsrc->end + offset;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PPC_MULTIPLATFORM */
|
||||
|
||||
+53
-13
@@ -7,25 +7,50 @@
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/acpi.h>
|
||||
#include "pci.h"
|
||||
|
||||
#define MMCONFIG_APER_SIZE (256*1024*1024)
|
||||
|
||||
/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */
|
||||
u32 pci_mmcfg_base_addr;
|
||||
|
||||
/* Static virtual mapping of the MMCONFIG aperture */
|
||||
char *pci_mmcfg_virt;
|
||||
struct mmcfg_virt {
|
||||
struct acpi_table_mcfg_config *cfg;
|
||||
char *virt;
|
||||
};
|
||||
static struct mmcfg_virt *pci_mmcfg_virt;
|
||||
|
||||
static inline char *pci_dev_base(unsigned int bus, unsigned int devfn)
|
||||
static char *get_virt(unsigned int seg, int bus)
|
||||
{
|
||||
return pci_mmcfg_virt + ((bus << 20) | (devfn << 12));
|
||||
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_virt[0].virt;
|
||||
}
|
||||
cfg = pci_mmcfg_virt[cfg_num].cfg;
|
||||
if (cfg->pci_segment_group_number != seg)
|
||||
continue;
|
||||
if ((cfg->start_bus_number <= bus) &&
|
||||
(cfg->end_bus_number >= bus))
|
||||
return pci_mmcfg_virt[cfg_num].virt;
|
||||
}
|
||||
}
|
||||
|
||||
static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)
|
||||
{
|
||||
|
||||
return get_virt(seg, bus) + ((bus << 20) | (devfn << 12));
|
||||
}
|
||||
|
||||
static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
|
||||
unsigned int devfn, int reg, int len, u32 *value)
|
||||
{
|
||||
char *addr = pci_dev_base(bus, devfn);
|
||||
char *addr = pci_dev_base(seg, bus, devfn);
|
||||
|
||||
if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))
|
||||
return -EINVAL;
|
||||
@@ -48,7 +73,7 @@ static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
|
||||
static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
|
||||
unsigned int devfn, int reg, int len, u32 value)
|
||||
{
|
||||
char *addr = pci_dev_base(bus,devfn);
|
||||
char *addr = pci_dev_base(seg, bus, devfn);
|
||||
|
||||
if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))
|
||||
return -EINVAL;
|
||||
@@ -75,9 +100,15 @@ static struct pci_raw_ops pci_mmcfg = {
|
||||
|
||||
static int __init pci_mmcfg_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((pci_probe & PCI_PROBE_MMCONF) == 0)
|
||||
return 0;
|
||||
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))
|
||||
return 0;
|
||||
|
||||
/* Kludge for now. Don't use mmconfig on AMD systems because
|
||||
@@ -88,13 +119,22 @@ static int __init pci_mmcfg_init(void)
|
||||
return 0;
|
||||
|
||||
/* RED-PEN i386 doesn't do _nocache right now */
|
||||
pci_mmcfg_virt = ioremap_nocache(pci_mmcfg_base_addr, MMCONFIG_APER_SIZE);
|
||||
if (!pci_mmcfg_virt) {
|
||||
printk("PCI: Cannot map mmconfig aperture\n");
|
||||
pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);
|
||||
if (pci_mmcfg_virt == NULL) {
|
||||
printk("PCI: Can not allocate memory for mmconfig structures\n");
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < pci_mmcfg_config_num; ++i) {
|
||||
pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];
|
||||
pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);
|
||||
if (!pci_mmcfg_virt[i].virt) {
|
||||
printk("PCI: Cannot map mmconfig aperture for segment %d\n",
|
||||
pci_mmcfg_config[i].pci_segment_group_number);
|
||||
return 0;
|
||||
}
|
||||
printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address);
|
||||
}
|
||||
|
||||
printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_base_addr);
|
||||
raw_pci_ops = &pci_mmcfg;
|
||||
pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;
|
||||
|
||||
|
||||
@@ -153,7 +153,7 @@ container_device_add(struct acpi_device **device, acpi_handle handle)
|
||||
return_VALUE(-ENODEV);
|
||||
}
|
||||
|
||||
result = acpi_bus_scan(*device);
|
||||
result = acpi_bus_start(*device);
|
||||
|
||||
return_VALUE(result);
|
||||
}
|
||||
|
||||
+20
-7
@@ -61,15 +61,14 @@ acpi_pci_data_handler (
|
||||
|
||||
|
||||
/**
|
||||
* acpi_os_get_pci_id
|
||||
* acpi_get_pci_id
|
||||
* ------------------
|
||||
* This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)
|
||||
* to resolve PCI information for ACPI-PCI devices defined in the namespace.
|
||||
* This typically occurs when resolving PCI operation region information.
|
||||
*/
|
||||
#ifdef ACPI_FUTURE_USAGE
|
||||
acpi_status
|
||||
acpi_os_get_pci_id (
|
||||
acpi_get_pci_id (
|
||||
acpi_handle handle,
|
||||
struct acpi_pci_id *id)
|
||||
{
|
||||
@@ -78,7 +77,7 @@ acpi_os_get_pci_id (
|
||||
struct acpi_device *device = NULL;
|
||||
struct acpi_pci_data *data = NULL;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_os_get_pci_id");
|
||||
ACPI_FUNCTION_TRACE("acpi_get_pci_id");
|
||||
|
||||
if (!id)
|
||||
return_ACPI_STATUS(AE_BAD_PARAMETER);
|
||||
@@ -92,7 +91,7 @@ acpi_os_get_pci_id (
|
||||
}
|
||||
|
||||
status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);
|
||||
if (ACPI_FAILURE(status) || !data || !data->dev) {
|
||||
if (ACPI_FAILURE(status) || !data) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
|
||||
"Invalid ACPI-PCI context for device %s\n",
|
||||
acpi_device_bid(device)));
|
||||
@@ -115,7 +114,7 @@ acpi_os_get_pci_id (
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
}
|
||||
#endif /* ACPI_FUTURE_USAGE */
|
||||
EXPORT_SYMBOL(acpi_get_pci_id);
|
||||
|
||||
|
||||
int
|
||||
@@ -129,6 +128,8 @@ acpi_pci_bind (
|
||||
char *pathname = NULL;
|
||||
struct acpi_buffer buffer = {0, NULL};
|
||||
acpi_handle handle = NULL;
|
||||
struct pci_dev *dev;
|
||||
struct pci_bus *bus;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_pci_bind");
|
||||
|
||||
@@ -193,8 +194,20 @@ acpi_pci_bind (
|
||||
* Locate matching device in PCI namespace. If it doesn't exist
|
||||
* this typically means that the device isn't currently inserted
|
||||
* (e.g. docking station, port replicator, etc.).
|
||||
* We cannot simply search the global pci device list, since
|
||||
* PCI devices are added to the global pci list when the root
|
||||
* bridge start ops are run, which may not have happened yet.
|
||||
*/
|
||||
data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function));
|
||||
bus = pci_find_bus(data->id.segment, data->id.bus);
|
||||
if (bus) {
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
if (dev->devfn == PCI_DEVFN(data->id.device,
|
||||
data->id.function)) {
|
||||
data->dev = dev;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!data->dev) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
|
||||
|
||||
+23
-1
@@ -46,6 +46,7 @@ ACPI_MODULE_NAME ("pci_root")
|
||||
|
||||
static int acpi_pci_root_add (struct acpi_device *device);
|
||||
static int acpi_pci_root_remove (struct acpi_device *device, int type);
|
||||
static int acpi_pci_root_start (struct acpi_device *device);
|
||||
|
||||
static struct acpi_driver acpi_pci_root_driver = {
|
||||
.name = ACPI_PCI_ROOT_DRIVER_NAME,
|
||||
@@ -54,6 +55,7 @@ static struct acpi_driver acpi_pci_root_driver = {
|
||||
.ops = {
|
||||
.add = acpi_pci_root_add,
|
||||
.remove = acpi_pci_root_remove,
|
||||
.start = acpi_pci_root_start,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -169,6 +171,7 @@ acpi_pci_root_add (
|
||||
if (!root)
|
||||
return_VALUE(-ENOMEM);
|
||||
memset(root, 0, sizeof(struct acpi_pci_root));
|
||||
INIT_LIST_HEAD(&root->node);
|
||||
|
||||
root->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);
|
||||
@@ -298,12 +301,31 @@ acpi_pci_root_add (
|
||||
root->id.bus);
|
||||
|
||||
end:
|
||||
if (result)
|
||||
if (result) {
|
||||
if (!list_empty(&root->node))
|
||||
list_del(&root->node);
|
||||
kfree(root);
|
||||
}
|
||||
|
||||
return_VALUE(result);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_pci_root_start (
|
||||
struct acpi_device *device)
|
||||
{
|
||||
struct acpi_pci_root *root;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_pci_root_start");
|
||||
|
||||
list_for_each_entry(root, &acpi_pci_roots, node) {
|
||||
if (root->handle == device->handle) {
|
||||
pci_bus_add_devices(root->bus);
|
||||
return_VALUE(0);
|
||||
}
|
||||
}
|
||||
return_VALUE(-ENODEV);
|
||||
}
|
||||
|
||||
static int
|
||||
acpi_pci_root_remove (
|
||||
|
||||
@@ -723,7 +723,7 @@ int acpi_processor_device_add(
|
||||
return_VALUE(-ENODEV);
|
||||
}
|
||||
|
||||
acpi_bus_scan(*device);
|
||||
acpi_bus_start(*device);
|
||||
|
||||
pr = acpi_driver_data(*device);
|
||||
if (!pr)
|
||||
|
||||
+101
-25
@@ -553,20 +553,29 @@ acpi_bus_driver_init (
|
||||
* upon possible configuration and currently allocated resources.
|
||||
*/
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
|
||||
return_VALUE(0);
|
||||
}
|
||||
|
||||
int
|
||||
acpi_start_single_object (
|
||||
struct acpi_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
struct acpi_driver *driver;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_start_single_object");
|
||||
|
||||
if (!(driver = device->driver))
|
||||
return_VALUE(0);
|
||||
|
||||
if (driver->ops.start) {
|
||||
result = driver->ops.start(device);
|
||||
if (result && driver->ops.remove)
|
||||
driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);
|
||||
return_VALUE(result);
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));
|
||||
|
||||
if (driver->ops.scan) {
|
||||
driver->ops.scan(device);
|
||||
}
|
||||
|
||||
return_VALUE(0);
|
||||
return_VALUE(result);
|
||||
}
|
||||
|
||||
static int acpi_driver_attach(struct acpi_driver * drv)
|
||||
@@ -586,6 +595,7 @@ static int acpi_driver_attach(struct acpi_driver * drv)
|
||||
|
||||
if (!acpi_bus_match(dev, drv)) {
|
||||
if (!acpi_bus_driver_init(dev, drv)) {
|
||||
acpi_start_single_object(dev);
|
||||
atomic_inc(&drv->references);
|
||||
count++;
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",
|
||||
@@ -1009,8 +1019,8 @@ acpi_bus_remove (
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
acpi_bus_add (
|
||||
static int
|
||||
acpi_add_single_object (
|
||||
struct acpi_device **child,
|
||||
struct acpi_device *parent,
|
||||
acpi_handle handle,
|
||||
@@ -1019,7 +1029,7 @@ acpi_bus_add (
|
||||
int result = 0;
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_bus_add");
|
||||
ACPI_FUNCTION_TRACE("acpi_add_single_object");
|
||||
|
||||
if (!child)
|
||||
return_VALUE(-EINVAL);
|
||||
@@ -1140,7 +1150,7 @@ acpi_bus_add (
|
||||
*
|
||||
* TBD: Assumes LDM provides driver hot-plug capability.
|
||||
*/
|
||||
acpi_bus_find_driver(device);
|
||||
result = acpi_bus_find_driver(device);
|
||||
|
||||
end:
|
||||
if (!result)
|
||||
@@ -1153,10 +1163,10 @@ end:
|
||||
|
||||
return_VALUE(result);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_add);
|
||||
|
||||
|
||||
int acpi_bus_scan (struct acpi_device *start)
|
||||
static int acpi_bus_scan (struct acpi_device *start,
|
||||
struct acpi_bus_ops *ops)
|
||||
{
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_device *parent = NULL;
|
||||
@@ -1229,9 +1239,20 @@ int acpi_bus_scan (struct acpi_device *start)
|
||||
continue;
|
||||
}
|
||||
|
||||
status = acpi_bus_add(&child, parent, chandle, type);
|
||||
if (ACPI_FAILURE(status))
|
||||
continue;
|
||||
if (ops->acpi_op_add)
|
||||
status = acpi_add_single_object(&child, parent,
|
||||
chandle, type);
|
||||
else
|
||||
status = acpi_bus_get_device(chandle, &child);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
continue;
|
||||
|
||||
if (ops->acpi_op_start) {
|
||||
status = acpi_start_single_object(child);
|
||||
if (ACPI_FAILURE(status))
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device is present, enabled, and functioning then
|
||||
@@ -1257,8 +1278,50 @@ int acpi_bus_scan (struct acpi_device *start)
|
||||
|
||||
return_VALUE(0);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_scan);
|
||||
|
||||
int
|
||||
acpi_bus_add (
|
||||
struct acpi_device **child,
|
||||
struct acpi_device *parent,
|
||||
acpi_handle handle,
|
||||
int type)
|
||||
{
|
||||
int result;
|
||||
struct acpi_bus_ops ops;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_bus_add");
|
||||
|
||||
result = acpi_add_single_object(child, parent, handle, type);
|
||||
if (!result) {
|
||||
memset(&ops, 0, sizeof(ops));
|
||||
ops.acpi_op_add = 1;
|
||||
result = acpi_bus_scan(*child, &ops);
|
||||
}
|
||||
return_VALUE(result);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_add);
|
||||
|
||||
int
|
||||
acpi_bus_start (
|
||||
struct acpi_device *device)
|
||||
{
|
||||
int result;
|
||||
struct acpi_bus_ops ops;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_bus_start");
|
||||
|
||||
if (!device)
|
||||
return_VALUE(-EINVAL);
|
||||
|
||||
result = acpi_start_single_object(device);
|
||||
if (!result) {
|
||||
memset(&ops, 0, sizeof(ops));
|
||||
ops.acpi_op_start = 1;
|
||||
result = acpi_bus_scan(device, &ops);
|
||||
}
|
||||
return_VALUE(result);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_bus_start);
|
||||
|
||||
static int
|
||||
acpi_bus_trim(struct acpi_device *start,
|
||||
@@ -1331,13 +1394,19 @@ acpi_bus_scan_fixed (
|
||||
/*
|
||||
* Enumerate all fixed-feature devices.
|
||||
*/
|
||||
if (acpi_fadt.pwr_button == 0)
|
||||
result = acpi_bus_add(&device, acpi_root,
|
||||
if (acpi_fadt.pwr_button == 0) {
|
||||
result = acpi_add_single_object(&device, acpi_root,
|
||||
NULL, ACPI_BUS_TYPE_POWER_BUTTON);
|
||||
if (!result)
|
||||
result = acpi_start_single_object(device);
|
||||
}
|
||||
|
||||
if (acpi_fadt.sleep_button == 0)
|
||||
result = acpi_bus_add(&device, acpi_root,
|
||||
if (acpi_fadt.sleep_button == 0) {
|
||||
result = acpi_add_single_object(&device, acpi_root,
|
||||
NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
|
||||
if (!result)
|
||||
result = acpi_start_single_object(device);
|
||||
}
|
||||
|
||||
return_VALUE(result);
|
||||
}
|
||||
@@ -1346,6 +1415,7 @@ acpi_bus_scan_fixed (
|
||||
static int __init acpi_scan_init(void)
|
||||
{
|
||||
int result;
|
||||
struct acpi_bus_ops ops;
|
||||
|
||||
ACPI_FUNCTION_TRACE("acpi_scan_init");
|
||||
|
||||
@@ -1357,17 +1427,23 @@ static int __init acpi_scan_init(void)
|
||||
/*
|
||||
* Create the root device in the bus's device tree
|
||||
*/
|
||||
result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
|
||||
result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
|
||||
ACPI_BUS_TYPE_SYSTEM);
|
||||
if (result)
|
||||
goto Done;
|
||||
|
||||
result = acpi_start_single_object(acpi_root);
|
||||
|
||||
/*
|
||||
* Enumerate devices in the ACPI namespace.
|
||||
*/
|
||||
result = acpi_bus_scan_fixed(acpi_root);
|
||||
if (!result)
|
||||
result = acpi_bus_scan(acpi_root);
|
||||
if (!result) {
|
||||
memset(&ops, 0, sizeof(ops));
|
||||
ops.acpi_op_add = 1;
|
||||
ops.acpi_op_start = 1;
|
||||
result = acpi_bus_scan(acpi_root, &ops);
|
||||
}
|
||||
|
||||
if (result)
|
||||
acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
|
||||
|
||||
+1
-1
@@ -451,7 +451,7 @@ static int __init moxa_init(void)
|
||||
int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
|
||||
i = 0;
|
||||
while (i < n) {
|
||||
while ((p = pci_find_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
|
||||
while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
|
||||
{
|
||||
if (pci_enable_device(p))
|
||||
continue;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user