···1030 irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned1031 automatically to PCI devices. You can make the kernel1032 exclude IRQs of your ISA cards this way.00001033 lastbus=N [IA-32] Scan all buses till bus #N. Can be useful1034 if the kernel is unable to find your secondary buses1035 and you want to tell it explicitly which ones they are.
···1030 irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned1031 automatically to PCI devices. You can make the kernel1032 exclude IRQs of your ISA cards this way.1033+ pirqaddr=0xAAAAA [IA-32] Specify the physical address1034+ of the PIRQ table (normally generated1035+ by the BIOS) if it is outside the1036+ F0000h-100000h range.1037 lastbus=N [IA-32] Scan all buses till bus #N. Can be useful1038 if the kernel is unable to find your secondary buses1039 and you want to tell it explicitly which ones they are.
+49-8
arch/i386/kernel/acpi/boot.c
···159#endif160161#ifdef CONFIG_PCI_MMCONFIG162-static int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)0000163{164 struct acpi_table_mcfg *mcfg;00165166 if (!phys_addr || !size)167 return -EINVAL;···178 return -ENODEV;179 }180181- if (mcfg->base_reserved) {182- printk(KERN_ERR PREFIX "MMCONFIG not in low 4GB of memory\n");0000000183 return -ENODEV;184 }185186- pci_mmcfg_base_addr = mcfg->base_address;000000000000000187188 return 0;189}190-#else191-#define acpi_parse_mcfg NULL192-#endif /* !CONFIG_PCI_MMCONFIG */193194#ifdef CONFIG_X86_LOCAL_APIC195static int __init···532}533EXPORT_SYMBOL(acpi_unmap_lsapic);534#endif /* CONFIG_ACPI_HOTPLUG_CPU */0000000000000000535536static unsigned long __init537acpi_scan_rsdp (···1165 acpi_process_madt();11661167 acpi_table_parse(ACPI_HPET, acpi_parse_hpet);1168- acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);11691170 return 0;1171}
···159#endif160161#ifdef CONFIG_PCI_MMCONFIG162+/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */163+struct acpi_table_mcfg_config *pci_mmcfg_config;164+int pci_mmcfg_config_num;165+166+int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)167{168 struct acpi_table_mcfg *mcfg;169+ unsigned long i;170+ int config_size;171172 if (!phys_addr || !size)173 return -EINVAL;···172 return -ENODEV;173 }174175+ /* how many config structures do we have */176+ pci_mmcfg_config_num = 0;177+ i = size - sizeof(struct acpi_table_mcfg);178+ while (i >= sizeof(struct acpi_table_mcfg_config)) {179+ ++pci_mmcfg_config_num;180+ i -= sizeof(struct acpi_table_mcfg_config);181+ };182+ if (pci_mmcfg_config_num == 0) {183+ printk(KERN_ERR PREFIX "MMCONFIG has no entries\n");184 return -ENODEV;185 }186187+ config_size = pci_mmcfg_config_num * sizeof(*pci_mmcfg_config);188+ pci_mmcfg_config = kmalloc(config_size, GFP_KERNEL);189+ if (!pci_mmcfg_config) {190+ printk(KERN_WARNING PREFIX191+ "No memory for MCFG config tables\n");192+ return -ENOMEM;193+ }194+195+ memcpy(pci_mmcfg_config, &mcfg->config, config_size);196+ for (i = 0; i < pci_mmcfg_config_num; ++i) {197+ if (mcfg->config[i].base_reserved) {198+ printk(KERN_ERR PREFIX199+ "MMCONFIG not in low 4GB of memory\n");200+ return -ENODEV;201+ }202+ }203204 return 0;205}206+#endif /* CONFIG_PCI_MMCONFIG */00207208#ifdef CONFIG_X86_LOCAL_APIC209static int __init···506}507EXPORT_SYMBOL(acpi_unmap_lsapic);508#endif /* CONFIG_ACPI_HOTPLUG_CPU */509+510+int511+acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base)512+{513+ /* TBD */514+ return -EINVAL;515+}516+EXPORT_SYMBOL(acpi_register_ioapic);517+518+int519+acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base)520+{521+ /* TBD */522+ return -EINVAL;523+}524+EXPORT_SYMBOL(acpi_unregister_ioapic);525526static unsigned long __init527acpi_scan_rsdp (···1123 acpi_process_madt();11241125 acpi_table_parse(ACPI_HPET, acpi_parse_hpet);011261127 return 0;1128}
···1112#include <linux/pci.h>13#include <linux/init.h>014#include "pci.h"15-16-/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */17-u32 pci_mmcfg_base_addr;1819#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))20···22/*23 * Functions for accessing PCI configuration space with MMCONFIG accesses24 */25-26-static inline void pci_exp_set_dev_base(int bus, int devfn)27{28- u32 dev_base = pci_mmcfg_base_addr | (bus << 20) | (devfn << 12);000000000000000000000029 if (dev_base != mmcfg_last_accessed_device) {30 mmcfg_last_accessed_device = dev_base;31 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);···6364 spin_lock_irqsave(&pci_config_lock, flags);6566- pci_exp_set_dev_base(bus, devfn);6768 switch (len) {69 case 1:···9293 spin_lock_irqsave(&pci_config_lock, flags);9495- pci_exp_set_dev_base(bus, devfn);9697 switch (len) {98 case 1:···120{121 if ((pci_probe & PCI_PROBE_MMCONF) == 0)122 goto out;123- if (!pci_mmcfg_base_addr)0000124 goto out;125126 /* Kludge for now. Don't use mmconfig on AMD systems because
···1112#include <linux/pci.h>13#include <linux/init.h>14+#include <linux/acpi.h>15#include "pci.h"0001617#define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG))18···24/*25 * Functions for accessing PCI configuration space with MMCONFIG accesses26 */27+static u32 get_base_addr(unsigned int seg, int bus)028{29+ int cfg_num = -1;30+ struct acpi_table_mcfg_config *cfg;31+32+ while (1) {33+ ++cfg_num;34+ if (cfg_num >= pci_mmcfg_config_num) {35+ /* something bad is going on, no cfg table is found. */36+ /* so we fall back to the old way we used to do this */37+ /* and just rely on the first entry to be correct. */38+ return pci_mmcfg_config[0].base_address;39+ }40+ cfg = &pci_mmcfg_config[cfg_num];41+ if (cfg->pci_segment_group_number != seg)42+ continue;43+ if ((cfg->start_bus_number <= bus) &&44+ (cfg->end_bus_number >= bus))45+ return cfg->base_address;46+ }47+}48+49+static inline void pci_exp_set_dev_base(unsigned int seg, int bus, int devfn)50+{51+ u32 dev_base = get_base_addr(seg, bus) | (bus << 20) | (devfn << 12);52 if (dev_base != mmcfg_last_accessed_device) {53 mmcfg_last_accessed_device = dev_base;54 set_fixmap_nocache(FIX_PCIE_MCFG, dev_base);···4445 spin_lock_irqsave(&pci_config_lock, flags);4647+ pci_exp_set_dev_base(seg, bus, devfn);4849 switch (len) {50 case 1:···7374 spin_lock_irqsave(&pci_config_lock, flags);7576+ pci_exp_set_dev_base(seg, bus, devfn);7778 switch (len) {79 case 1:···101{102 if ((pci_probe & PCI_PROBE_MMCONF) == 0)103 goto out;104+105+ acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);106+ if ((pci_mmcfg_config_num == 0) ||107+ (pci_mmcfg_config == NULL) ||108+ (pci_mmcfg_config[0].base_address == 0))109 goto out;110111 /* Kludge for now. Don't use mmconfig on AMD systems because
+2
arch/i386/pci/numa.c
···115 return 0;116117 pci_root_bus = pcibios_scan_root(0);00118 if (num_online_nodes() > 1)119 for_each_online_node(quad) {120 if (quad == 0)
···115 return 0;116117 pci_root_bus = pcibios_scan_root(0);118+ if (pci_root_bus)119+ pci_bus_add_devices(pci_root_bus);120 if (num_online_nodes() > 1)121 for_each_online_node(quad) {122 if (quad == 0)
+1
arch/i386/pci/pci.h
···27#define PCI_ASSIGN_ALL_BUSSES 0x40002829extern unsigned int pci_probe;03031/* pci-i386.c */32
···27#define PCI_ASSIGN_ALL_BUSSES 0x40002829extern unsigned int pci_probe;30+extern unsigned long pirq_table_addr;3132/* pci-i386.c */33
···129 char __iomem *addr; /* base address of IOSAPIC */130 unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */131 unsigned short num_rte; /* number of RTE in this IOSAPIC */0132#ifdef CONFIG_NUMA133 unsigned short node; /* numa node association via pxm */134#endif135} iosapic_lists[NR_IOSAPICS];136137-static int num_iosapic;138-139-static unsigned char pcat_compat __initdata; /* 8259 compatibility flag */140141static int iosapic_kmalloc_ok;142static LIST_HEAD(free_rte_list);···148{149 int i;150151- for (i = 0; i < num_iosapic; i++) {152 if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)153 return i;154 }···597 rte->refcnt++;598 list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes);599 iosapic_intr_info[vector].count++;0600 }601 else if (vector_is_shared(vector)) {602 struct iosapic_intr_info *info = &iosapic_intr_info[vector];···778iosapic_unregister_intr (unsigned int gsi)779{780 unsigned long flags;781- int irq, vector;782 irq_desc_t *idesc;783 u32 low32;784 unsigned long trigger, polarity;···819 list_del(&rte->rte_list);820 iosapic_intr_info[vector].count--;821 iosapic_free_rte(rte);000822823 trigger = iosapic_intr_info[vector].trigger;824 polarity = iosapic_intr_info[vector].polarity;···955 }956}957958-void __init000000000000000000000000000000000000000000000959iosapic_init (unsigned long phys_addr, unsigned int gsi_base)960{961- int num_rte;962 unsigned int isa_irq, ver;963 char __iomem *addr;0964965- addr = ioremap(phys_addr, 0);966- ver = iosapic_version(addr);00967968- /*969- * The MAX_REDIR register holds the highest input pin970- * number (starting from 0).971- * We add 1 so that we can use it for number of pins (= RTEs)972- */973- num_rte = ((ver >> 16) & 0xff) + 1;974975- iosapic_lists[num_iosapic].addr = addr;976- iosapic_lists[num_iosapic].gsi_base = gsi_base;977- iosapic_lists[num_iosapic].num_rte = num_rte;00000000978#ifdef CONFIG_NUMA979- iosapic_lists[num_iosapic].node = MAX_NUMNODES;980#endif981- num_iosapic++;0982983 if ((gsi_base == 0) && pcat_compat) {984 /*···1045 for (isa_irq = 0; isa_irq < 16; ++isa_irq)1046 iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);1047 }01048}1049000000000000000000000000000000001050#ifdef CONFIG_NUMA1051-void __init1052map_iosapic_to_node(unsigned int gsi_base, int node)1053{1054 int index;
···129 char __iomem *addr; /* base address of IOSAPIC */130 unsigned int gsi_base; /* first GSI assigned to this IOSAPIC */131 unsigned short num_rte; /* number of RTE in this IOSAPIC */132+ int rtes_inuse; /* # of RTEs in use on this IOSAPIC */133#ifdef CONFIG_NUMA134 unsigned short node; /* numa node association via pxm */135#endif136} iosapic_lists[NR_IOSAPICS];137138+static unsigned char pcat_compat __devinitdata; /* 8259 compatibility flag */00139140static int iosapic_kmalloc_ok;141static LIST_HEAD(free_rte_list);···149{150 int i;151152+ for (i = 0; i < NR_IOSAPICS; i++) {153 if ((unsigned) (gsi - iosapic_lists[i].gsi_base) < iosapic_lists[i].num_rte)154 return i;155 }···598 rte->refcnt++;599 list_add_tail(&rte->rte_list, &iosapic_intr_info[vector].rtes);600 iosapic_intr_info[vector].count++;601+ iosapic_lists[index].rtes_inuse++;602 }603 else if (vector_is_shared(vector)) {604 struct iosapic_intr_info *info = &iosapic_intr_info[vector];···778iosapic_unregister_intr (unsigned int gsi)779{780 unsigned long flags;781+ int irq, vector, index;782 irq_desc_t *idesc;783 u32 low32;784 unsigned long trigger, polarity;···819 list_del(&rte->rte_list);820 iosapic_intr_info[vector].count--;821 iosapic_free_rte(rte);822+ index = find_iosapic(gsi);823+ iosapic_lists[index].rtes_inuse--;824+ WARN_ON(iosapic_lists[index].rtes_inuse < 0);825826 trigger = iosapic_intr_info[vector].trigger;827 polarity = iosapic_intr_info[vector].polarity;···952 }953}954955+static inline int956+iosapic_alloc (void)957+{958+ int index;959+960+ for (index = 0; index < NR_IOSAPICS; index++)961+ if (!iosapic_lists[index].addr)962+ return index;963+964+ printk(KERN_WARNING "%s: failed to allocate iosapic\n", __FUNCTION__);965+ return -1;966+}967+968+static inline void969+iosapic_free (int index)970+{971+ memset(&iosapic_lists[index], 0, sizeof(iosapic_lists[0]));972+}973+974+static inline int975+iosapic_check_gsi_range (unsigned int gsi_base, unsigned int ver)976+{977+ int index;978+ unsigned int gsi_end, base, end;979+980+ /* check gsi range */981+ gsi_end = gsi_base + ((ver >> 16) & 0xff);982+ for (index = 0; index < NR_IOSAPICS; index++) {983+ if (!iosapic_lists[index].addr)984+ continue;985+986+ base = iosapic_lists[index].gsi_base;987+ end = base + iosapic_lists[index].num_rte - 1;988+989+ if (gsi_base < base && gsi_end < base)990+ continue;/* OK */991+992+ if (gsi_base > end && gsi_end > end)993+ continue; /* OK */994+995+ return -EBUSY;996+ }997+ return 0;998+}999+1000+int __devinit1001iosapic_init (unsigned long phys_addr, unsigned int gsi_base)1002{1003+ int num_rte, err, index;1004 unsigned int isa_irq, ver;1005 char __iomem *addr;1006+ unsigned long flags;10071008+ spin_lock_irqsave(&iosapic_lock, flags);1009+ {1010+ addr = ioremap(phys_addr, 0);1011+ ver = iosapic_version(addr);10121013+ if ((err = iosapic_check_gsi_range(gsi_base, ver))) {1014+ iounmap(addr);1015+ spin_unlock_irqrestore(&iosapic_lock, flags);1016+ return err;1017+ }010181019+ /*1020+ * The MAX_REDIR register holds the highest input pin1021+ * number (starting from 0).1022+ * We add 1 so that we can use it for number of pins (= RTEs)1023+ */1024+ num_rte = ((ver >> 16) & 0xff) + 1;1025+1026+ index = iosapic_alloc();1027+ iosapic_lists[index].addr = addr;1028+ iosapic_lists[index].gsi_base = gsi_base;1029+ iosapic_lists[index].num_rte = num_rte;1030#ifdef CONFIG_NUMA1031+ iosapic_lists[index].node = MAX_NUMNODES;1032#endif1033+ }1034+ spin_unlock_irqrestore(&iosapic_lock, flags);10351036 if ((gsi_base == 0) && pcat_compat) {1037 /*···986 for (isa_irq = 0; isa_irq < 16; ++isa_irq)987 iosapic_override_isa_irq(isa_irq, isa_irq, IOSAPIC_POL_HIGH, IOSAPIC_EDGE);988 }989+ return 0;990}991992+#ifdef CONFIG_HOTPLUG993+int994+iosapic_remove (unsigned int gsi_base)995+{996+ int index, err = 0;997+ unsigned long flags;998+999+ spin_lock_irqsave(&iosapic_lock, flags);1000+ {1001+ index = find_iosapic(gsi_base);1002+ if (index < 0) {1003+ printk(KERN_WARNING "%s: No IOSAPIC for GSI base %u\n",1004+ __FUNCTION__, gsi_base);1005+ goto out;1006+ }1007+1008+ if (iosapic_lists[index].rtes_inuse) {1009+ err = -EBUSY;1010+ printk(KERN_WARNING "%s: IOSAPIC for GSI base %u is busy\n",1011+ __FUNCTION__, gsi_base);1012+ goto out;1013+ }1014+1015+ iounmap(iosapic_lists[index].addr);1016+ iosapic_free(index);1017+ }1018+ out:1019+ spin_unlock_irqrestore(&iosapic_lock, flags);1020+ return err;1021+}1022+#endif /* CONFIG_HOTPLUG */1023+1024#ifdef CONFIG_NUMA1025+void __devinit1026map_iosapic_to_node(unsigned int gsi_base, int node)1027{1028 int index;
+33-5
arch/ia64/pci/pci.c
···312 acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,313 &info);314315- pbus = pci_scan_bus(bus, &pci_root_ops, controller);316 if (pbus)317 pcibios_setup_root_windows(pbus, controller);318···373 res->end = region->end + offset;374}3750000000000000000000376static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)377{378 struct pci_bus_region region;···405 region.start = dev->resource[i].start;406 region.end = dev->resource[i].end;407 pcibios_bus_to_resource(dev, &dev->resource[i], ®ion);408- pci_claim_resource(dev, i);0409 }410}411···418{419 struct pci_dev *dev;4200000421 list_for_each_entry(dev, &b->devices, bus_list)422 pcibios_fixup_device_resources(dev);423···442 u16 cmd, old_cmd;443 int idx;444 struct resource *r;0445446 if (!dev)447 return -EINVAL;448449 pci_read_config_word(dev, PCI_COMMAND, &cmd);450 old_cmd = cmd;451- for (idx=0; idx<6; idx++) {452 /* Only set up the desired resources. */453 if (!(mask & (1 << idx)))454 continue;455456 r = &dev->resource[idx];00000457 if (!r->start && r->end) {458 printk(KERN_ERR459 "PCI: Device %s not available because of resource collisions\n",···471 if (r->flags & IORESOURCE_MEM)472 cmd |= PCI_COMMAND_MEMORY;473 }474- if (dev->resource[PCI_ROM_RESOURCE].start)475- cmd |= PCI_COMMAND_MEMORY;476 if (cmd != old_cmd) {477 printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);478 pci_write_config_word(dev, PCI_COMMAND, cmd);
···312 acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window,313 &info);314315+ pbus = pci_scan_bus_parented(NULL, bus, &pci_root_ops, controller);316 if (pbus)317 pcibios_setup_root_windows(pbus, controller);318···373 res->end = region->end + offset;374}375376+static int __devinit is_valid_resource(struct pci_dev *dev, int idx)377+{378+ unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM;379+ struct resource *devr = &dev->resource[idx];380+381+ if (!dev->bus)382+ return 0;383+ for (i=0; i<PCI_BUS_NUM_RESOURCES; i++) {384+ struct resource *busr = dev->bus->resource[i];385+386+ if (!busr || ((busr->flags ^ devr->flags) & type_mask))387+ continue;388+ if ((devr->start) && (devr->start >= busr->start) &&389+ (devr->end <= busr->end))390+ return 1;391+ }392+ return 0;393+}394+395static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)396{397 struct pci_bus_region region;···386 region.start = dev->resource[i].start;387 region.end = dev->resource[i].end;388 pcibios_bus_to_resource(dev, &dev->resource[i], ®ion);389+ if ((is_valid_resource(dev, i)))390+ pci_claim_resource(dev, i);391 }392}393···398{399 struct pci_dev *dev;400401+ if (b->self) {402+ pci_read_bridge_bases(b);403+ pcibios_fixup_device_resources(b->self);404+ }405 list_for_each_entry(dev, &b->devices, bus_list)406 pcibios_fixup_device_resources(dev);407···418 u16 cmd, old_cmd;419 int idx;420 struct resource *r;421+ unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;422423 if (!dev)424 return -EINVAL;425426 pci_read_config_word(dev, PCI_COMMAND, &cmd);427 old_cmd = cmd;428+ for (idx=0; idx<PCI_NUM_RESOURCES; idx++) {429 /* Only set up the desired resources. */430 if (!(mask & (1 << idx)))431 continue;432433 r = &dev->resource[idx];434+ if (!(r->flags & type_mask))435+ continue;436+ if ((idx == PCI_ROM_RESOURCE) &&437+ (!(r->flags & IORESOURCE_ROM_ENABLE)))438+ continue;439 if (!r->start && r->end) {440 printk(KERN_ERR441 "PCI: Device %s not available because of resource collisions\n",···441 if (r->flags & IORESOURCE_MEM)442 cmd |= PCI_COMMAND_MEMORY;443 }00444 if (cmd != old_cmd) {445 printk("PCI: Enabling device %s (%04x -> %04x)\n", pci_name(dev), old_cmd, cmd);446 pci_write_config_word(dev, PCI_COMMAND, cmd);
···78#include <linux/pci.h>9#include <linux/init.h>010#include "pci.h"1112#define MMCONFIG_APER_SIZE (256*1024*1024)1314-/* The physical address of the MMCONFIG aperture. Set from ACPI tables. */15-u32 pci_mmcfg_base_addr;16-17/* Static virtual mapping of the MMCONFIG aperture */18-char *pci_mmcfg_virt;00001920-static inline char *pci_dev_base(unsigned int bus, unsigned int devfn)21{22- return pci_mmcfg_virt + ((bus << 20) | (devfn << 12));0000000000000000000000023}2425static int pci_mmcfg_read(unsigned int seg, unsigned int bus,26 unsigned int devfn, int reg, int len, u32 *value)27{28- char *addr = pci_dev_base(bus, devfn); 2930 if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))31 return -EINVAL;···73static int pci_mmcfg_write(unsigned int seg, unsigned int bus,74 unsigned int devfn, int reg, int len, u32 value)75{76- char *addr = pci_dev_base(bus,devfn);7778 if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))79 return -EINVAL;···100101static int __init pci_mmcfg_init(void)102{00103 if ((pci_probe & PCI_PROBE_MMCONF) == 0)104 return 0;105- if (!pci_mmcfg_base_addr)0000106 return 0;107108 /* Kludge for now. Don't use mmconfig on AMD systems because···119 return 0; 120121 /* RED-PEN i386 doesn't do _nocache right now */122- pci_mmcfg_virt = ioremap_nocache(pci_mmcfg_base_addr, MMCONFIG_APER_SIZE);123- if (!pci_mmcfg_virt) { 124- printk("PCI: Cannot map mmconfig aperture\n");125 return 0;126- } 0000000000127128- printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_base_addr);129 raw_pci_ops = &pci_mmcfg;130 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;131
···78#include <linux/pci.h>9#include <linux/init.h>10+#include <linux/acpi.h>11#include "pci.h"1213#define MMCONFIG_APER_SIZE (256*1024*1024)1400015/* Static virtual mapping of the MMCONFIG aperture */16+struct mmcfg_virt {17+ struct acpi_table_mcfg_config *cfg;18+ char *virt;19+};20+static struct mmcfg_virt *pci_mmcfg_virt;2122+static char *get_virt(unsigned int seg, int bus)23{24+ int cfg_num = -1;25+ struct acpi_table_mcfg_config *cfg;26+27+ while (1) {28+ ++cfg_num;29+ if (cfg_num >= pci_mmcfg_config_num) {30+ /* something bad is going on, no cfg table is found. */31+ /* so we fall back to the old way we used to do this */32+ /* and just rely on the first entry to be correct. */33+ return pci_mmcfg_virt[0].virt;34+ }35+ cfg = pci_mmcfg_virt[cfg_num].cfg;36+ if (cfg->pci_segment_group_number != seg)37+ continue;38+ if ((cfg->start_bus_number <= bus) &&39+ (cfg->end_bus_number >= bus))40+ return pci_mmcfg_virt[cfg_num].virt;41+ }42+}43+44+static inline char *pci_dev_base(unsigned int seg, unsigned int bus, unsigned int devfn)45+{46+47+ return get_virt(seg, bus) + ((bus << 20) | (devfn << 12));48}4950static int pci_mmcfg_read(unsigned int seg, unsigned int bus,51 unsigned int devfn, int reg, int len, u32 *value)52{53+ char *addr = pci_dev_base(seg, bus, devfn);5455 if (unlikely(!value || (bus > 255) || (devfn > 255) || (reg > 4095)))56 return -EINVAL;···48static int pci_mmcfg_write(unsigned int seg, unsigned int bus,49 unsigned int devfn, int reg, int len, u32 value)50{51+ char *addr = pci_dev_base(seg, bus, devfn);5253 if (unlikely((bus > 255) || (devfn > 255) || (reg > 4095)))54 return -EINVAL;···7576static int __init pci_mmcfg_init(void)77{78+ int i;79+80 if ((pci_probe & PCI_PROBE_MMCONF) == 0)81 return 0;82+83+ acpi_table_parse(ACPI_MCFG, acpi_parse_mcfg);84+ if ((pci_mmcfg_config_num == 0) ||85+ (pci_mmcfg_config == NULL) ||86+ (pci_mmcfg_config[0].base_address == 0))87 return 0;8889 /* Kludge for now. Don't use mmconfig on AMD systems because···88 return 0; 8990 /* RED-PEN i386 doesn't do _nocache right now */91+ pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL);92+ if (pci_mmcfg_virt == NULL) {93+ printk("PCI: Can not allocate memory for mmconfig structures\n");94 return 0;95+ }96+ for (i = 0; i < pci_mmcfg_config_num; ++i) {97+ pci_mmcfg_virt[i].cfg = &pci_mmcfg_config[i];98+ pci_mmcfg_virt[i].virt = ioremap_nocache(pci_mmcfg_config[i].base_address, MMCONFIG_APER_SIZE);99+ if (!pci_mmcfg_virt[i].virt) {100+ printk("PCI: Cannot map mmconfig aperture for segment %d\n",101+ pci_mmcfg_config[i].pci_segment_group_number);102+ return 0;103+ }104+ printk(KERN_INFO "PCI: Using MMCONFIG at %x\n", pci_mmcfg_config[i].base_address);105+ }1060107 raw_pci_ops = &pci_mmcfg;108 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF;109
+1-1
drivers/acpi/container.c
···153 return_VALUE(-ENODEV);154 }155156- result = acpi_bus_scan(*device);157158 return_VALUE(result);159}
···153 return_VALUE(-ENODEV);154 }155156+ result = acpi_bus_start(*device);157158 return_VALUE(result);159}
+20-7
drivers/acpi/pci_bind.c
···616263/**64- * acpi_os_get_pci_id65 * ------------------66 * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)67 * to resolve PCI information for ACPI-PCI devices defined in the namespace.68 * This typically occurs when resolving PCI operation region information.69 */70-#ifdef ACPI_FUTURE_USAGE71acpi_status72-acpi_os_get_pci_id (73 acpi_handle handle,74 struct acpi_pci_id *id)75{···77 struct acpi_device *device = NULL;78 struct acpi_pci_data *data = NULL;7980- ACPI_FUNCTION_TRACE("acpi_os_get_pci_id");8182 if (!id)83 return_ACPI_STATUS(AE_BAD_PARAMETER);···91 }9293 status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);94- if (ACPI_FAILURE(status) || !data || !data->dev) {95 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 96 "Invalid ACPI-PCI context for device %s\n",97 acpi_device_bid(device)));···114115 return_ACPI_STATUS(AE_OK);116}117-#endif /* ACPI_FUTURE_USAGE */118119120int···128 char *pathname = NULL;129 struct acpi_buffer buffer = {0, NULL};130 acpi_handle handle = NULL;00131132 ACPI_FUNCTION_TRACE("acpi_pci_bind");133···194 * Locate matching device in PCI namespace. If it doesn't exist195 * this typically means that the device isn't currently inserted196 * (e.g. docking station, port replicator, etc.).000197 */198- data->dev = pci_find_slot(data->id.bus, PCI_DEVFN(data->id.device, data->id.function));000000000199 if (!data->dev) {200 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 201 "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
···616263/**64+ * acpi_get_pci_id65 * ------------------66 * This function is used by the ACPI Interpreter (a.k.a. Core Subsystem)67 * to resolve PCI information for ACPI-PCI devices defined in the namespace.68 * This typically occurs when resolving PCI operation region information.69 */070acpi_status71+acpi_get_pci_id (72 acpi_handle handle,73 struct acpi_pci_id *id)74{···78 struct acpi_device *device = NULL;79 struct acpi_pci_data *data = NULL;8081+ ACPI_FUNCTION_TRACE("acpi_get_pci_id");8283 if (!id)84 return_ACPI_STATUS(AE_BAD_PARAMETER);···92 }9394 status = acpi_get_data(handle, acpi_pci_data_handler, (void**) &data);95+ if (ACPI_FAILURE(status) || !data) {96 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 97 "Invalid ACPI-PCI context for device %s\n",98 acpi_device_bid(device)));···115116 return_ACPI_STATUS(AE_OK);117}118+EXPORT_SYMBOL(acpi_get_pci_id);119120121int···129 char *pathname = NULL;130 struct acpi_buffer buffer = {0, NULL};131 acpi_handle handle = NULL;132+ struct pci_dev *dev;133+ struct pci_bus *bus;134135 ACPI_FUNCTION_TRACE("acpi_pci_bind");136···193 * Locate matching device in PCI namespace. If it doesn't exist194 * this typically means that the device isn't currently inserted195 * (e.g. docking station, port replicator, etc.).196+ * We cannot simply search the global pci device list, since197+ * PCI devices are added to the global pci list when the root198+ * bridge start ops are run, which may not have happened yet.199 */200+ bus = pci_find_bus(data->id.segment, data->id.bus);201+ if (bus) {202+ list_for_each_entry(dev, &bus->devices, bus_list) {203+ if (dev->devfn == PCI_DEVFN(data->id.device,204+ data->id.function)) {205+ data->dev = dev;206+ break;207+ }208+ }209+ }210 if (!data->dev) {211 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 212 "Device %02x:%02x:%02x.%02x not present in PCI namespace\n",
+23-1
drivers/acpi/pci_root.c
···4647static int acpi_pci_root_add (struct acpi_device *device);48static int acpi_pci_root_remove (struct acpi_device *device, int type);04950static struct acpi_driver acpi_pci_root_driver = {51 .name = ACPI_PCI_ROOT_DRIVER_NAME,···55 .ops = {56 .add = acpi_pci_root_add,57 .remove = acpi_pci_root_remove,058 },59};60···171 if (!root)172 return_VALUE(-ENOMEM);173 memset(root, 0, sizeof(struct acpi_pci_root));0174175 root->handle = device->handle;176 strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME);···301 root->id.bus);302303end:304- if (result)00305 kfree(root);0306307 return_VALUE(result);308}3090000000000000000310311static int312acpi_pci_root_remove (
···723 return_VALUE(-ENODEV);724 }725726- acpi_bus_scan(*device);727728 pr = acpi_driver_data(*device);729 if (!pr)
···723 return_VALUE(-ENODEV);724 }725726+ acpi_bus_start(*device);727728 pr = acpi_driver_data(*device);729 if (!pr)
+101-25
drivers/acpi/scan.c
···553 * upon possible configuration and currently allocated resources.554 */5550000000000000000556 if (driver->ops.start) {557 result = driver->ops.start(device);558 if (result && driver->ops.remove)559 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);560- return_VALUE(result);561 }562563- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));564-565- if (driver->ops.scan) {566- driver->ops.scan(device);567- }568-569- return_VALUE(0);570}571572static int acpi_driver_attach(struct acpi_driver * drv)···595596 if (!acpi_bus_match(dev, drv)) {597 if (!acpi_bus_driver_init(dev, drv)) {0598 atomic_inc(&drv->references);599 count++;600 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",···1019}102010211022-int1023-acpi_bus_add (1024 struct acpi_device **child,1025 struct acpi_device *parent,1026 acpi_handle handle,···1029 int result = 0;1030 struct acpi_device *device = NULL;10311032- ACPI_FUNCTION_TRACE("acpi_bus_add");10331034 if (!child)1035 return_VALUE(-EINVAL);···1150 *1151 * TBD: Assumes LDM provides driver hot-plug capability.1152 */1153- acpi_bus_find_driver(device);11541155end:1156 if (!result)···11631164 return_VALUE(result);1165}1166-EXPORT_SYMBOL(acpi_bus_add);116711681169-int acpi_bus_scan (struct acpi_device *start)01170{1171 acpi_status status = AE_OK;1172 struct acpi_device *parent = NULL;···1239 continue;1240 }12411242- status = acpi_bus_add(&child, parent, chandle, type);1243- if (ACPI_FAILURE(status))1244- continue;0000000000012451246 /*1247 * If the device is present, enabled, and functioning then···12781279 return_VALUE(0);1280}1281-EXPORT_SYMBOL(acpi_bus_scan);1282000000000000000000000000000000000000000000012831284static int1285acpi_bus_trim(struct acpi_device *start,···1394 /*1395 * Enumerate all fixed-feature devices.1396 */1397- if (acpi_fadt.pwr_button == 0)1398- result = acpi_bus_add(&device, acpi_root, 1399 NULL, ACPI_BUS_TYPE_POWER_BUTTON);00014001401- if (acpi_fadt.sleep_button == 0)1402- result = acpi_bus_add(&device, acpi_root, 1403 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);00014041405 return_VALUE(result);1406}···1415static int __init acpi_scan_init(void)1416{1417 int result;014181419 ACPI_FUNCTION_TRACE("acpi_scan_init");1420···1427 /*1428 * Create the root device in the bus's device tree1429 */1430- result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT, 1431 ACPI_BUS_TYPE_SYSTEM);1432 if (result)1433 goto Done;0014341435 /*1436 * Enumerate devices in the ACPI namespace.1437 */1438 result = acpi_bus_scan_fixed(acpi_root);1439- if (!result) 1440- result = acpi_bus_scan(acpi_root);000014411442 if (result)1443 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
···553 * upon possible configuration and currently allocated resources.554 */555556+ ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Driver successfully bound to device\n"));557+ return_VALUE(0);558+}559+560+int561+acpi_start_single_object (562+ struct acpi_device *device)563+{564+ int result = 0;565+ struct acpi_driver *driver;566+567+ ACPI_FUNCTION_TRACE("acpi_start_single_object");568+569+ if (!(driver = device->driver))570+ return_VALUE(0);571+572 if (driver->ops.start) {573 result = driver->ops.start(device);574 if (result && driver->ops.remove)575 driver->ops.remove(device, ACPI_BUS_REMOVAL_NORMAL);0576 }577578+ return_VALUE(result);000000579}580581static int acpi_driver_attach(struct acpi_driver * drv)···586587 if (!acpi_bus_match(dev, drv)) {588 if (!acpi_bus_driver_init(dev, drv)) {589+ acpi_start_single_object(dev);590 atomic_inc(&drv->references);591 count++;592 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found driver [%s] for device [%s]\n",···1009}101010111012+static int1013+acpi_add_single_object (1014 struct acpi_device **child,1015 struct acpi_device *parent,1016 acpi_handle handle,···1019 int result = 0;1020 struct acpi_device *device = NULL;10211022+ ACPI_FUNCTION_TRACE("acpi_add_single_object");10231024 if (!child)1025 return_VALUE(-EINVAL);···1140 *1141 * TBD: Assumes LDM provides driver hot-plug capability.1142 */1143+ result = acpi_bus_find_driver(device);11441145end:1146 if (!result)···11531154 return_VALUE(result);1155}0115611571158+static int acpi_bus_scan (struct acpi_device *start,1159+ struct acpi_bus_ops *ops)1160{1161 acpi_status status = AE_OK;1162 struct acpi_device *parent = NULL;···1229 continue;1230 }12311232+ if (ops->acpi_op_add)1233+ status = acpi_add_single_object(&child, parent,1234+ chandle, type);1235+ else1236+ status = acpi_bus_get_device(chandle, &child);1237+1238+ if (ACPI_FAILURE(status))1239+ continue;1240+1241+ if (ops->acpi_op_start) {1242+ status = acpi_start_single_object(child);1243+ if (ACPI_FAILURE(status))1244+ continue;1245+ }12461247 /*1248 * If the device is present, enabled, and functioning then···12571258 return_VALUE(0);1259}012601261+int1262+acpi_bus_add (1263+ struct acpi_device **child,1264+ struct acpi_device *parent,1265+ acpi_handle handle,1266+ int type)1267+{1268+ int result;1269+ struct acpi_bus_ops ops;1270+1271+ ACPI_FUNCTION_TRACE("acpi_bus_add");1272+1273+ result = acpi_add_single_object(child, parent, handle, type);1274+ if (!result) {1275+ memset(&ops, 0, sizeof(ops));1276+ ops.acpi_op_add = 1;1277+ result = acpi_bus_scan(*child, &ops);1278+ }1279+ return_VALUE(result);1280+}1281+EXPORT_SYMBOL(acpi_bus_add);1282+1283+int1284+acpi_bus_start (1285+ struct acpi_device *device)1286+{1287+ int result;1288+ struct acpi_bus_ops ops;1289+1290+ ACPI_FUNCTION_TRACE("acpi_bus_start");1291+1292+ if (!device)1293+ return_VALUE(-EINVAL);1294+1295+ result = acpi_start_single_object(device);1296+ if (!result) {1297+ memset(&ops, 0, sizeof(ops));1298+ ops.acpi_op_start = 1;1299+ result = acpi_bus_scan(device, &ops);1300+ }1301+ return_VALUE(result);1302+}1303+EXPORT_SYMBOL(acpi_bus_start);13041305static int1306acpi_bus_trim(struct acpi_device *start,···1331 /*1332 * Enumerate all fixed-feature devices.1333 */1334+ if (acpi_fadt.pwr_button == 0) {1335+ result = acpi_add_single_object(&device, acpi_root,1336 NULL, ACPI_BUS_TYPE_POWER_BUTTON);1337+ if (!result)1338+ result = acpi_start_single_object(device);1339+ }13401341+ if (acpi_fadt.sleep_button == 0) {1342+ result = acpi_add_single_object(&device, acpi_root,1343 NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);1344+ if (!result)1345+ result = acpi_start_single_object(device);1346+ }13471348 return_VALUE(result);1349}···1346static int __init acpi_scan_init(void)1347{1348 int result;1349+ struct acpi_bus_ops ops;13501351 ACPI_FUNCTION_TRACE("acpi_scan_init");1352···1357 /*1358 * Create the root device in the bus's device tree1359 */1360+ result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,1361 ACPI_BUS_TYPE_SYSTEM);1362 if (result)1363 goto Done;1364+1365+ result = acpi_start_single_object(acpi_root);13661367 /*1368 * Enumerate devices in the ACPI namespace.1369 */1370 result = acpi_bus_scan_fixed(acpi_root);1371+ if (!result) {1372+ memset(&ops, 0, sizeof(ops));1373+ ops.acpi_op_add = 1;1374+ ops.acpi_op_start = 1;1375+ result = acpi_bus_scan(acpi_root, &ops);1376+ }13771378 if (result)1379 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+1-1
drivers/char/moxa.c
···451 int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;452 i = 0;453 while (i < n) {454- while ((p = pci_find_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)455 {456 if (pci_enable_device(p))457 continue;
···451 int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;452 i = 0;453 while (i < n) {454+ while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)455 {456 if (pci_enable_device(p))457 continue;
+2-2
drivers/char/rio/rio_linux.c
···10951096#ifdef CONFIG_PCI1097 /* First look for the JET devices: */1098- while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 1099 PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 1100 pdev))) {1101 if (pci_enable_device(pdev)) continue;···1169 */11701171 /* Then look for the older RIO/PCI devices: */1172- while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 1173 PCI_DEVICE_ID_SPECIALIX_RIO, 1174 pdev))) {1175 if (pci_enable_device(pdev)) continue;
···10951096#ifdef CONFIG_PCI1097 /* First look for the JET devices: */1098+ while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,1099 PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 1100 pdev))) {1101 if (pci_enable_device(pdev)) continue;···1169 */11701171 /* Then look for the older RIO/PCI devices: */1172+ while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,1173 PCI_DEVICE_ID_SPECIALIX_RIO, 1174 pdev))) {1175 if (pci_enable_device(pdev)) continue;
···993 bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,994 &dino_cfg_ops, NULL);995 if(bus) {0996 /* This code *depends* on scanning being single threaded997 * if it isn't, this global bus number count will fail998 */
···993 bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,994 &dino_cfg_ops, NULL);995 if(bus) {996+ pci_bus_add_devices(bus);997 /* This code *depends* on scanning being single threaded998 * if it isn't, this global bus number count will fail999 */
+2
drivers/parisc/lba_pci.c
···1570 lba_bus = lba_dev->hba.hba_bus =1571 pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,1572 cfg_ops, NULL);0015731574 /* This is in lieu of calling pci_assign_unassigned_resources() */1575 if (is_pdc_pat()) {
···1570 lba_bus = lba_dev->hba.hba_bus =1571 pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,1572 cfg_ops, NULL);1573+ if (lba_bus)1574+ pci_bus_add_devices(lba_bus);15751576 /* This is in lieu of calling pci_assign_unassigned_resources() */1577 if (is_pdc_pat()) {
+7-4
drivers/pci/bus.c
···121 * If there is an unattached subordinate bus, attach122 * it and then scan for unattached PCI devices.123 */124- if (dev->subordinate && list_empty(&dev->subordinate->node)) {125- spin_lock(&pci_bus_lock);126- list_add_tail(&dev->subordinate->node, &dev->bus->children);127- spin_unlock(&pci_bus_lock);000128 pci_bus_add_devices(dev->subordinate);129130 sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
···121 * If there is an unattached subordinate bus, attach122 * it and then scan for unattached PCI devices.123 */124+ if (dev->subordinate) {125+ if (list_empty(&dev->subordinate->node)) {126+ spin_lock(&pci_bus_lock);127+ list_add_tail(&dev->subordinate->node,128+ &dev->bus->children);129+ spin_unlock(&pci_bus_lock);130+ }131 pci_bus_add_devices(dev->subordinate);132133 sysfs_create_link(&dev->subordinate->class_dev.kobj, &dev->dev.kobj, "bridge");
···7 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)8 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)9 * Copyright (C) 2002,2003 NEC Corporation0010 *11 * All rights reserved.12 *···5455struct acpiphp_bridge;56struct acpiphp_slot;57-struct pci_resource;5859/*60 * struct slot - slot information for each *physical* slot···64 struct list_head slot_list;6566 struct acpiphp_slot *acpi_slot;67-};68-69-/*70- * struct pci_resource - describes pci resource (mem, pfmem, io, bus)71- */72-struct pci_resource {73- struct pci_resource * next;74- u64 base;75- u32 length;76};7778/**···93 int type;94 int nr_slots;9596- u8 seg;97- u8 bus;98- u8 sub;99-100 u32 flags;101102 /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */···105 struct hpp_param hpp;106107 spinlock_t res_lock;108-109- /* available resources on this bus */110- struct pci_resource *mem_head;111- struct pci_resource *p_mem_head;112- struct pci_resource *io_head;113- struct pci_resource *bus_head;114};115116···145146 u8 function; /* pci function# */147 u32 flags; /* see below */148-149- /* resources used for this function */150- struct pci_resource *mem_head;151- struct pci_resource *p_mem_head;152- struct pci_resource *io_head;153- struct pci_resource *bus_head;154};155156/**···218extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);219extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);220extern u32 acpiphp_get_address (struct acpiphp_slot *slot);221-222-/* acpiphp_pci.c */223-extern struct pci_dev *acpiphp_allocate_pcidev (struct pci_bus *pbus, int dev, int fn);224-extern int acpiphp_configure_slot (struct acpiphp_slot *slot);225-extern int acpiphp_configure_function (struct acpiphp_func *func);226-extern void acpiphp_unconfigure_function (struct acpiphp_func *func);227-extern int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge);228-extern int acpiphp_init_func_resource (struct acpiphp_func *func);229-230-/* acpiphp_res.c */231-extern struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size);232-extern struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size);233-extern struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size);234-extern int acpiphp_resource_sort_and_combine (struct pci_resource **head);235-extern struct pci_resource *acpiphp_make_resource (u64 base, u32 length);236-extern void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to);237-extern void acpiphp_free_resource (struct pci_resource **res);238-extern void acpiphp_dump_resource (struct acpiphp_bridge *bridge); /* debug */239-extern void acpiphp_dump_func_resource (struct acpiphp_func *func); /* debug */240241/* variables */242extern int acpiphp_debug;
···7 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)8 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)9 * Copyright (C) 2002,2003 NEC Corporation10+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)11+ * Copyright (C) 2003-2005 Hewlett Packard12 *13 * All rights reserved.14 *···5253struct acpiphp_bridge;54struct acpiphp_slot;05556/*57 * struct slot - slot information for each *physical* slot···63 struct list_head slot_list;6465 struct acpiphp_slot *acpi_slot;00000000066};6768/**···101 int type;102 int nr_slots;1030000104 u32 flags;105106 /* This bus (host bridge) or Secondary bus (PCI-to-PCI bridge) */···117 struct hpp_param hpp;118119 spinlock_t res_lock;000000120};121122···163164 u8 function; /* pci function# */165 u32 flags; /* see below */000000166};167168/**···242extern u8 acpiphp_get_latch_status (struct acpiphp_slot *slot);243extern u8 acpiphp_get_adapter_status (struct acpiphp_slot *slot);244extern u32 acpiphp_get_address (struct acpiphp_slot *slot);0000000000000000000245246/* variables */247extern int acpiphp_debug;
+5-4
drivers/pci/hotplug/acpiphp_core.c
···7 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)8 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)9 * Copyright (C) 2002,2003 NEC Corporation0010 *11 * All rights reserved.12 *···55static int num_slots;56static struct acpiphp_attention_info *attention_info;5758-#define DRIVER_VERSION "0.4"59-#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>"60#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver"6162MODULE_AUTHOR(DRIVER_AUTHOR);···283/**284 * get_address - get pci address of a slot285 * @hotplug_slot: slot to get status286- * @busdev: pointer to struct pci_busdev (seg, bus, dev)287- *288 */289static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)290{
···7 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)8 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)9 * Copyright (C) 2002,2003 NEC Corporation10+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)11+ * Copyright (C) 2003-2005 Hewlett Packard12 *13 * All rights reserved.14 *···53static int num_slots;54static struct acpiphp_attention_info *attention_info;5556+#define DRIVER_VERSION "0.5"57+#define DRIVER_AUTHOR "Greg Kroah-Hartman <gregkh@us.ibm.com>, Takayoshi Kochi <t-kochi@bq.jp.nec.com>, Matthew Wilcox <willy@hp.com>"58#define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver"5960MODULE_AUTHOR(DRIVER_AUTHOR);···281/**282 * get_address - get pci address of a slot283 * @hotplug_slot: slot to get status284+ * @value: pointer to struct pci_busdev (seg, bus, dev)0285 */286static int get_address(struct hotplug_slot *hotplug_slot, u32 *value)287{
+514-372
drivers/pci/hotplug/acpiphp_glue.c
···4 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)5 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)6 * Copyright (C) 2002,2003 NEC Corporation00007 *8 * All rights reserved.9 *···28 *29 * Send feedback to <t-kochi@bq.jp.nec.com>30 *000000000031 */3233#include <linux/init.h>···192193 bridge->nr_slots++;194195- dbg("found ACPI PCI Hotplug slot at PCI %02x:%02x Slot:%d\n",196- slot->bridge->bus, slot->device, slot->sun);0197 }198199 newfunc->slot = slot;200 list_add_tail(&newfunc->sibling, &slot->funcs);201202 /* associate corresponding pci_dev */203- newfunc->pci_dev = pci_find_slot(bridge->bus,204 PCI_DEVFN(device, function));205 if (newfunc->pci_dev) {206- if (acpiphp_init_func_resource(newfunc) < 0) {207- kfree(newfunc);208- return AE_ERROR;209- }210 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);211 }212···237 return count;238}239240-241-/* decode ACPI _CRS data and convert into our internal resource list242- * TBD: _TRA, etc.243- */244-static acpi_status245-decode_acpi_resource(struct acpi_resource *resource, void *context)246-{247- struct acpiphp_bridge *bridge = (struct acpiphp_bridge *) context;248- struct acpi_resource_address64 address;249- struct pci_resource *res;250-251- if (resource->id != ACPI_RSTYPE_ADDRESS16 &&252- resource->id != ACPI_RSTYPE_ADDRESS32 &&253- resource->id != ACPI_RSTYPE_ADDRESS64)254- return AE_OK;255-256- acpi_resource_to_address64(resource, &address);257-258- if (address.producer_consumer == ACPI_PRODUCER && address.address_length > 0) {259- dbg("resource type: %d: 0x%llx - 0x%llx\n", address.resource_type,260- (unsigned long long)address.min_address_range,261- (unsigned long long)address.max_address_range);262- res = acpiphp_make_resource(address.min_address_range,263- address.address_length);264- if (!res) {265- err("out of memory\n");266- return AE_OK;267- }268-269- switch (address.resource_type) {270- case ACPI_MEMORY_RANGE:271- if (address.attribute.memory.cache_attribute == ACPI_PREFETCHABLE_MEMORY) {272- res->next = bridge->p_mem_head;273- bridge->p_mem_head = res;274- } else {275- res->next = bridge->mem_head;276- bridge->mem_head = res;277- }278- break;279- case ACPI_IO_RANGE:280- res->next = bridge->io_head;281- bridge->io_head = res;282- break;283- case ACPI_BUS_NUMBER_RANGE:284- res->next = bridge->bus_head;285- bridge->bus_head = res;286- break;287- default:288- /* invalid type */289- kfree(res);290- break;291- }292- }293-294- return AE_OK;295-}296297/* decode ACPI 2.0 _HPP hot plug parameters */298static void decode_hpp(struct acpiphp_bridge *bridge)···301 /* decode ACPI 2.0 _HPP (hot plug parameters) */302 decode_hpp(bridge);303304- /* subtract all resources already allocated */305- acpiphp_detect_pci_resource(bridge);306-307 /* register all slot objects under this bridge */308 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,309 register_slot, bridge, NULL);310311 /* install notify handler */312- status = acpi_install_notify_handler(bridge->handle,0313 ACPI_SYSTEM_NOTIFY,314 handle_hotplug_event_bridge,315 bridge);316317- if (ACPI_FAILURE(status)) {318- err("failed to register interrupt notify handler\n");0319 }320321 list_add(&bridge->list, &bridge_list);322-323- dbg("Bridge resource:\n");324- acpiphp_dump_resource(bridge);325}326327328/* allocate and initialize host bridge data structure */329-static void add_host_bridge(acpi_handle *handle, int seg, int bus)330{331- acpi_status status;332 struct acpiphp_bridge *bridge;333334 bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);···334335 bridge->type = BRIDGE_TYPE_HOST;336 bridge->handle = handle;337- bridge->seg = seg;338- bridge->bus = bus;339340- bridge->pci_bus = pci_find_bus(seg, bus);341342 spin_lock_init(&bridge->res_lock);343-344- /* to be overridden when we decode _CRS */345- bridge->sub = bridge->bus;346-347- /* decode resources */348-349- status = acpi_walk_resources(handle, METHOD_NAME__CRS,350- decode_acpi_resource, bridge);351-352- if (ACPI_FAILURE(status)) {353- err("failed to decode bridge resources\n");354- kfree(bridge);355- return;356- }357-358- acpiphp_resource_sort_and_combine(&bridge->io_head);359- acpiphp_resource_sort_and_combine(&bridge->mem_head);360- acpiphp_resource_sort_and_combine(&bridge->p_mem_head);361- acpiphp_resource_sort_and_combine(&bridge->bus_head);362-363- dbg("ACPI _CRS resource:\n");364- acpiphp_dump_resource(bridge);365-366- if (bridge->bus_head) {367- bridge->bus = bridge->bus_head->base;368- bridge->sub = bridge->bus_head->base + bridge->bus_head->length - 1;369- }370371 init_bridge_misc(bridge);372}373374375/* allocate and initialize PCI-to-PCI bridge data structure */376-static void add_p2p_bridge(acpi_handle *handle, int seg, int bus, int dev, int fn)377{378 struct acpiphp_bridge *bridge;379- u8 tmp8;380- u16 tmp16;381- u64 base64, limit64;382- u32 base, limit, base32u, limit32u;383384 bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);385 if (bridge == NULL) {···358359 bridge->type = BRIDGE_TYPE_P2P;360 bridge->handle = handle;361- bridge->seg = seg;362363- bridge->pci_dev = pci_find_slot(bus, PCI_DEVFN(dev, fn));364- if (!bridge->pci_dev) {365- err("Can't get pci_dev\n");366- kfree(bridge);367- return;368- }369-370- bridge->pci_bus = bridge->pci_dev->subordinate;371 if (!bridge->pci_bus) {372 err("This is not a PCI-to-PCI bridge!\n");373- kfree(bridge);374- return;375 }376377 spin_lock_init(&bridge->res_lock);378379- bridge->bus = bridge->pci_bus->number;380- bridge->sub = bridge->pci_bus->subordinate;381-382- /*383- * decode resources under this P2P bridge384- */385-386- /* I/O resources */387- pci_read_config_byte(bridge->pci_dev, PCI_IO_BASE, &tmp8);388- base = tmp8;389- pci_read_config_byte(bridge->pci_dev, PCI_IO_LIMIT, &tmp8);390- limit = tmp8;391-392- switch (base & PCI_IO_RANGE_TYPE_MASK) {393- case PCI_IO_RANGE_TYPE_16:394- base = (base << 8) & 0xf000;395- limit = ((limit << 8) & 0xf000) + 0xfff;396- bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);397- if (!bridge->io_head) {398- err("out of memory\n");399- kfree(bridge);400- return;401- }402- dbg("16bit I/O range: %04x-%04x\n",403- (u32)bridge->io_head->base,404- (u32)(bridge->io_head->base + bridge->io_head->length - 1));405- break;406- case PCI_IO_RANGE_TYPE_32:407- pci_read_config_word(bridge->pci_dev, PCI_IO_BASE_UPPER16, &tmp16);408- base = ((u32)tmp16 << 16) | ((base << 8) & 0xf000);409- pci_read_config_word(bridge->pci_dev, PCI_IO_LIMIT_UPPER16, &tmp16);410- limit = (((u32)tmp16 << 16) | ((limit << 8) & 0xf000)) + 0xfff;411- bridge->io_head = acpiphp_make_resource((u64)base, limit - base + 1);412- if (!bridge->io_head) {413- err("out of memory\n");414- kfree(bridge);415- return;416- }417- dbg("32bit I/O range: %08x-%08x\n",418- (u32)bridge->io_head->base,419- (u32)(bridge->io_head->base + bridge->io_head->length - 1));420- break;421- case 0x0f:422- dbg("I/O space unsupported\n");423- break;424- default:425- warn("Unknown I/O range type\n");426- }427-428- /* Memory resources (mandatory for P2P bridge) */429- pci_read_config_word(bridge->pci_dev, PCI_MEMORY_BASE, &tmp16);430- base = (tmp16 & 0xfff0) << 16;431- pci_read_config_word(bridge->pci_dev, PCI_MEMORY_LIMIT, &tmp16);432- limit = ((tmp16 & 0xfff0) << 16) | 0xfffff;433- bridge->mem_head = acpiphp_make_resource((u64)base, limit - base + 1);434- if (!bridge->mem_head) {435- err("out of memory\n");436- kfree(bridge);437- return;438- }439- dbg("32bit Memory range: %08x-%08x\n",440- (u32)bridge->mem_head->base,441- (u32)(bridge->mem_head->base + bridge->mem_head->length-1));442-443- /* Prefetchable Memory resources (optional) */444- pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_BASE, &tmp16);445- base = tmp16;446- pci_read_config_word(bridge->pci_dev, PCI_PREF_MEMORY_LIMIT, &tmp16);447- limit = tmp16;448-449- switch (base & PCI_MEMORY_RANGE_TYPE_MASK) {450- case PCI_PREF_RANGE_TYPE_32:451- base = (base & 0xfff0) << 16;452- limit = ((limit & 0xfff0) << 16) | 0xfffff;453- bridge->p_mem_head = acpiphp_make_resource((u64)base, limit - base + 1);454- if (!bridge->p_mem_head) {455- err("out of memory\n");456- kfree(bridge);457- return;458- }459- dbg("32bit Prefetchable memory range: %08x-%08x\n",460- (u32)bridge->p_mem_head->base,461- (u32)(bridge->p_mem_head->base + bridge->p_mem_head->length - 1));462- break;463- case PCI_PREF_RANGE_TYPE_64:464- pci_read_config_dword(bridge->pci_dev, PCI_PREF_BASE_UPPER32, &base32u);465- pci_read_config_dword(bridge->pci_dev, PCI_PREF_LIMIT_UPPER32, &limit32u);466- base64 = ((u64)base32u << 32) | ((base & 0xfff0) << 16);467- limit64 = (((u64)limit32u << 32) | ((limit & 0xfff0) << 16)) + 0xfffff;468-469- bridge->p_mem_head = acpiphp_make_resource(base64, limit64 - base64 + 1);470- if (!bridge->p_mem_head) {471- err("out of memory\n");472- kfree(bridge);473- return;474- }475- dbg("64bit Prefetchable memory range: %08x%08x-%08x%08x\n",476- (u32)(bridge->p_mem_head->base >> 32),477- (u32)(bridge->p_mem_head->base & 0xffffffff),478- (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) >> 32),479- (u32)((bridge->p_mem_head->base + bridge->p_mem_head->length - 1) & 0xffffffff));480- break;481- case 0x0f:482- break;483- default:484- warn("Unknown prefetchale memory type\n");485- }486-487 init_bridge_misc(bridge);00000488}489490···383{384 acpi_status status;385 acpi_handle dummy_handle;386- unsigned long *segbus = context;387 unsigned long tmp;388- int seg, bus, device, function;389 struct pci_dev *dev;390-391- /* get PCI address */392- seg = (*segbus >> 8) & 0xff;393- bus = *segbus & 0xff;394395 status = acpi_get_handle(handle, "_ADR", &dummy_handle);396 if (ACPI_FAILURE(status))···401 device = (tmp >> 16) & 0xffff;402 function = tmp & 0xffff;403404- dev = pci_find_slot(bus, PCI_DEVFN(device, function));405406- if (!dev)407- return AE_OK;408-409- if (!dev->subordinate)410- return AE_OK;411412 /* check if this bridge has ejectable slots */413 if (detect_ejectable_slots(handle) > 0) {414 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));415- add_p2p_bridge(handle, seg, bus, device, function);416 }41700418 return AE_OK;419}420···425 unsigned long tmp;426 int seg, bus;427 acpi_handle dummy_handle;0428429 /* if the bridge doesn't have _STA, we assume it is always there */430 status = acpi_get_handle(handle, "_STA", &dummy_handle);···455 bus = 0;456 }457458- /* check if this bridge has ejectable slots */459- if (detect_ejectable_slots(handle) > 0) {460- dbg("found PCI host-bus bridge with hot-pluggable slots\n");461- add_host_bridge(handle, seg, bus);462 return 0;463 }464465- tmp = seg << 8 | bus;00000466467 /* search P2P bridges under this host bridge */468 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,469- find_p2p_bridge, &tmp, NULL);470471 if (ACPI_FAILURE(status))472 warn("find_p2p_bridge faied (error code = 0x%x)\n",status);···478 return 0;479}48000000000000000000000000000000000000000000000000000000000000481482static void remove_bridge(acpi_handle handle)483{484- /* No-op for now .. */000000000485}48600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000487488static int power_on_slot(struct acpiphp_slot *slot)489{···718 acpi_status status;719 struct acpiphp_func *func;720 struct list_head *l;721- struct acpi_object_list arg_list;722- union acpi_object arg;723724 int retval = 0;725···728 list_for_each (l, &slot->funcs) {729 func = list_entry(l, struct acpiphp_func, sibling);730731- if (func->pci_dev && (func->flags & FUNC_HAS_PS3)) {732 status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);733 if (ACPI_FAILURE(status)) {734 warn("%s: _PS3 failed\n", __FUNCTION__);735- retval = -1;736- goto err_exit;737- } else738- break;739- }740- }741-742- list_for_each (l, &slot->funcs) {743- func = list_entry(l, struct acpiphp_func, sibling);744-745- /* We don't want to call _EJ0 on non-existing functions. */746- if (func->pci_dev && (func->flags & FUNC_HAS_EJ0)) {747- /* _EJ0 method take one argument */748- arg_list.count = 1;749- arg_list.pointer = &arg;750- arg.type = ACPI_TYPE_INTEGER;751- arg.integer.value = 1;752-753- status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);754- if (ACPI_FAILURE(status)) {755- warn("%s: _EJ0 failed\n", __FUNCTION__);756 retval = -1;757 goto err_exit;758 } else···758 */759static int enable_device(struct acpiphp_slot *slot)760{761- u8 bus;762 struct pci_dev *dev;763- struct pci_bus *child;764 struct list_head *l;765 struct acpiphp_func *func;766 int retval = 0;767- int num;768769 if (slot->flags & SLOT_ENABLED)770 goto err_exit;771772 /* sanity check: dev should be NULL when hot-plugged in */773- dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));774 if (dev) {775 /* This case shouldn't happen */776 err("pci_dev structure already exists.\n");0777 retval = -1;778 goto err_exit;779 }780781- /* allocate resources to device */782- retval = acpiphp_configure_slot(slot);783- if (retval)784- goto err_exit;785-786- /* returned `dev' is the *first function* only! */787- num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));788- if (num)789- pci_bus_add_devices(slot->bridge->pci_bus);790- dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));791-792- if (!dev) {793 err("No new device found\n");794 retval = -1;795 goto err_exit;796 }797798- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {799- pci_read_config_byte(dev, PCI_SECONDARY_BUS, &bus);800- child = (struct pci_bus*) pci_add_new_bus(dev->bus, dev, bus);801- pci_do_scan_bus(child);00000802 }000803804 /* associate pci_dev to our representation */805 list_for_each (l, &slot->funcs) {806 func = list_entry(l, struct acpiphp_func, sibling);807-808- func->pci_dev = pci_find_slot(slot->bridge->bus,809- PCI_DEVFN(slot->device,810 func->function));811- if (!func->pci_dev)812- continue;813-814- /* configure device */815- retval = acpiphp_configure_function(func);816- if (retval)817- goto err_exit;818 }819820 slot->flags |= SLOT_ENABLED;821-822- dbg("Available resources:\n");823- acpiphp_dump_resource(slot->bridge);824825 err_exit:826 return retval;···828829 list_for_each (l, &slot->funcs) {830 func = list_entry(l, struct acpiphp_func, sibling);00831832- if (func->pci_dev)833- acpiphp_unconfigure_function(func);0834 }835836 slot->flags &= (~SLOT_ENABLED);···885}886887/**000000000000000000000000000000000888 * acpiphp_check_bridge - re-enumerate devices889 *890 * Iterate over all slots under this bridge and make sure that if a···940 if (retval) {941 err("Error occurred in disabling\n");942 goto err_exit;00943 }944 disabled++;945 } else {···960961 err_exit:962 return retval;000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000963}964965/*···1120 char objname[64];1121 struct acpi_buffer buffer = { .length = sizeof(objname),1122 .pointer = objname };011231124- bridge = (struct acpiphp_bridge *)context;000000000011251126 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);1127···1180 }1181}11821183-1184/**1185 * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)1186 *···1222 case ACPI_NOTIFY_EJECT_REQUEST:1223 /* request device eject */1224 dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);1225- acpiphp_disable_slot(func->slot);01226 break;12271228 default:···1232 }1233}12340000000000000000000000000000000000000000012351236static struct acpi_pci_driver acpi_pci_hp_driver = {1237 .add = add_bridge,···1285 */1286int __init acpiphp_glue_init(void)1287{1288- int num;12891290- if (list_empty(&pci_root_buses))1291- return -1;1292-1293- num = acpi_pci_register_driver(&acpi_pci_hp_driver);12941295 if (num <= 0)1296 return -1;0012971298 return 0;1299}···1306 */1307void __exit acpiphp_glue_exit(void)1308{1309- struct list_head *l1, *l2, *n1, *n2;1310- struct acpiphp_bridge *bridge;1311- struct acpiphp_slot *slot, *next;1312- struct acpiphp_func *func;1313- acpi_status status;1314-1315- list_for_each_safe (l1, n1, &bridge_list) {1316- bridge = (struct acpiphp_bridge *)l1;1317- slot = bridge->slots;1318- while (slot) {1319- next = slot->next;1320- list_for_each_safe (l2, n2, &slot->funcs) {1321- func = list_entry(l2, struct acpiphp_func, sibling);1322- acpiphp_free_resource(&func->io_head);1323- acpiphp_free_resource(&func->mem_head);1324- acpiphp_free_resource(&func->p_mem_head);1325- acpiphp_free_resource(&func->bus_head);1326- status = acpi_remove_notify_handler(func->handle,1327- ACPI_SYSTEM_NOTIFY,1328- handle_hotplug_event_func);1329- if (ACPI_FAILURE(status))1330- err("failed to remove notify handler\n");1331- kfree(func);1332- }1333- kfree(slot);1334- slot = next;1335- }1336- status = acpi_remove_notify_handler(bridge->handle, ACPI_SYSTEM_NOTIFY,1337- handle_hotplug_event_bridge);1338- if (ACPI_FAILURE(status))1339- err("failed to remove notify handler\n");1340-1341- acpiphp_free_resource(&bridge->io_head);1342- acpiphp_free_resource(&bridge->mem_head);1343- acpiphp_free_resource(&bridge->p_mem_head);1344- acpiphp_free_resource(&bridge->bus_head);1345-1346- kfree(bridge);1347- }1348-1349 acpi_pci_unregister_driver(&acpi_pci_hp_driver);1350}1351···13231324 list_for_each (node, &bridge_list) {1325 bridge = (struct acpiphp_bridge *)node;1326- dbg("Bus%d %dslot(s)\n", bridge->bus, bridge->nr_slots);0001327 num_slots += bridge->nr_slots;1328 }13291330- dbg("Total %dslots\n", num_slots);1331 return num_slots;1332}1333···1407 return retval;1408}14091410-1411/**1412 * acpiphp_disable_slot - power off slot1413 */···1426 if (retval)1427 goto err_exit;14281429- acpiphp_resource_sort_and_combine(&slot->bridge->io_head);1430- acpiphp_resource_sort_and_combine(&slot->bridge->mem_head);1431- acpiphp_resource_sort_and_combine(&slot->bridge->p_mem_head);1432- acpiphp_resource_sort_and_combine(&slot->bridge->bus_head);1433- dbg("Available resources:\n");1434- acpiphp_dump_resource(slot->bridge);1435-1436 err_exit:1437 up(&slot->crit_sect);1438 return retval;···1438 */1439u8 acpiphp_get_power_status(struct acpiphp_slot *slot)1440{1441- unsigned int sta;1442-1443- sta = get_slot_status(slot);1444-1445- return (sta & ACPI_STA_ENABLED) ? 1 : 0;1446}14471448···1476u32 acpiphp_get_address(struct acpiphp_slot *slot)1477{1478 u32 address;014791480- address = ((slot->bridge->seg) << 16) |1481- ((slot->bridge->bus) << 8) |1482 slot->device;14831484 return address;
···4 * Copyright (C) 2002,2003 Takayoshi Kochi (t-kochi@bq.jp.nec.com)5 * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)6 * Copyright (C) 2002,2003 NEC Corporation7+ * Copyright (C) 2003-2005 Matthew Wilcox (matthew.wilcox@hp.com)8+ * Copyright (C) 2003-2005 Hewlett Packard9+ * Copyright (C) 2005 Rajesh Shah (rajesh.shah@intel.com)10+ * Copyright (C) 2005 Intel Corporation11 *12 * All rights reserved.13 *···24 *25 * Send feedback to <t-kochi@bq.jp.nec.com>26 *27+ */28+29+/*30+ * Lifetime rules for pci_dev:31+ * - The one in acpiphp_func has its refcount elevated by pci_get_slot()32+ * when the driver is loaded or when an insertion event occurs. It loses33+ * a refcount when its ejected or the driver unloads.34+ * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot()35+ * when the bridge is scanned and it loses a refcount when the bridge36+ * is removed.37 */3839#include <linux/init.h>···178179 bridge->nr_slots++;180181+ dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n",182+ slot->sun, pci_domain_nr(bridge->pci_bus),183+ bridge->pci_bus->number, slot->device);184 }185186 newfunc->slot = slot;187 list_add_tail(&newfunc->sibling, &slot->funcs);188189 /* associate corresponding pci_dev */190+ newfunc->pci_dev = pci_get_slot(bridge->pci_bus,191 PCI_DEVFN(device, function));192 if (newfunc->pci_dev) {0000193 slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);194 }195···226 return count;227}22800000000000000000000000000000000000000000000000000000000229230/* decode ACPI 2.0 _HPP hot plug parameters */231static void decode_hpp(struct acpiphp_bridge *bridge)···346 /* decode ACPI 2.0 _HPP (hot plug parameters) */347 decode_hpp(bridge);348000349 /* register all slot objects under this bridge */350 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, bridge->handle, (u32)1,351 register_slot, bridge, NULL);352353 /* install notify handler */354+ if (bridge->type != BRIDGE_TYPE_HOST) {355+ status = acpi_install_notify_handler(bridge->handle,356 ACPI_SYSTEM_NOTIFY,357 handle_hotplug_event_bridge,358 bridge);359360+ if (ACPI_FAILURE(status)) {361+ err("failed to register interrupt notify handler\n");362+ }363 }364365 list_add(&bridge->list, &bridge_list);000366}367368369/* allocate and initialize host bridge data structure */370+static void add_host_bridge(acpi_handle *handle, struct pci_bus *pci_bus)371{0372 struct acpiphp_bridge *bridge;373374 bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);···384385 bridge->type = BRIDGE_TYPE_HOST;386 bridge->handle = handle;00387388+ bridge->pci_bus = pci_bus;389390 spin_lock_init(&bridge->res_lock);000000000000000000000000000391392 init_bridge_misc(bridge);393}394395396/* allocate and initialize PCI-to-PCI bridge data structure */397+static void add_p2p_bridge(acpi_handle *handle, struct pci_dev *pci_dev)398{399 struct acpiphp_bridge *bridge;0000400401 bridge = kmalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);402 if (bridge == NULL) {···441442 bridge->type = BRIDGE_TYPE_P2P;443 bridge->handle = handle;0444445+ bridge->pci_dev = pci_dev_get(pci_dev);446+ bridge->pci_bus = pci_dev->subordinate;000000447 if (!bridge->pci_bus) {448 err("This is not a PCI-to-PCI bridge!\n");449+ goto err;0450 }451452 spin_lock_init(&bridge->res_lock);453000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000454 init_bridge_misc(bridge);455+ return;456+ err:457+ pci_dev_put(pci_dev);458+ kfree(bridge);459+ return;460}461462···577{578 acpi_status status;579 acpi_handle dummy_handle;0580 unsigned long tmp;581+ int device, function;582 struct pci_dev *dev;583+ struct pci_bus *pci_bus = context;000584585 status = acpi_get_handle(handle, "_ADR", &dummy_handle);586 if (ACPI_FAILURE(status))···599 device = (tmp >> 16) & 0xffff;600 function = tmp & 0xffff;601602+ dev = pci_get_slot(pci_bus, PCI_DEVFN(device, function));603604+ if (!dev || !dev->subordinate)605+ goto out;000606607 /* check if this bridge has ejectable slots */608 if (detect_ejectable_slots(handle) > 0) {609 dbg("found PCI-to-PCI bridge at PCI %s\n", pci_name(dev));610+ add_p2p_bridge(handle, dev);611 }612613+ out:614+ pci_dev_put(dev);615 return AE_OK;616}617···624 unsigned long tmp;625 int seg, bus;626 acpi_handle dummy_handle;627+ struct pci_bus *pci_bus;628629 /* if the bridge doesn't have _STA, we assume it is always there */630 status = acpi_get_handle(handle, "_STA", &dummy_handle);···653 bus = 0;654 }655656+ pci_bus = pci_find_bus(seg, bus);657+ if (!pci_bus) {658+ err("Can't find bus %04x:%02x\n", seg, bus);0659 return 0;660 }661662+ /* check if this bridge has ejectable slots */663+ if (detect_ejectable_slots(handle) > 0) {664+ dbg("found PCI host-bus bridge with hot-pluggable slots\n");665+ add_host_bridge(handle, pci_bus);666+ return 0;667+ }668669 /* search P2P bridges under this host bridge */670 status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,671+ find_p2p_bridge, pci_bus, NULL);672673 if (ACPI_FAILURE(status))674 warn("find_p2p_bridge faied (error code = 0x%x)\n",status);···672 return 0;673}674675+static struct acpiphp_bridge *acpiphp_handle_to_bridge(acpi_handle handle)676+{677+ struct list_head *head;678+ list_for_each(head, &bridge_list) {679+ struct acpiphp_bridge *bridge = list_entry(head,680+ struct acpiphp_bridge, list);681+ if (bridge->handle == handle)682+ return bridge;683+ }684+685+ return NULL;686+}687+688+static void cleanup_bridge(struct acpiphp_bridge *bridge)689+{690+ struct list_head *list, *tmp;691+ struct acpiphp_slot *slot;692+ acpi_status status;693+ acpi_handle handle = bridge->handle;694+695+ status = acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,696+ handle_hotplug_event_bridge);697+ if (ACPI_FAILURE(status))698+ err("failed to remove notify handler\n");699+700+ slot = bridge->slots;701+ while (slot) {702+ struct acpiphp_slot *next = slot->next;703+ list_for_each_safe (list, tmp, &slot->funcs) {704+ struct acpiphp_func *func;705+ func = list_entry(list, struct acpiphp_func, sibling);706+ status = acpi_remove_notify_handler(func->handle,707+ ACPI_SYSTEM_NOTIFY,708+ handle_hotplug_event_func);709+ if (ACPI_FAILURE(status))710+ err("failed to remove notify handler\n");711+ pci_dev_put(func->pci_dev);712+ list_del(list);713+ kfree(func);714+ }715+ kfree(slot);716+ slot = next;717+ }718+719+ pci_dev_put(bridge->pci_dev);720+ list_del(&bridge->list);721+ kfree(bridge);722+}723+724+static acpi_status725+cleanup_p2p_bridge(acpi_handle handle, u32 lvl, void *context, void **rv)726+{727+ struct acpiphp_bridge *bridge;728+729+ if (!(bridge = acpiphp_handle_to_bridge(handle)))730+ return AE_OK;731+ cleanup_bridge(bridge);732+ return AE_OK;733+}734735static void remove_bridge(acpi_handle handle)736{737+ struct acpiphp_bridge *bridge;738+739+ bridge = acpiphp_handle_to_bridge(handle);740+ if (bridge) {741+ cleanup_bridge(bridge);742+ } else {743+ /* clean-up p2p bridges under this host bridge */744+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,745+ (u32)1, cleanup_p2p_bridge, NULL, NULL);746+ }747}748749+static struct pci_dev * get_apic_pci_info(acpi_handle handle)750+{751+ struct acpi_pci_id id;752+ struct pci_bus *bus;753+ struct pci_dev *dev;754+755+ if (ACPI_FAILURE(acpi_get_pci_id(handle, &id)))756+ return NULL;757+758+ bus = pci_find_bus(id.segment, id.bus);759+ if (!bus)760+ return NULL;761+762+ dev = pci_get_slot(bus, PCI_DEVFN(id.device, id.function));763+ if (!dev)764+ return NULL;765+766+ if ((dev->class != PCI_CLASS_SYSTEM_PIC_IOAPIC) &&767+ (dev->class != PCI_CLASS_SYSTEM_PIC_IOXAPIC))768+ {769+ pci_dev_put(dev);770+ return NULL;771+ }772+773+ return dev;774+}775+776+static int get_gsi_base(acpi_handle handle, u32 *gsi_base)777+{778+ acpi_status status;779+ int result = -1;780+ unsigned long gsb;781+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};782+ union acpi_object *obj;783+ void *table;784+785+ status = acpi_evaluate_integer(handle, "_GSB", NULL, &gsb);786+ if (ACPI_SUCCESS(status)) {787+ *gsi_base = (u32)gsb;788+ return 0;789+ }790+791+ status = acpi_evaluate_object(handle, "_MAT", NULL, &buffer);792+ if (ACPI_FAILURE(status) || !buffer.length || !buffer.pointer)793+ return -1;794+795+ obj = buffer.pointer;796+ if (obj->type != ACPI_TYPE_BUFFER)797+ goto out;798+799+ table = obj->buffer.pointer;800+ switch (((acpi_table_entry_header *)table)->type) {801+ case ACPI_MADT_IOSAPIC:802+ *gsi_base = ((struct acpi_table_iosapic *)table)->global_irq_base;803+ result = 0;804+ break;805+ case ACPI_MADT_IOAPIC:806+ *gsi_base = ((struct acpi_table_ioapic *)table)->global_irq_base;807+ result = 0;808+ break;809+ default:810+ break;811+ }812+ out:813+ acpi_os_free(buffer.pointer);814+ return result;815+}816+817+static acpi_status818+ioapic_add(acpi_handle handle, u32 lvl, void *context, void **rv)819+{820+ acpi_status status;821+ unsigned long sta;822+ acpi_handle tmp;823+ struct pci_dev *pdev;824+ u32 gsi_base;825+ u64 phys_addr;826+827+ /* Evaluate _STA if present */828+ status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);829+ if (ACPI_SUCCESS(status) && sta != ACPI_STA_ALL)830+ return AE_CTRL_DEPTH;831+832+ /* Scan only PCI bus scope */833+ status = acpi_get_handle(handle, "_HID", &tmp);834+ if (ACPI_SUCCESS(status))835+ return AE_CTRL_DEPTH;836+837+ if (get_gsi_base(handle, &gsi_base))838+ return AE_OK;839+840+ pdev = get_apic_pci_info(handle);841+ if (!pdev)842+ return AE_OK;843+844+ if (pci_enable_device(pdev)) {845+ pci_dev_put(pdev);846+ return AE_OK;847+ }848+849+ pci_set_master(pdev);850+851+ if (pci_request_region(pdev, 0, "I/O APIC(acpiphp)")) {852+ pci_disable_device(pdev);853+ pci_dev_put(pdev);854+ return AE_OK;855+ }856+857+ phys_addr = pci_resource_start(pdev, 0);858+ if (acpi_register_ioapic(handle, phys_addr, gsi_base)) {859+ pci_release_region(pdev, 0);860+ pci_disable_device(pdev);861+ pci_dev_put(pdev);862+ return AE_OK;863+ }864+865+ return AE_OK;866+}867+868+static int acpiphp_configure_ioapics(acpi_handle handle)869+{870+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle,871+ ACPI_UINT32_MAX, ioapic_add, NULL, NULL);872+ return 0;873+}874875static int power_on_slot(struct acpiphp_slot *slot)876{···719 acpi_status status;720 struct acpiphp_func *func;721 struct list_head *l;00722723 int retval = 0;724···731 list_for_each (l, &slot->funcs) {732 func = list_entry(l, struct acpiphp_func, sibling);733734+ if (func->flags & FUNC_HAS_PS3) {735 status = acpi_evaluate_object(func->handle, "_PS3", NULL, NULL);736 if (ACPI_FAILURE(status)) {737 warn("%s: _PS3 failed\n", __FUNCTION__);000000000000000000000738 retval = -1;739 goto err_exit;740 } else···782 */783static int enable_device(struct acpiphp_slot *slot)784{0785 struct pci_dev *dev;786+ struct pci_bus *bus = slot->bridge->pci_bus;787 struct list_head *l;788 struct acpiphp_func *func;789 int retval = 0;790+ int num, max, pass;791792 if (slot->flags & SLOT_ENABLED)793 goto err_exit;794795 /* sanity check: dev should be NULL when hot-plugged in */796+ dev = pci_get_slot(bus, PCI_DEVFN(slot->device, 0));797 if (dev) {798 /* This case shouldn't happen */799 err("pci_dev structure already exists.\n");800+ pci_dev_put(dev);801 retval = -1;802 goto err_exit;803 }804805+ num = pci_scan_slot(bus, PCI_DEVFN(slot->device, 0));806+ if (num == 0) {0000000000807 err("No new device found\n");808 retval = -1;809 goto err_exit;810 }811812+ max = bus->secondary;813+ for (pass = 0; pass < 2; pass++) {814+ list_for_each_entry(dev, &bus->devices, bus_list) {815+ if (PCI_SLOT(dev->devfn) != slot->device)816+ continue;817+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||818+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)819+ max = pci_scan_bridge(bus, dev, max, pass);820+ }821 }822+823+ pci_bus_assign_resources(bus);824+ pci_bus_add_devices(bus);825826 /* associate pci_dev to our representation */827 list_for_each (l, &slot->funcs) {828 func = list_entry(l, struct acpiphp_func, sibling);829+ func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device,00830 func->function));0000000831 }832833 slot->flags |= SLOT_ENABLED;000834835 err_exit:836 return retval;···866867 list_for_each (l, &slot->funcs) {868 func = list_entry(l, struct acpiphp_func, sibling);869+ if (!func->pci_dev)870+ continue;871872+ pci_remove_bus_device(func->pci_dev);873+ pci_dev_put(func->pci_dev);874+ func->pci_dev = NULL;875 }876877 slot->flags &= (~SLOT_ENABLED);···920}921922/**923+ * acpiphp_eject_slot - physically eject the slot924+ */925+static int acpiphp_eject_slot(struct acpiphp_slot *slot)926+{927+ acpi_status status;928+ struct acpiphp_func *func;929+ struct list_head *l;930+ struct acpi_object_list arg_list;931+ union acpi_object arg;932+933+ list_for_each (l, &slot->funcs) {934+ func = list_entry(l, struct acpiphp_func, sibling);935+936+ /* We don't want to call _EJ0 on non-existing functions. */937+ if ((func->flags & FUNC_HAS_EJ0)) {938+ /* _EJ0 method take one argument */939+ arg_list.count = 1;940+ arg_list.pointer = &arg;941+ arg.type = ACPI_TYPE_INTEGER;942+ arg.integer.value = 1;943+944+ status = acpi_evaluate_object(func->handle, "_EJ0", &arg_list, NULL);945+ if (ACPI_FAILURE(status)) {946+ warn("%s: _EJ0 failed\n", __FUNCTION__);947+ return -1;948+ } else949+ break;950+ }951+ }952+ return 0;953+}954+955+/**956 * acpiphp_check_bridge - re-enumerate devices957 *958 * Iterate over all slots under this bridge and make sure that if a···942 if (retval) {943 err("Error occurred in disabling\n");944 goto err_exit;945+ } else {946+ acpiphp_eject_slot(slot);947 }948 disabled++;949 } else {···960961 err_exit:962 return retval;963+}964+965+static void program_hpp(struct pci_dev *dev, struct acpiphp_bridge *bridge)966+{967+ u16 pci_cmd, pci_bctl;968+ struct pci_dev *cdev;969+970+ /* Program hpp values for this device */971+ if (!(dev->hdr_type == PCI_HEADER_TYPE_NORMAL ||972+ (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE &&973+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))974+ return;975+ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,976+ bridge->hpp.cache_line_size);977+ pci_write_config_byte(dev, PCI_LATENCY_TIMER,978+ bridge->hpp.latency_timer);979+ pci_read_config_word(dev, PCI_COMMAND, &pci_cmd);980+ if (bridge->hpp.enable_SERR)981+ pci_cmd |= PCI_COMMAND_SERR;982+ else983+ pci_cmd &= ~PCI_COMMAND_SERR;984+ if (bridge->hpp.enable_PERR)985+ pci_cmd |= PCI_COMMAND_PARITY;986+ else987+ pci_cmd &= ~PCI_COMMAND_PARITY;988+ pci_write_config_word(dev, PCI_COMMAND, pci_cmd);989+990+ /* Program bridge control value and child devices */991+ if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {992+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER,993+ bridge->hpp.latency_timer);994+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &pci_bctl);995+ if (bridge->hpp.enable_SERR)996+ pci_bctl |= PCI_BRIDGE_CTL_SERR;997+ else998+ pci_bctl &= ~PCI_BRIDGE_CTL_SERR;999+ if (bridge->hpp.enable_PERR)1000+ pci_bctl |= PCI_BRIDGE_CTL_PARITY;1001+ else1002+ pci_bctl &= ~PCI_BRIDGE_CTL_PARITY;1003+ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, pci_bctl);1004+ if (dev->subordinate) {1005+ list_for_each_entry(cdev, &dev->subordinate->devices,1006+ bus_list)1007+ program_hpp(cdev, bridge);1008+ }1009+ }1010+}1011+1012+static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus)1013+{1014+ struct acpiphp_bridge bridge;1015+ struct pci_dev *dev;1016+1017+ memset(&bridge, 0, sizeof(bridge));1018+ bridge.handle = handle;1019+ decode_hpp(&bridge);1020+ list_for_each_entry(dev, &bus->devices, bus_list)1021+ program_hpp(dev, &bridge);1022+1023+}1024+1025+/*1026+ * Remove devices for which we could not assign resources, call1027+ * arch specific code to fix-up the bus1028+ */1029+static void acpiphp_sanitize_bus(struct pci_bus *bus)1030+{1031+ struct pci_dev *dev;1032+ int i;1033+ unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;1034+1035+ list_for_each_entry(dev, &bus->devices, bus_list) {1036+ for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {1037+ struct resource *res = &dev->resource[i];1038+ if ((res->flags & type_mask) && !res->start &&1039+ res->end) {1040+ /* Could not assign a required resources1041+ * for this device, remove it */1042+ pci_remove_bus_device(dev);1043+ break;1044+ }1045+ }1046+ }1047+}1048+1049+/* Program resources in newly inserted bridge */1050+static int acpiphp_configure_bridge (acpi_handle handle)1051+{1052+ struct acpi_pci_id pci_id;1053+ struct pci_bus *bus;1054+1055+ if (ACPI_FAILURE(acpi_get_pci_id(handle, &pci_id))) {1056+ err("cannot get PCI domain and bus number for bridge\n");1057+ return -EINVAL;1058+ }1059+ bus = pci_find_bus(pci_id.segment, pci_id.bus);1060+ if (!bus) {1061+ err("cannot find bus %d:%d\n",1062+ pci_id.segment, pci_id.bus);1063+ return -EINVAL;1064+ }1065+1066+ pci_bus_size_bridges(bus);1067+ pci_bus_assign_resources(bus);1068+ acpiphp_sanitize_bus(bus);1069+ acpiphp_set_hpp_values(handle, bus);1070+ pci_enable_bridges(bus);1071+ acpiphp_configure_ioapics(handle);1072+ return 0;1073+}1074+1075+static void handle_bridge_insertion(acpi_handle handle, u32 type)1076+{1077+ struct acpi_device *device, *pdevice;1078+ acpi_handle phandle;1079+1080+ if ((type != ACPI_NOTIFY_BUS_CHECK) &&1081+ (type != ACPI_NOTIFY_DEVICE_CHECK)) {1082+ err("unexpected notification type %d\n", type);1083+ return;1084+ }1085+1086+ acpi_get_parent(handle, &phandle);1087+ if (acpi_bus_get_device(phandle, &pdevice)) {1088+ dbg("no parent device, assuming NULL\n");1089+ pdevice = NULL;1090+ }1091+ if (acpi_bus_add(&device, pdevice, handle, ACPI_BUS_TYPE_DEVICE)) {1092+ err("cannot add bridge to acpi list\n");1093+ return;1094+ }1095+ if (!acpiphp_configure_bridge(handle) &&1096+ !acpi_bus_start(device))1097+ add_bridge(handle);1098+ else1099+ err("cannot configure and start bridge\n");1100+1101}11021103/*···982 char objname[64];983 struct acpi_buffer buffer = { .length = sizeof(objname),984 .pointer = objname };985+ struct acpi_device *device;986987+ if (acpi_bus_get_device(handle, &device)) {988+ /* This bridge must have just been physically inserted */989+ handle_bridge_insertion(handle, type);990+ return;991+ }992+993+ bridge = acpiphp_handle_to_bridge(handle);994+ if (!bridge) {995+ err("cannot get bridge info\n");996+ return;997+ }998999 acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);1000···1031 }1032}103301034/**1035 * handle_hotplug_event_func - handle ACPI event on functions (i.e. slots)1036 *···1074 case ACPI_NOTIFY_EJECT_REQUEST:1075 /* request device eject */1076 dbg("%s: Device eject notify on %s\n", __FUNCTION__, objname);1077+ if (!(acpiphp_disable_slot(func->slot)))1078+ acpiphp_eject_slot(func->slot);1079 break;10801081 default:···1083 }1084}10851086+static int is_root_bridge(acpi_handle handle)1087+{1088+ acpi_status status;1089+ struct acpi_device_info *info;1090+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};1091+ int i;1092+1093+ status = acpi_get_object_info(handle, &buffer);1094+ if (ACPI_SUCCESS(status)) {1095+ info = buffer.pointer;1096+ if ((info->valid & ACPI_VALID_HID) &&1097+ !strcmp(PCI_ROOT_HID_STRING,1098+ info->hardware_id.value)) {1099+ acpi_os_free(buffer.pointer);1100+ return 1;1101+ }1102+ if (info->valid & ACPI_VALID_CID) {1103+ for (i=0; i < info->compatibility_id.count; i++) {1104+ if (!strcmp(PCI_ROOT_HID_STRING,1105+ info->compatibility_id.id[i].value)) {1106+ acpi_os_free(buffer.pointer);1107+ return 1;1108+ }1109+ }1110+ }1111+ }1112+ return 0;1113+}1114+1115+static acpi_status1116+find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)1117+{1118+ int *count = (int *)context;1119+1120+ if (is_root_bridge(handle)) {1121+ acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,1122+ handle_hotplug_event_bridge, NULL);1123+ (*count)++;1124+ }1125+ return AE_OK ;1126+}11271128static struct acpi_pci_driver acpi_pci_hp_driver = {1129 .add = add_bridge,···1095 */1096int __init acpiphp_glue_init(void)1097{1098+ int num = 0;10991100+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,1101+ ACPI_UINT32_MAX, find_root_bridges, &num, NULL);0011021103 if (num <= 0)1104 return -1;1105+ else1106+ acpi_pci_register_driver(&acpi_pci_hp_driver);11071108 return 0;1109}···1116 */1117void __exit acpiphp_glue_exit(void)1118{00000000000000000000000000000000000000001119 acpi_pci_unregister_driver(&acpi_pci_hp_driver);1120}1121···11731174 list_for_each (node, &bridge_list) {1175 bridge = (struct acpiphp_bridge *)node;1176+ dbg("Bus %04x:%02x has %d slot%s\n",1177+ pci_domain_nr(bridge->pci_bus),1178+ bridge->pci_bus->number, bridge->nr_slots,1179+ bridge->nr_slots == 1 ? "" : "s");1180 num_slots += bridge->nr_slots;1181 }11821183+ dbg("Total %d slots\n", num_slots);1184 return num_slots;1185}1186···1254 return retval;1255}125601257/**1258 * acpiphp_disable_slot - power off slot1259 */···1274 if (retval)1275 goto err_exit;127600000001277 err_exit:1278 up(&slot->crit_sect);1279 return retval;···1293 */1294u8 acpiphp_get_power_status(struct acpiphp_slot *slot)1295{1296+ return (slot->flags & SLOT_POWEREDON);00001297}12981299···1335u32 acpiphp_get_address(struct acpiphp_slot *slot)1336{1337 u32 address;1338+ struct pci_bus *pci_bus = slot->bridge->pci_bus;13391340+ address = (pci_domain_nr(pci_bus) << 16) |1341+ (pci_bus->number << 8) |1342 slot->device;13431344 return address;
-449
drivers/pci/hotplug/acpiphp_pci.c
···1-/*2- * ACPI PCI HotPlug PCI configuration space management3- *4- * Copyright (C) 1995,2001 Compaq Computer Corporation5- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)6- * Copyright (C) 2001,2002 IBM Corp.7- * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)8- * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)9- * Copyright (C) 2002 NEC Corporation10- *11- * All rights reserved.12- *13- * This program is free software; you can redistribute it and/or modify14- * it under the terms of the GNU General Public License as published by15- * the Free Software Foundation; either version 2 of the License, or (at16- * your option) any later version.17- *18- * This program is distributed in the hope that it will be useful, but19- * WITHOUT ANY WARRANTY; without even the implied warranty of20- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or21- * NON INFRINGEMENT. See the GNU General Public License for more22- * details.23- *24- * You should have received a copy of the GNU General Public License25- * along with this program; if not, write to the Free Software26- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.27- *28- * Send feedback to <t-kochi@bq.jp.nec.com>29- *30- */31-32-#include <linux/init.h>33-#include <linux/module.h>34-35-#include <linux/kernel.h>36-#include <linux/pci.h>37-#include <linux/acpi.h>38-#include "../pci.h"39-#include "pci_hotplug.h"40-#include "acpiphp.h"41-42-#define MY_NAME "acpiphp_pci"43-44-45-/* allocate mem/pmem/io resource to a new function */46-static int init_config_space (struct acpiphp_func *func)47-{48- u32 bar, len;49- u32 address[] = {50- PCI_BASE_ADDRESS_0,51- PCI_BASE_ADDRESS_1,52- PCI_BASE_ADDRESS_2,53- PCI_BASE_ADDRESS_3,54- PCI_BASE_ADDRESS_4,55- PCI_BASE_ADDRESS_5,56- 057- };58- int count;59- struct acpiphp_bridge *bridge;60- struct pci_resource *res;61- struct pci_bus *pbus;62- int bus, device, function;63- unsigned int devfn;64- u16 tmp;65-66- bridge = func->slot->bridge;67- pbus = bridge->pci_bus;68- bus = bridge->bus;69- device = func->slot->device;70- function = func->function;71- devfn = PCI_DEVFN(device, function);72-73- for (count = 0; address[count]; count++) { /* for 6 BARs */74- pci_bus_write_config_dword(pbus, devfn,75- address[count], 0xFFFFFFFF);76- pci_bus_read_config_dword(pbus, devfn, address[count], &bar);77-78- if (!bar) /* This BAR is not implemented */79- continue;80-81- dbg("Device %02x.%02x BAR %d wants %x\n", device, function, count, bar);82-83- if (bar & PCI_BASE_ADDRESS_SPACE_IO) {84- /* This is IO */85-86- len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);87- len = len & ~(len - 1);88-89- dbg("len in IO %x, BAR %d\n", len, count);90-91- spin_lock(&bridge->res_lock);92- res = acpiphp_get_io_resource(&bridge->io_head, len);93- spin_unlock(&bridge->res_lock);94-95- if (!res) {96- err("cannot allocate requested io for %02x:%02x.%d len %x\n",97- bus, device, function, len);98- return -1;99- }100- pci_bus_write_config_dword(pbus, devfn,101- address[count],102- (u32)res->base);103- res->next = func->io_head;104- func->io_head = res;105-106- } else {107- /* This is Memory */108- if (bar & PCI_BASE_ADDRESS_MEM_PREFETCH) {109- /* pfmem */110-111- len = bar & 0xFFFFFFF0;112- len = ~len + 1;113-114- dbg("len in PFMEM %x, BAR %d\n", len, count);115-116- spin_lock(&bridge->res_lock);117- res = acpiphp_get_resource(&bridge->p_mem_head, len);118- spin_unlock(&bridge->res_lock);119-120- if (!res) {121- err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",122- bus, device, function, len);123- return -1;124- }125-126- pci_bus_write_config_dword(pbus, devfn,127- address[count],128- (u32)res->base);129-130- if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */131- dbg("inside the pfmem 64 case, count %d\n", count);132- count += 1;133- pci_bus_write_config_dword(pbus, devfn,134- address[count],135- (u32)(res->base >> 32));136- }137-138- res->next = func->p_mem_head;139- func->p_mem_head = res;140-141- } else {142- /* regular memory */143-144- len = bar & 0xFFFFFFF0;145- len = ~len + 1;146-147- dbg("len in MEM %x, BAR %d\n", len, count);148-149- spin_lock(&bridge->res_lock);150- res = acpiphp_get_resource(&bridge->mem_head, len);151- spin_unlock(&bridge->res_lock);152-153- if (!res) {154- err("cannot allocate requested pfmem for %02x:%02x.%d len %x\n",155- bus, device, function, len);156- return -1;157- }158-159- pci_bus_write_config_dword(pbus, devfn,160- address[count],161- (u32)res->base);162-163- if (bar & PCI_BASE_ADDRESS_MEM_TYPE_64) {164- /* takes up another dword */165- dbg("inside mem 64 case, reg. mem, count %d\n", count);166- count += 1;167- pci_bus_write_config_dword(pbus, devfn,168- address[count],169- (u32)(res->base >> 32));170- }171-172- res->next = func->mem_head;173- func->mem_head = res;174-175- }176- }177- }178-179- /* disable expansion rom */180- pci_bus_write_config_dword(pbus, devfn, PCI_ROM_ADDRESS, 0x00000000);181-182- /* set PCI parameters from _HPP */183- pci_bus_write_config_byte(pbus, devfn, PCI_CACHE_LINE_SIZE,184- bridge->hpp.cache_line_size);185- pci_bus_write_config_byte(pbus, devfn, PCI_LATENCY_TIMER,186- bridge->hpp.latency_timer);187-188- pci_bus_read_config_word(pbus, devfn, PCI_COMMAND, &tmp);189- if (bridge->hpp.enable_SERR)190- tmp |= PCI_COMMAND_SERR;191- if (bridge->hpp.enable_PERR)192- tmp |= PCI_COMMAND_PARITY;193- pci_bus_write_config_word(pbus, devfn, PCI_COMMAND, tmp);194-195- return 0;196-}197-198-/* detect_used_resource - subtract resource under dev from bridge */199-static int detect_used_resource (struct acpiphp_bridge *bridge, struct pci_dev *dev)200-{201- int count;202-203- dbg("Device %s\n", pci_name(dev));204-205- for (count = 0; count < DEVICE_COUNT_RESOURCE; count++) {206- struct pci_resource *res;207- struct pci_resource **head;208- unsigned long base = dev->resource[count].start;209- unsigned long len = dev->resource[count].end - base + 1;210- unsigned long flags = dev->resource[count].flags;211-212- if (!flags)213- continue;214-215- dbg("BAR[%d] 0x%lx - 0x%lx (0x%lx)\n", count, base,216- base + len - 1, flags);217-218- if (flags & IORESOURCE_IO) {219- head = &bridge->io_head;220- } else if (flags & IORESOURCE_PREFETCH) {221- head = &bridge->p_mem_head;222- } else {223- head = &bridge->mem_head;224- }225-226- spin_lock(&bridge->res_lock);227- res = acpiphp_get_resource_with_base(head, base, len);228- spin_unlock(&bridge->res_lock);229- if (res)230- kfree(res);231- }232-233- return 0;234-}235-236-237-/**238- * acpiphp_detect_pci_resource - detect resources under bridge239- * @bridge: detect all resources already used under this bridge240- *241- * collect all resources already allocated for all devices under a bridge.242- */243-int acpiphp_detect_pci_resource (struct acpiphp_bridge *bridge)244-{245- struct list_head *l;246- struct pci_dev *dev;247-248- list_for_each (l, &bridge->pci_bus->devices) {249- dev = pci_dev_b(l);250- detect_used_resource(bridge, dev);251- }252-253- return 0;254-}255-256-257-/**258- * acpiphp_init_slot_resource - gather resource usage information of a slot259- * @slot: ACPI slot object to be checked, should have valid pci_dev member260- *261- * TBD: PCI-to-PCI bridge case262- * use pci_dev->resource[]263- */264-int acpiphp_init_func_resource (struct acpiphp_func *func)265-{266- u64 base;267- u32 bar, len;268- u32 address[] = {269- PCI_BASE_ADDRESS_0,270- PCI_BASE_ADDRESS_1,271- PCI_BASE_ADDRESS_2,272- PCI_BASE_ADDRESS_3,273- PCI_BASE_ADDRESS_4,274- PCI_BASE_ADDRESS_5,275- 0276- };277- int count;278- struct pci_resource *res;279- struct pci_dev *dev;280-281- dev = func->pci_dev;282- dbg("Hot-pluggable device %s\n", pci_name(dev));283-284- for (count = 0; address[count]; count++) { /* for 6 BARs */285- pci_read_config_dword(dev, address[count], &bar);286-287- if (!bar) /* This BAR is not implemented */288- continue;289-290- pci_write_config_dword(dev, address[count], 0xFFFFFFFF);291- pci_read_config_dword(dev, address[count], &len);292-293- if (len & PCI_BASE_ADDRESS_SPACE_IO) {294- /* This is IO */295- base = bar & 0xFFFFFFFC;296- len = len & (PCI_BASE_ADDRESS_IO_MASK & 0xFFFF);297- len = len & ~(len - 1);298-299- dbg("BAR[%d] %08x - %08x (IO)\n", count, (u32)base, (u32)base + len - 1);300-301- res = acpiphp_make_resource(base, len);302- if (!res)303- goto no_memory;304-305- res->next = func->io_head;306- func->io_head = res;307-308- } else {309- /* This is Memory */310- base = bar & 0xFFFFFFF0;311- if (len & PCI_BASE_ADDRESS_MEM_PREFETCH) {312- /* pfmem */313-314- len &= 0xFFFFFFF0;315- len = ~len + 1;316-317- if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) { /* takes up another dword */318- dbg("prefetch mem 64\n");319- count += 1;320- }321- dbg("BAR[%d] %08x - %08x (PMEM)\n", count, (u32)base, (u32)base + len - 1);322- res = acpiphp_make_resource(base, len);323- if (!res)324- goto no_memory;325-326- res->next = func->p_mem_head;327- func->p_mem_head = res;328-329- } else {330- /* regular memory */331-332- len &= 0xFFFFFFF0;333- len = ~len + 1;334-335- if (len & PCI_BASE_ADDRESS_MEM_TYPE_64) {336- /* takes up another dword */337- dbg("mem 64\n");338- count += 1;339- }340- dbg("BAR[%d] %08x - %08x (MEM)\n", count, (u32)base, (u32)base + len - 1);341- res = acpiphp_make_resource(base, len);342- if (!res)343- goto no_memory;344-345- res->next = func->mem_head;346- func->mem_head = res;347-348- }349- }350-351- pci_write_config_dword(dev, address[count], bar);352- }353-#if 1354- acpiphp_dump_func_resource(func);355-#endif356-357- return 0;358-359- no_memory:360- err("out of memory\n");361- acpiphp_free_resource(&func->io_head);362- acpiphp_free_resource(&func->mem_head);363- acpiphp_free_resource(&func->p_mem_head);364-365- return -1;366-}367-368-369-/**370- * acpiphp_configure_slot - allocate PCI resources371- * @slot: slot to be configured372- *373- * initializes a PCI functions on a device inserted374- * into the slot375- *376- */377-int acpiphp_configure_slot (struct acpiphp_slot *slot)378-{379- struct acpiphp_func *func;380- struct list_head *l;381- u8 hdr;382- u32 dvid;383- int retval = 0;384- int is_multi = 0;385-386- pci_bus_read_config_byte(slot->bridge->pci_bus,387- PCI_DEVFN(slot->device, 0),388- PCI_HEADER_TYPE, &hdr);389-390- if (hdr & 0x80)391- is_multi = 1;392-393- list_for_each (l, &slot->funcs) {394- func = list_entry(l, struct acpiphp_func, sibling);395- if (is_multi || func->function == 0) {396- pci_bus_read_config_dword(slot->bridge->pci_bus,397- PCI_DEVFN(slot->device,398- func->function),399- PCI_VENDOR_ID, &dvid);400- if (dvid != 0xffffffff) {401- retval = init_config_space(func);402- if (retval)403- break;404- }405- }406- }407-408- return retval;409-}410-411-/**412- * acpiphp_configure_function - configure PCI function413- * @func: function to be configured414- *415- * initializes a PCI functions on a device inserted416- * into the slot417- *418- */419-int acpiphp_configure_function (struct acpiphp_func *func)420-{421- /* all handled by the pci core now */422- return 0;423-}424-425-/**426- * acpiphp_unconfigure_function - unconfigure PCI function427- * @func: function to be unconfigured428- *429- */430-void acpiphp_unconfigure_function (struct acpiphp_func *func)431-{432- struct acpiphp_bridge *bridge;433-434- /* if pci_dev is NULL, ignore it */435- if (!func->pci_dev)436- return;437-438- pci_remove_bus_device(func->pci_dev);439-440- /* free all resources */441- bridge = func->slot->bridge;442-443- spin_lock(&bridge->res_lock);444- acpiphp_move_resource(&func->io_head, &bridge->io_head);445- acpiphp_move_resource(&func->mem_head, &bridge->mem_head);446- acpiphp_move_resource(&func->p_mem_head, &bridge->p_mem_head);447- acpiphp_move_resource(&func->bus_head, &bridge->bus_head);448- spin_unlock(&bridge->res_lock);449-}
···1-/*2- * ACPI PCI HotPlug Utility functions3- *4- * Copyright (C) 1995,2001 Compaq Computer Corporation5- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)6- * Copyright (C) 2001 IBM Corp.7- * Copyright (C) 2002 Hiroshi Aono (h-aono@ap.jp.nec.com)8- * Copyright (C) 2002 Takayoshi Kochi (t-kochi@bq.jp.nec.com)9- * Copyright (C) 2002 NEC Corporation10- *11- * All rights reserved.12- *13- * This program is free software; you can redistribute it and/or modify14- * it under the terms of the GNU General Public License as published by15- * the Free Software Foundation; either version 2 of the License, or (at16- * your option) any later version.17- *18- * This program is distributed in the hope that it will be useful, but19- * WITHOUT ANY WARRANTY; without even the implied warranty of20- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or21- * NON INFRINGEMENT. See the GNU General Public License for more22- * details.23- *24- * You should have received a copy of the GNU General Public License25- * along with this program; if not, write to the Free Software26- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.27- *28- * Send feedback to <gregkh@us.ibm.com>, <t-kochi@bq.jp.nec.com>29- *30- */31-32-#include <linux/init.h>33-#include <linux/module.h>34-35-#include <linux/kernel.h>36-#include <linux/types.h>37-#include <linux/proc_fs.h>38-#include <linux/sysctl.h>39-#include <linux/pci.h>40-#include <linux/smp.h>41-#include <linux/smp_lock.h>42-43-#include <linux/string.h>44-#include <linux/mm.h>45-#include <linux/errno.h>46-#include <linux/ioport.h>47-#include <linux/slab.h>48-#include <linux/interrupt.h>49-#include <linux/timer.h>50-51-#include <linux/ioctl.h>52-#include <linux/fcntl.h>53-54-#include <linux/list.h>55-56-#include "pci_hotplug.h"57-#include "acpiphp.h"58-59-#define MY_NAME "acpiphp_res"60-61-62-/*63- * sort_by_size - sort nodes by their length, smallest first64- */65-static int sort_by_size(struct pci_resource **head)66-{67- struct pci_resource *current_res;68- struct pci_resource *next_res;69- int out_of_order = 1;70-71- if (!(*head))72- return 1;73-74- if (!((*head)->next))75- return 0;76-77- while (out_of_order) {78- out_of_order = 0;79-80- /* Special case for swapping list head */81- if (((*head)->next) &&82- ((*head)->length > (*head)->next->length)) {83- out_of_order++;84- current_res = *head;85- *head = (*head)->next;86- current_res->next = (*head)->next;87- (*head)->next = current_res;88- }89-90- current_res = *head;91-92- while (current_res->next && current_res->next->next) {93- if (current_res->next->length > current_res->next->next->length) {94- out_of_order++;95- next_res = current_res->next;96- current_res->next = current_res->next->next;97- current_res = current_res->next;98- next_res->next = current_res->next;99- current_res->next = next_res;100- } else101- current_res = current_res->next;102- }103- } /* End of out_of_order loop */104-105- return 0;106-}107-108-#if 0109-/*110- * sort_by_max_size - sort nodes by their length, largest first111- */112-static int sort_by_max_size(struct pci_resource **head)113-{114- struct pci_resource *current_res;115- struct pci_resource *next_res;116- int out_of_order = 1;117-118- if (!(*head))119- return 1;120-121- if (!((*head)->next))122- return 0;123-124- while (out_of_order) {125- out_of_order = 0;126-127- /* Special case for swapping list head */128- if (((*head)->next) &&129- ((*head)->length < (*head)->next->length)) {130- out_of_order++;131- current_res = *head;132- *head = (*head)->next;133- current_res->next = (*head)->next;134- (*head)->next = current_res;135- }136-137- current_res = *head;138-139- while (current_res->next && current_res->next->next) {140- if (current_res->next->length < current_res->next->next->length) {141- out_of_order++;142- next_res = current_res->next;143- current_res->next = current_res->next->next;144- current_res = current_res->next;145- next_res->next = current_res->next;146- current_res->next = next_res;147- } else148- current_res = current_res->next;149- }150- } /* End of out_of_order loop */151-152- return 0;153-}154-#endif155-156-/**157- * get_io_resource - get resource for I/O ports158- *159- * this function sorts the resource list by size and then160- * returns the first node of "size" length that is not in the161- * ISA aliasing window. If it finds a node larger than "size"162- * it will split it up.163- *164- * size must be a power of two.165- *166- * difference from get_resource is handling of ISA aliasing space.167- *168- */169-struct pci_resource *acpiphp_get_io_resource (struct pci_resource **head, u32 size)170-{171- struct pci_resource *prevnode;172- struct pci_resource *node;173- struct pci_resource *split_node;174- u64 temp_qword;175-176- if (!(*head))177- return NULL;178-179- if (acpiphp_resource_sort_and_combine(head))180- return NULL;181-182- if (sort_by_size(head))183- return NULL;184-185- for (node = *head; node; node = node->next) {186- if (node->length < size)187- continue;188-189- if (node->base & (size - 1)) {190- /* this one isn't base aligned properly191- so we'll make a new entry and split it up */192- temp_qword = (node->base | (size-1)) + 1;193-194- /* Short circuit if adjusted size is too small */195- if ((node->length - (temp_qword - node->base)) < size)196- continue;197-198- split_node = acpiphp_make_resource(node->base, temp_qword - node->base);199-200- if (!split_node)201- return NULL;202-203- node->base = temp_qword;204- node->length -= split_node->length;205-206- /* Put it in the list */207- split_node->next = node->next;208- node->next = split_node;209- } /* End of non-aligned base */210-211- /* Don't need to check if too small since we already did */212- if (node->length > size) {213- /* this one is longer than we need214- so we'll make a new entry and split it up */215- split_node = acpiphp_make_resource(node->base + size, node->length - size);216-217- if (!split_node)218- return NULL;219-220- node->length = size;221-222- /* Put it in the list */223- split_node->next = node->next;224- node->next = split_node;225- } /* End of too big on top end */226-227- /* For IO make sure it's not in the ISA aliasing space */228- if ((node->base & 0x300L) && !(node->base & 0xfffff000))229- continue;230-231- /* If we got here, then it is the right size232- Now take it out of the list */233- if (*head == node) {234- *head = node->next;235- } else {236- prevnode = *head;237- while (prevnode->next != node)238- prevnode = prevnode->next;239-240- prevnode->next = node->next;241- }242- node->next = NULL;243- /* Stop looping */244- break;245- }246-247- return node;248-}249-250-251-#if 0252-/**253- * get_max_resource - get the largest resource254- *255- * Gets the largest node that is at least "size" big from the256- * list pointed to by head. It aligns the node on top and bottom257- * to "size" alignment before returning it.258- */259-static struct pci_resource *acpiphp_get_max_resource (struct pci_resource **head, u32 size)260-{261- struct pci_resource *max;262- struct pci_resource *temp;263- struct pci_resource *split_node;264- u64 temp_qword;265-266- if (!(*head))267- return NULL;268-269- if (acpiphp_resource_sort_and_combine(head))270- return NULL;271-272- if (sort_by_max_size(head))273- return NULL;274-275- for (max = *head;max; max = max->next) {276-277- /* If not big enough we could probably just bail,278- instead we'll continue to the next. */279- if (max->length < size)280- continue;281-282- if (max->base & (size - 1)) {283- /* this one isn't base aligned properly284- so we'll make a new entry and split it up */285- temp_qword = (max->base | (size-1)) + 1;286-287- /* Short circuit if adjusted size is too small */288- if ((max->length - (temp_qword - max->base)) < size)289- continue;290-291- split_node = acpiphp_make_resource(max->base, temp_qword - max->base);292-293- if (!split_node)294- return NULL;295-296- max->base = temp_qword;297- max->length -= split_node->length;298-299- /* Put it next in the list */300- split_node->next = max->next;301- max->next = split_node;302- }303-304- if ((max->base + max->length) & (size - 1)) {305- /* this one isn't end aligned properly at the top306- so we'll make a new entry and split it up */307- temp_qword = ((max->base + max->length) & ~(size - 1));308-309- split_node = acpiphp_make_resource(temp_qword,310- max->length + max->base - temp_qword);311-312- if (!split_node)313- return NULL;314-315- max->length -= split_node->length;316-317- /* Put it in the list */318- split_node->next = max->next;319- max->next = split_node;320- }321-322- /* Make sure it didn't shrink too much when we aligned it */323- if (max->length < size)324- continue;325-326- /* Now take it out of the list */327- temp = (struct pci_resource*) *head;328- if (temp == max) {329- *head = max->next;330- } else {331- while (temp && temp->next != max) {332- temp = temp->next;333- }334-335- temp->next = max->next;336- }337-338- max->next = NULL;339- return max;340- }341-342- /* If we get here, we couldn't find one */343- return NULL;344-}345-#endif346-347-/**348- * get_resource - get resource (mem, pfmem)349- *350- * this function sorts the resource list by size and then351- * returns the first node of "size" length. If it finds a node352- * larger than "size" it will split it up.353- *354- * size must be a power of two.355- *356- */357-struct pci_resource *acpiphp_get_resource (struct pci_resource **head, u32 size)358-{359- struct pci_resource *prevnode;360- struct pci_resource *node;361- struct pci_resource *split_node;362- u64 temp_qword;363-364- if (!(*head))365- return NULL;366-367- if (acpiphp_resource_sort_and_combine(head))368- return NULL;369-370- if (sort_by_size(head))371- return NULL;372-373- for (node = *head; node; node = node->next) {374- dbg("%s: req_size =%x node=%p, base=%x, length=%x\n",375- __FUNCTION__, size, node, (u32)node->base, node->length);376- if (node->length < size)377- continue;378-379- if (node->base & (size - 1)) {380- dbg("%s: not aligned\n", __FUNCTION__);381- /* this one isn't base aligned properly382- so we'll make a new entry and split it up */383- temp_qword = (node->base | (size-1)) + 1;384-385- /* Short circuit if adjusted size is too small */386- if ((node->length - (temp_qword - node->base)) < size)387- continue;388-389- split_node = acpiphp_make_resource(node->base, temp_qword - node->base);390-391- if (!split_node)392- return NULL;393-394- node->base = temp_qword;395- node->length -= split_node->length;396-397- /* Put it in the list */398- split_node->next = node->next;399- node->next = split_node;400- } /* End of non-aligned base */401-402- /* Don't need to check if too small since we already did */403- if (node->length > size) {404- dbg("%s: too big\n", __FUNCTION__);405- /* this one is longer than we need406- so we'll make a new entry and split it up */407- split_node = acpiphp_make_resource(node->base + size, node->length - size);408-409- if (!split_node)410- return NULL;411-412- node->length = size;413-414- /* Put it in the list */415- split_node->next = node->next;416- node->next = split_node;417- } /* End of too big on top end */418-419- dbg("%s: got one!!!\n", __FUNCTION__);420- /* If we got here, then it is the right size421- Now take it out of the list */422- if (*head == node) {423- *head = node->next;424- } else {425- prevnode = *head;426- while (prevnode->next != node)427- prevnode = prevnode->next;428-429- prevnode->next = node->next;430- }431- node->next = NULL;432- /* Stop looping */433- break;434- }435- return node;436-}437-438-/**439- * get_resource_with_base - get resource with specific base address440- *441- * this function442- * returns the first node of "size" length located at specified base address.443- * If it finds a node larger than "size" it will split it up.444- *445- * size must be a power of two.446- *447- */448-struct pci_resource *acpiphp_get_resource_with_base (struct pci_resource **head, u64 base, u32 size)449-{450- struct pci_resource *prevnode;451- struct pci_resource *node;452- struct pci_resource *split_node;453- u64 temp_qword;454-455- if (!(*head))456- return NULL;457-458- if (acpiphp_resource_sort_and_combine(head))459- return NULL;460-461- for (node = *head; node; node = node->next) {462- dbg(": 1st req_base=%x req_size =%x node=%p, base=%x, length=%x\n",463- (u32)base, size, node, (u32)node->base, node->length);464- if (node->base > base)465- continue;466-467- if ((node->base + node->length) < (base + size))468- continue;469-470- if (node->base < base) {471- dbg(": split 1\n");472- /* this one isn't base aligned properly473- so we'll make a new entry and split it up */474- temp_qword = base;475-476- /* Short circuit if adjusted size is too small */477- if ((node->length - (temp_qword - node->base)) < size)478- continue;479-480- split_node = acpiphp_make_resource(node->base, temp_qword - node->base);481-482- if (!split_node)483- return NULL;484-485- node->base = temp_qword;486- node->length -= split_node->length;487-488- /* Put it in the list */489- split_node->next = node->next;490- node->next = split_node;491- }492-493- dbg(": 2nd req_base=%x req_size =%x node=%p, base=%x, length=%x\n",494- (u32)base, size, node, (u32)node->base, node->length);495-496- /* Don't need to check if too small since we already did */497- if (node->length > size) {498- dbg(": split 2\n");499- /* this one is longer than we need500- so we'll make a new entry and split it up */501- split_node = acpiphp_make_resource(node->base + size, node->length - size);502-503- if (!split_node)504- return NULL;505-506- node->length = size;507-508- /* Put it in the list */509- split_node->next = node->next;510- node->next = split_node;511- } /* End of too big on top end */512-513- dbg(": got one!!!\n");514- /* If we got here, then it is the right size515- Now take it out of the list */516- if (*head == node) {517- *head = node->next;518- } else {519- prevnode = *head;520- while (prevnode->next != node)521- prevnode = prevnode->next;522-523- prevnode->next = node->next;524- }525- node->next = NULL;526- /* Stop looping */527- break;528- }529- return node;530-}531-532-533-/**534- * acpiphp_resource_sort_and_combine535- *536- * Sorts all of the nodes in the list in ascending order by537- * their base addresses. Also does garbage collection by538- * combining adjacent nodes.539- *540- * returns 0 if success541- */542-int acpiphp_resource_sort_and_combine (struct pci_resource **head)543-{544- struct pci_resource *node1;545- struct pci_resource *node2;546- int out_of_order = 1;547-548- if (!(*head))549- return 1;550-551- dbg("*head->next = %p\n",(*head)->next);552-553- if (!(*head)->next)554- return 0; /* only one item on the list, already sorted! */555-556- dbg("*head->base = 0x%x\n",(u32)(*head)->base);557- dbg("*head->next->base = 0x%x\n", (u32)(*head)->next->base);558- while (out_of_order) {559- out_of_order = 0;560-561- /* Special case for swapping list head */562- if (((*head)->next) &&563- ((*head)->base > (*head)->next->base)) {564- node1 = *head;565- (*head) = (*head)->next;566- node1->next = (*head)->next;567- (*head)->next = node1;568- out_of_order++;569- }570-571- node1 = (*head);572-573- while (node1->next && node1->next->next) {574- if (node1->next->base > node1->next->next->base) {575- out_of_order++;576- node2 = node1->next;577- node1->next = node1->next->next;578- node1 = node1->next;579- node2->next = node1->next;580- node1->next = node2;581- } else582- node1 = node1->next;583- }584- } /* End of out_of_order loop */585-586- node1 = *head;587-588- while (node1 && node1->next) {589- if ((node1->base + node1->length) == node1->next->base) {590- /* Combine */591- dbg("8..\n");592- node1->length += node1->next->length;593- node2 = node1->next;594- node1->next = node1->next->next;595- kfree(node2);596- } else597- node1 = node1->next;598- }599-600- return 0;601-}602-603-604-/**605- * acpiphp_make_resource - make resource structure606- * @base: base address of a resource607- * @length: length of a resource608- */609-struct pci_resource *acpiphp_make_resource (u64 base, u32 length)610-{611- struct pci_resource *res;612-613- res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);614- if (res) {615- memset(res, 0, sizeof(struct pci_resource));616- res->base = base;617- res->length = length;618- }619-620- return res;621-}622-623-624-/**625- * acpiphp_move_resource - move linked resources from one to another626- * @from: head of linked resource list627- * @to: head of linked resource list628- */629-void acpiphp_move_resource (struct pci_resource **from, struct pci_resource **to)630-{631- struct pci_resource *tmp;632-633- while (*from) {634- tmp = (*from)->next;635- (*from)->next = *to;636- *to = *from;637- *from = tmp;638- }639-640- /* *from = NULL is guaranteed */641-}642-643-644-/**645- * acpiphp_free_resource - free all linked resources646- * @res: head of linked resource list647- */648-void acpiphp_free_resource (struct pci_resource **res)649-{650- struct pci_resource *tmp;651-652- while (*res) {653- tmp = (*res)->next;654- kfree(*res);655- *res = tmp;656- }657-658- /* *res = NULL is guaranteed */659-}660-661-662-/* debug support functions; will go away sometime :) */663-static void dump_resource(struct pci_resource *head)664-{665- struct pci_resource *p;666- int cnt;667-668- p = head;669- cnt = 0;670-671- while (p) {672- dbg("[%02d] %08x - %08x\n",673- cnt++, (u32)p->base, (u32)p->base + p->length - 1);674- p = p->next;675- }676-}677-678-void acpiphp_dump_resource(struct acpiphp_bridge *bridge)679-{680- dbg("I/O resource:\n");681- dump_resource(bridge->io_head);682- dbg("MEM resource:\n");683- dump_resource(bridge->mem_head);684- dbg("PMEM resource:\n");685- dump_resource(bridge->p_mem_head);686- dbg("BUS resource:\n");687- dump_resource(bridge->bus_head);688-}689-690-void acpiphp_dump_func_resource(struct acpiphp_func *func)691-{692- dbg("I/O resource:\n");693- dump_resource(func->io_head);694- dbg("MEM resource:\n");695- dump_resource(func->mem_head);696- dbg("PMEM resource:\n");697- dump_resource(func->p_mem_head);698- dbg("BUS resource:\n");699- dump_resource(func->bus_head);700-}
···60static void __iomem *cpqhp_rom_start;61static int power_mode;62static int debug;06364#define DRIVER_VERSION "0.9.8"65#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"···1272{1273 int loop;1274 int retval = 0;1275- static int initialized = 0;12761277 if (initialized)1278 return 0;···1441 }14421443 // Stop the notification mechanism1444- cpqhp_event_stop_thread();014451446 //unmap the rom address1447 if (cpqhp_rom_start)
···60static void __iomem *cpqhp_rom_start;61static int power_mode;62static int debug;63+static int initialized;6465#define DRIVER_VERSION "0.9.8"66#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"···1271{1272 int loop;1273 int retval = 0;012741275 if (initialized)1276 return 0;···1441 }14421443 // Stop the notification mechanism1444+ if (initialized)1445+ cpqhp_event_stop_thread();14461447 //unmap the rom address1448 if (cpqhp_rom_start)
+35-57
drivers/pci/msi.c
···28static kmem_cache_t* msi_cachep;2930static int pci_msi_enable = 1;31-static int last_alloc_vector = 0;32-static int nr_released_vectors = 0;33static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS;34-static int nr_msix_devices = 0;3536#ifndef CONFIG_X86_IO_APIC37int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};···170 return 0; /* never anything pending */171}172173-static void release_msi(unsigned int vector);174-static void shutdown_msi_irq(unsigned int vector)175-{176- release_msi(vector);177-}178-179-#define shutdown_msi_irq_wo_maskbit shutdown_msi_irq180-static void enable_msi_irq_wo_maskbit(unsigned int vector) {}181-static void disable_msi_irq_wo_maskbit(unsigned int vector) {}182-static void ack_msi_irq_wo_maskbit(unsigned int vector) {}183-static void end_msi_irq_wo_maskbit(unsigned int vector)184-{185- move_msi(vector);186- ack_APIC_irq();187-}188-189static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)0000000190{191 struct msi_desc *entry;192 unsigned long flags;193194 spin_lock_irqsave(&msi_lock, flags);195 entry = msi_desc[vector];196- if (!entry || !entry->dev) {197- spin_unlock_irqrestore(&msi_lock, flags);198- return 0;199- }200- entry->msi_attrib.state = 1; /* Mark it active */201 spin_unlock_irqrestore(&msi_lock, flags);202-203- unmask_MSI_irq(vector);204- return 0; /* never anything pending */205}206207-#define shutdown_msi_irq_w_maskbit shutdown_msi_irq208-#define enable_msi_irq_w_maskbit unmask_MSI_irq209-#define disable_msi_irq_w_maskbit mask_MSI_irq210-#define ack_msi_irq_w_maskbit mask_MSI_irq0211212static void end_msi_irq_w_maskbit(unsigned int vector)213{214 move_msi(vector);215 unmask_MSI_irq(vector);216 ack_APIC_irq();0000217}218219/*···213static struct hw_interrupt_type msix_irq_type = {214 .typename = "PCI-MSI-X",215 .startup = startup_msi_irq_w_maskbit,216- .shutdown = shutdown_msi_irq_w_maskbit,217- .enable = enable_msi_irq_w_maskbit,218- .disable = disable_msi_irq_w_maskbit,219- .ack = ack_msi_irq_w_maskbit,220 .end = end_msi_irq_w_maskbit,221 .set_affinity = set_msi_irq_affinity222};···229static struct hw_interrupt_type msi_irq_w_maskbit_type = {230 .typename = "PCI-MSI",231 .startup = startup_msi_irq_w_maskbit,232- .shutdown = shutdown_msi_irq_w_maskbit,233- .enable = enable_msi_irq_w_maskbit,234- .disable = disable_msi_irq_w_maskbit,235- .ack = ack_msi_irq_w_maskbit,236 .end = end_msi_irq_w_maskbit,237 .set_affinity = set_msi_irq_affinity238};···245static struct hw_interrupt_type msi_irq_wo_maskbit_type = {246 .typename = "PCI-MSI",247 .startup = startup_msi_irq_wo_maskbit,248- .shutdown = shutdown_msi_irq_wo_maskbit,249- .enable = enable_msi_irq_wo_maskbit,250- .disable = disable_msi_irq_wo_maskbit,251- .ack = ack_msi_irq_wo_maskbit,252 .end = end_msi_irq_wo_maskbit,253 .set_affinity = set_msi_irq_affinity254};···397{398 struct msi_desc *entry;399400- entry = (struct msi_desc*) kmem_cache_alloc(msi_cachep, SLAB_KERNEL);401 if (!entry)402 return NULL;403···786 }787}788789-static void release_msi(unsigned int vector)790-{791- struct msi_desc *entry;792- unsigned long flags;793-794- spin_lock_irqsave(&msi_lock, flags);795- entry = msi_desc[vector];796- if (entry && entry->dev)797- entry->msi_attrib.state = 0; /* Mark it not active */798- spin_unlock_irqrestore(&msi_lock, flags);799-}800-801static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)802{803 struct msi_desc *entry;···902/**903 * pci_enable_msix - configure device's MSI-X capability structure904 * @dev: pointer to the pci_dev data structure of MSI-X device function905- * @data: pointer to an array of MSI-X entries906 * @nvec: number of MSI-X vectors requested for allocation by device driver907 *908 * Setup the MSI-X capability structure of device function with the number
···28static kmem_cache_t* msi_cachep;2930static int pci_msi_enable = 1;31+static int last_alloc_vector;32+static int nr_released_vectors;33static int nr_reserved_vectors = NR_HP_RESERVED_VECTORS;34+static int nr_msix_devices;3536#ifndef CONFIG_X86_IO_APIC37int vector_irq[NR_VECTORS] = { [0 ... NR_VECTORS - 1] = -1};···170 return 0; /* never anything pending */171}1720000000000000000173static unsigned int startup_msi_irq_w_maskbit(unsigned int vector)174+{175+ startup_msi_irq_wo_maskbit(vector);176+ unmask_MSI_irq(vector);177+ return 0; /* never anything pending */178+}179+180+static void shutdown_msi_irq(unsigned int vector)181{182 struct msi_desc *entry;183 unsigned long flags;184185 spin_lock_irqsave(&msi_lock, flags);186 entry = msi_desc[vector];187+ if (entry && entry->dev)188+ entry->msi_attrib.state = 0; /* Mark it not active */000189 spin_unlock_irqrestore(&msi_lock, flags);000190}191192+static void end_msi_irq_wo_maskbit(unsigned int vector)193+{194+ move_msi(vector);195+ ack_APIC_irq();196+}197198static void end_msi_irq_w_maskbit(unsigned int vector)199{200 move_msi(vector);201 unmask_MSI_irq(vector);202 ack_APIC_irq();203+}204+205+static void do_nothing(unsigned int vector)206+{207}208209/*···223static struct hw_interrupt_type msix_irq_type = {224 .typename = "PCI-MSI-X",225 .startup = startup_msi_irq_w_maskbit,226+ .shutdown = shutdown_msi_irq,227+ .enable = unmask_MSI_irq,228+ .disable = mask_MSI_irq,229+ .ack = mask_MSI_irq,230 .end = end_msi_irq_w_maskbit,231 .set_affinity = set_msi_irq_affinity232};···239static struct hw_interrupt_type msi_irq_w_maskbit_type = {240 .typename = "PCI-MSI",241 .startup = startup_msi_irq_w_maskbit,242+ .shutdown = shutdown_msi_irq,243+ .enable = unmask_MSI_irq,244+ .disable = mask_MSI_irq,245+ .ack = mask_MSI_irq,246 .end = end_msi_irq_w_maskbit,247 .set_affinity = set_msi_irq_affinity248};···255static struct hw_interrupt_type msi_irq_wo_maskbit_type = {256 .typename = "PCI-MSI",257 .startup = startup_msi_irq_wo_maskbit,258+ .shutdown = shutdown_msi_irq,259+ .enable = do_nothing,260+ .disable = do_nothing,261+ .ack = do_nothing,262 .end = end_msi_irq_wo_maskbit,263 .set_affinity = set_msi_irq_affinity264};···407{408 struct msi_desc *entry;409410+ entry = kmem_cache_alloc(msi_cachep, SLAB_KERNEL);411 if (!entry)412 return NULL;413···796 }797}798000000000000799static int msi_free_vector(struct pci_dev* dev, int vector, int reassign)800{801 struct msi_desc *entry;···924/**925 * pci_enable_msix - configure device's MSI-X capability structure926 * @dev: pointer to the pci_dev data structure of MSI-X device function927+ * @entries: pointer to an array of MSI-X entries928 * @nvec: number of MSI-X vectors requested for allocation by device driver929 *930 * Setup the MSI-X capability structure of device function with the number
···60 char * str = buf;61 int i;62 int max = 7;06364 if (pci_dev->subordinate)65 max = DEVICE_COUNT_RESOURCE;6667 for (i = 0; i < max; i++) {68- str += sprintf(str,"0x%016lx 0x%016lx 0x%016lx\n",69- pci_resource_start(pci_dev,i),70- pci_resource_end(pci_dev,i),71- pci_resource_flags(pci_dev,i));0072 }73 return (str - buf);74}···316 struct device, kobj));317 struct resource *res = (struct resource *)attr->private;318 enum pci_mmap_state mmap_type;00319320- vma->vm_pgoff += res->start >> PAGE_SHIFT;00000000000321 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;322323 return pci_mmap_page_range(pdev, vma, mmap_type, 0);
···60 char * str = buf;61 int i;62 int max = 7;63+ u64 start, end;6465 if (pci_dev->subordinate)66 max = DEVICE_COUNT_RESOURCE;6768 for (i = 0; i < max; i++) {69+ struct resource *res = &pci_dev->resource[i];70+ pci_resource_to_user(pci_dev, i, res, &start, &end);71+ str += sprintf(str,"0x%016llx 0x%016llx 0x%016llx\n",72+ (unsigned long long)start,73+ (unsigned long long)end,74+ (unsigned long long)res->flags);75 }76 return (str - buf);77}···313 struct device, kobj));314 struct resource *res = (struct resource *)attr->private;315 enum pci_mmap_state mmap_type;316+ u64 start, end;317+ int i;318319+ for (i = 0; i < PCI_ROM_RESOURCE; i++)320+ if (res == &pdev->resource[i])321+ break;322+ if (i >= PCI_ROM_RESOURCE)323+ return -ENODEV;324+325+ /* pci_mmap_page_range() expects the same kind of entry as coming326+ * from /proc/bus/pci/ which is a "user visible" value. If this is327+ * different from the resource itself, arch will do necessary fixup.328+ */329+ pci_resource_to_user(pdev, i, res, &start, &end);330+ vma->vm_pgoff += start >> PAGE_SHIFT;331 mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;332333 return pci_mmap_page_range(pdev, vma, mmap_type, 0);
+22-7
drivers/pci/probe.c
···374 struct pci_bus *child;375376 child = pci_alloc_child_bus(parent, dev, busnr);377- if (child)0378 list_add_tail(&child->node, &parent->children);00379 return child;380}381···414{415 struct pci_bus *child;416 int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);417- u32 buses;418 u16 bctl;419420 pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);···450 return max;451 }452453- child = pci_alloc_child_bus(bus, dev, busnr);454 if (!child)455 return max;456 child->primary = buses & 0xFF;···473 /* Clear errors */474 pci_write_config_word(dev, PCI_STATUS, 0xffff);475476- child = pci_alloc_child_bus(bus, dev, ++max);0000477 buses = (buses & 0xff000000)478 | ((unsigned int)(child->primary) << 0)479 | ((unsigned int)(child->secondary) << 8)···508 * as cards with a PCI-to-PCI bridge can be509 * inserted later.510 */511- max += CARDBUS_RESERVE_BUSNR;0000512 }513 /*514 * Set the subordinate bus number to its real value.···768 * and the bus list for fixup functions, etc.769 */770 INIT_LIST_HEAD(&dev->global_list);0771 list_add_tail(&dev->bus_list, &bus->devices);0772773 return dev;774}···891 pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);892 goto err_out;893 }0894 list_add_tail(&b->node, &pci_root_buses);0895896 memset(dev, 0, sizeof(*dev));897 dev->parent = parent;···926927 b->subordinate = pci_scan_child_bus(b);928929- pci_bus_add_devices(b);930-931 return b;932933sys_create_link_err:···935class_dev_reg_err:936 device_unregister(dev);937dev_reg_err:0938 list_del(&b->node);0939err_out:940 kfree(dev);941 kfree(b);
···374 struct pci_bus *child;375376 child = pci_alloc_child_bus(parent, dev, busnr);377+ if (child) {378+ spin_lock(&pci_bus_lock);379 list_add_tail(&child->node, &parent->children);380+ spin_unlock(&pci_bus_lock);381+ }382 return child;383}384···411{412 struct pci_bus *child;413 int is_cardbus = (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS);414+ u32 buses, i;415 u16 bctl;416417 pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses);···447 return max;448 }449450+ child = pci_add_new_bus(bus, dev, busnr);451 if (!child)452 return max;453 child->primary = buses & 0xFF;···470 /* Clear errors */471 pci_write_config_word(dev, PCI_STATUS, 0xffff);472473+ /* Prevent assigning a bus number that already exists.474+ * This can happen when a bridge is hot-plugged */475+ if (pci_find_bus(pci_domain_nr(bus), max+1))476+ return max;477+ child = pci_add_new_bus(bus, dev, ++max);478 buses = (buses & 0xff000000)479 | ((unsigned int)(child->primary) << 0)480 | ((unsigned int)(child->secondary) << 8)···501 * as cards with a PCI-to-PCI bridge can be502 * inserted later.503 */504+ for (i=0; i<CARDBUS_RESERVE_BUSNR; i++)505+ if (pci_find_bus(pci_domain_nr(bus),506+ max+i+1))507+ break;508+ max += i;509 }510 /*511 * Set the subordinate bus number to its real value.···757 * and the bus list for fixup functions, etc.758 */759 INIT_LIST_HEAD(&dev->global_list);760+ spin_lock(&pci_bus_lock);761 list_add_tail(&dev->bus_list, &bus->devices);762+ spin_unlock(&pci_bus_lock);763764 return dev;765}···878 pr_debug("PCI: Bus %04x:%02x already known\n", pci_domain_nr(b), bus);879 goto err_out;880 }881+ spin_lock(&pci_bus_lock);882 list_add_tail(&b->node, &pci_root_buses);883+ spin_unlock(&pci_bus_lock);884885 memset(dev, 0, sizeof(*dev));886 dev->parent = parent;···911912 b->subordinate = pci_scan_child_bus(b);91300914 return b;915916sys_create_link_err:···922class_dev_reg_err:923 device_unregister(dev);924dev_reg_err:925+ spin_lock(&pci_bus_lock);926 list_del(&b->node);927+ spin_unlock(&pci_bus_lock);928err_out:929 kfree(dev);930 kfree(b);
+10-4
drivers/pci/proc.c
···355 dev->device,356 dev->irq);357 /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */358- for(i=0; i<7; i++)00359 seq_printf(m, LONG_FORMAT,360- dev->resource[i].start |361 (dev->resource[i].flags & PCI_REGION_FLAG_MASK));362- for(i=0; i<7; i++)000363 seq_printf(m, LONG_FORMAT,364 dev->resource[i].start < dev->resource[i].end ?365- dev->resource[i].end - dev->resource[i].start + 1 : 0);0366 seq_putc(m, '\t');367 if (drv)368 seq_printf(m, "%s", drv->name);
···355 dev->device,356 dev->irq);357 /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */358+ for (i=0; i<7; i++) {359+ u64 start, end;360+ pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);361 seq_printf(m, LONG_FORMAT,362+ ((unsigned long)start) |363 (dev->resource[i].flags & PCI_REGION_FLAG_MASK));364+ }365+ for (i=0; i<7; i++) {366+ u64 start, end;367+ pci_resource_to_user(dev, i, &dev->resource[i], &start, &end);368 seq_printf(m, LONG_FORMAT,369 dev->resource[i].start < dev->resource[i].end ?370+ (unsigned long)(end - start) + 1 : 0);371+ }372 seq_putc(m, '\t');373 if (drv)374 seq_printf(m, "%s", drv->name);
+9-5
drivers/pci/remove.c
···1819static void pci_destroy_dev(struct pci_dev *dev)20{21- pci_proc_detach_device(dev);22- pci_remove_sysfs_dev_files(dev);23- device_unregister(&dev->dev);0000002425 /* Remove the device from the device lists, and prevent any further26 * list accesses from this device */27 spin_lock(&pci_bus_lock);28 list_del(&dev->bus_list);29- list_del(&dev->global_list);30 dev->bus_list.next = dev->bus_list.prev = NULL;31- dev->global_list.next = dev->global_list.prev = NULL;32 spin_unlock(&pci_bus_lock);3334 pci_free_resources(dev);
···1819static void pci_destroy_dev(struct pci_dev *dev)20{21+ if (!list_empty(&dev->global_list)) {22+ pci_proc_detach_device(dev);23+ pci_remove_sysfs_dev_files(dev);24+ device_unregister(&dev->dev);25+ spin_lock(&pci_bus_lock);26+ list_del(&dev->global_list);27+ dev->global_list.next = dev->global_list.prev = NULL;28+ spin_unlock(&pci_bus_lock);29+ }3031 /* Remove the device from the device lists, and prevent any further32 * list accesses from this device */33 spin_lock(&pci_bus_lock);34 list_del(&dev->bus_list);035 dev->bus_list.next = dev->bus_list.prev = NULL;036 spin_unlock(&pci_bus_lock);3738 pci_free_resources(dev);
+4-1
drivers/pci/setup-bus.c
···72 for (list = head.next; list;) {73 res = list->res;74 idx = res - &list->dev->resource[0];75- pci_assign_resource(list->dev, idx);00076 tmp = list;77 list = list->next;78 kfree(tmp);
···72 for (list = head.next; list;) {73 res = list->res;74 idx = res - &list->dev->resource[0];75+ if (pci_assign_resource(list->dev, idx)) {76+ res->start = 0;77+ res->flags = 0;78+ }79 tmp = list;80 list = list->next;81 kfree(tmp);
+3-5
drivers/scsi/3w-9xxx.c
···1916} /* End __twa_shutdown() */19171918/* Wrapper for __twa_shutdown */1919-static void twa_shutdown(struct device *dev)1920{1921- struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));1922 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;19231924 __twa_shutdown(tw_dev);···2140 .id_table = twa_pci_tbl,2141 .probe = twa_probe,2142 .remove = twa_remove,2143- .driver = {2144- .shutdown = twa_shutdown2145- }2146};21472148/* This function is called on driver initialization */
···1916} /* End __twa_shutdown() */19171918/* Wrapper for __twa_shutdown */1919+static void twa_shutdown(struct pci_dev *pdev)1920{1921+ struct Scsi_Host *host = pci_get_drvdata(pdev);1922 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;19231924 __twa_shutdown(tw_dev);···2140 .id_table = twa_pci_tbl,2141 .probe = twa_probe,2142 .remove = twa_remove,2143+ .shutdown = twa_shutdown002144};21452146/* This function is called on driver initialization */
+3-5
drivers/scsi/3w-xxxx.c
···2264} /* End __tw_shutdown() */22652266/* Wrapper for __tw_shutdown */2267-static void tw_shutdown(struct device *dev)2268{2269- struct Scsi_Host *host = pci_get_drvdata(to_pci_dev(dev));2270 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;22712272 __tw_shutdown(tw_dev);···2451 .id_table = tw_pci_tbl,2452 .probe = tw_probe,2453 .remove = tw_remove,2454- .driver = {2455- .shutdown = tw_shutdown2456- }2457};24582459/* This function is called on driver initialization */
···2264} /* End __tw_shutdown() */22652266/* Wrapper for __tw_shutdown */2267+static void tw_shutdown(struct pci_dev *pdev)2268{2269+ struct Scsi_Host *host = pci_get_drvdata(pdev);2270 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;22712272 __tw_shutdown(tw_dev);···2451 .id_table = tw_pci_tbl,2452 .probe = tw_probe,2453 .remove = tw_remove,2454+ .shutdown = tw_shutdown,002455};24562457/* This function is called on driver initialization */
+4-6
drivers/scsi/ipr.c
···60126013/**6014 * ipr_shutdown - Shutdown handler.6015- * @dev: device struct6016 *6017 * This function is invoked upon system shutdown/reboot. It will issue6018 * an adapter shutdown to the adapter to flush the write cache.···6020 * Return value:6021 * none6022 **/6023-static void ipr_shutdown(struct device *dev)6024{6025- struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(to_pci_dev(dev));6026 unsigned long lock_flags = 0;60276028 spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);···6068 .id_table = ipr_pci_table,6069 .probe = ipr_probe,6070 .remove = ipr_remove,6071- .driver = {6072- .shutdown = ipr_shutdown,6073- },6074};60756076/**
···60126013/**6014 * ipr_shutdown - Shutdown handler.6015+ * @pdev: pci device struct6016 *6017 * This function is invoked upon system shutdown/reboot. It will issue6018 * an adapter shutdown to the adapter to flush the write cache.···6020 * Return value:6021 * none6022 **/6023+static void ipr_shutdown(struct pci_dev *pdev)6024{6025+ struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);6026 unsigned long lock_flags = 0;60276028 spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);···6068 .id_table = ipr_pci_table,6069 .probe = ipr_probe,6070 .remove = ipr_remove,6071+ .shutdown = ipr_shutdown,006072};60736074/**
···223 /* Nothing to do. */224}2250000000000000000000226/* TODO: integrate with include/asm-generic/pci.h ? */227static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)228{
···223 /* Nothing to do. */224}225226+#ifdef CONFIG_PCI227+static inline void pci_dma_burst_advice(struct pci_dev *pdev,228+ enum pci_dma_burst_strategy *strat,229+ unsigned long *strategy_parameter)230+{231+ unsigned long cacheline_size;232+ u8 byte;233+234+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);235+ if (byte == 0)236+ cacheline_size = 1024;237+ else238+ cacheline_size = (int) byte * 4;239+240+ *strat = PCI_DMA_BURST_BOUNDARY;241+ *strategy_parameter = cacheline_size;242+}243+#endif244+245/* TODO: integrate with include/asm-generic/pci.h ? */246static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)247{
···57 */58#define PCI_DMA_BUS_IS_PHYS (1)59000000000060/*61 * These are pretty much arbitary with the CoMEM implementation.62 * We have the whole address space to ourselves.
···57 */58#define PCI_DMA_BUS_IS_PHYS (1)5960+#ifdef CONFIG_PCI61+static inline void pci_dma_burst_advice(struct pci_dev *pdev,62+ enum pci_dma_burst_strategy *strat,63+ unsigned long *strategy_parameter)64+{65+ *strat = PCI_DMA_BURST_INFINITY;66+ *strategy_parameter = ~0UL;67+}68+#endif69+70/*71 * These are pretty much arbitary with the CoMEM implementation.72 * We have the whole address space to ourselves.
+10
include/asm-i386/pci.h
···99{100}1010000000000102#endif /* __KERNEL__ */103104/* implement the pci_ DMA API in terms of the generic device dma_ one */
···99{100}101102+#ifdef CONFIG_PCI103+static inline void pci_dma_burst_advice(struct pci_dev *pdev,104+ enum pci_dma_burst_strategy *strat,105+ unsigned long *strategy_parameter)106+{107+ *strat = PCI_DMA_BURST_INFINITY;108+ *strategy_parameter = ~0UL;109+}110+#endif111+112#endif /* __KERNEL__ */113114/* implement the pci_ DMA API in terms of the generic device dma_ one */
+9-3
include/asm-ia64/iosapic.h
···71}7273extern void __init iosapic_system_init (int pcat_compat);74-extern void __init iosapic_init (unsigned long address,75 unsigned int gsi_base);00076extern int gsi_to_vector (unsigned int gsi);77extern int gsi_to_irq (unsigned int gsi);78extern void iosapic_enable_intr (unsigned int vector);···9798extern void iosapic_pci_fixup (int);99#ifdef CONFIG_NUMA100-extern void __init map_iosapic_to_node (unsigned int, int);101#endif102#else103#define iosapic_system_init(pcat_compat) do { } while (0)104-#define iosapic_init(address,gsi_base) do { } while (0)000105#define iosapic_register_intr(gsi,polarity,trigger) (gsi)106#define iosapic_unregister_intr(irq) do { } while (0)107#define iosapic_override_isa_irq(isa_irq,gsi,polarity,trigger) do { } while (0)
···71}7273extern void __init iosapic_system_init (int pcat_compat);74+extern int __devinit iosapic_init (unsigned long address,75 unsigned int gsi_base);76+#ifdef CONFIG_HOTPLUG77+extern int iosapic_remove (unsigned int gsi_base);78+#endif /* CONFIG_HOTPLUG */79extern int gsi_to_vector (unsigned int gsi);80extern int gsi_to_irq (unsigned int gsi);81extern void iosapic_enable_intr (unsigned int vector);···9495extern void iosapic_pci_fixup (int);96#ifdef CONFIG_NUMA97+extern void __devinit map_iosapic_to_node (unsigned int, int);98#endif99#else100#define iosapic_system_init(pcat_compat) do { } while (0)101+#define iosapic_init(address,gsi_base) (-EINVAL)102+#ifdef CONFIG_HOTPLUG103+#define iosapic_remove(gsi_base) (-ENODEV)104+#endif /* CONFIG_HOTPLUG */105#define iosapic_register_intr(gsi,polarity,trigger) (gsi)106#define iosapic_unregister_intr(irq) do { } while (0)107#define iosapic_override_isa_irq(isa_irq,gsi,polarity,trigger) do { } while (0)
+19
include/asm-ia64/pci.h
···82#define sg_dma_len(sg) ((sg)->dma_length)83#define sg_dma_address(sg) ((sg)->dma_address)84000000000000000000085#define HAVE_PCI_MMAP86extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,87 enum pci_mmap_state mmap_state, int write_combine);
···230/* export the pci_ DMA API in terms of the dma_ one */231#include <asm-generic/pci-dma-compat.h>2320000000000000000000233extern void234pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,235 struct resource *res);
···230/* export the pci_ DMA API in terms of the dma_ one */231#include <asm-generic/pci-dma-compat.h>232233+#ifdef CONFIG_PCI234+static inline void pci_dma_burst_advice(struct pci_dev *pdev,235+ enum pci_dma_burst_strategy *strat,236+ unsigned long *strategy_parameter)237+{238+ unsigned long cacheline_size;239+ u8 byte;240+241+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);242+ if (byte == 0)243+ cacheline_size = 1024;244+ else245+ cacheline_size = (int) byte * 4;246+247+ *strat = PCI_DMA_BURST_MULTIPLE;248+ *strategy_parameter = cacheline_size;249+}250+#endif251+252extern void253pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,254 struct resource *res);
+16
include/asm-ppc/pci.h
···69#define pci_unmap_len(PTR, LEN_NAME) (0)70#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)71000000000072/*73 * At present there are very few 32-bit PPC machines that can have74 * memory above the 4GB point, and we don't support that.···112 unsigned long offset,113 unsigned long size,114 pgprot_t prot);000000115116#endif /* __KERNEL__ */117
···69#define pci_unmap_len(PTR, LEN_NAME) (0)70#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)7172+#ifdef CONFIG_PCI73+static inline void pci_dma_burst_advice(struct pci_dev *pdev,74+ enum pci_dma_burst_strategy *strat,75+ unsigned long *strategy_parameter)76+{77+ *strat = PCI_DMA_BURST_INFINITY;78+ *strategy_parameter = ~0UL;79+}80+#endif81+82/*83 * At present there are very few 32-bit PPC machines that can have84 * memory above the 4GB point, and we don't support that.···102 unsigned long offset,103 unsigned long size,104 pgprot_t prot);105+106+#define HAVE_ARCH_PCI_RESOURCE_TO_USER107+extern void pci_resource_to_user(const struct pci_dev *dev, int bar,108+ const struct resource *rsrc,109+ u64 *start, u64 *end);110+111112#endif /* __KERNEL__ */113
+26
include/asm-ppc64/pci.h
···78 return 0;79}80000000000000000000081extern int pci_domain_nr(struct pci_bus *bus);8283/* Decide whether to display the domain number in /proc */···154 unsigned long offset,155 unsigned long size,156 pgprot_t prot);0000000157158159#endif /* __KERNEL__ */
···78 return 0;79}8081+#ifdef CONFIG_PCI82+static inline void pci_dma_burst_advice(struct pci_dev *pdev,83+ enum pci_dma_burst_strategy *strat,84+ unsigned long *strategy_parameter)85+{86+ unsigned long cacheline_size;87+ u8 byte;88+89+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);90+ if (byte == 0)91+ cacheline_size = 1024;92+ else93+ cacheline_size = (int) byte * 4;94+95+ *strat = PCI_DMA_BURST_MULTIPLE;96+ *strategy_parameter = cacheline_size;97+}98+#endif99+100extern int pci_domain_nr(struct pci_bus *bus);101102/* Decide whether to display the domain number in /proc */···135 unsigned long offset,136 unsigned long size,137 pgprot_t prot);138+139+#ifdef CONFIG_PPC_MULTIPLATFORM140+#define HAVE_ARCH_PCI_RESOURCE_TO_USER141+extern void pci_resource_to_user(const struct pci_dev *dev, int bar,142+ const struct resource *rsrc,143+ u64 *start, u64 *end);144+#endif /* CONFIG_PPC_MULTIPLATFORM */145146147#endif /* __KERNEL__ */
···220 return (dma_addr == PCI_DMA_ERROR_CODE);221}2220000000000000000000223/* Return the index of the PCI controller for device PDEV. */224225extern int pci_domain_nr(struct pci_bus *bus);
···220 return (dma_addr == PCI_DMA_ERROR_CODE);221}222223+#ifdef CONFIG_PCI224+static inline void pci_dma_burst_advice(struct pci_dev *pdev,225+ enum pci_dma_burst_strategy *strat,226+ unsigned long *strategy_parameter)227+{228+ unsigned long cacheline_size;229+ u8 byte;230+231+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &byte);232+ if (byte == 0)233+ cacheline_size = 1024;234+ else235+ cacheline_size = (int) byte * 4;236+237+ *strat = PCI_DMA_BURST_BOUNDARY;238+ *strategy_parameter = cacheline_size;239+}240+#endif241+242/* Return the index of the PCI controller for device PDEV. */243244extern int pci_domain_nr(struct pci_bus *bus);