diff options
-rw-r--r-- | arch/frv/mb93090-mb00/pci-frv.h | 1 | ||||
-rw-r--r-- | arch/frv/mb93090-mb00/pci-vdk.c | 4 | ||||
-rw-r--r-- | arch/ia64/pci/pci.c | 8 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2305/pci-asb2305.h | 1 | ||||
-rw-r--r-- | arch/mn10300/unit-asb2305/pci.c | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/pci.h | 3 | ||||
-rw-r--r-- | arch/x86/include/asm/pci_x86.h | 1 | ||||
-rw-r--r-- | arch/x86/pci/acpi.c | 9 | ||||
-rw-r--r-- | arch/x86/pci/common.c | 1 | ||||
-rw-r--r-- | arch/x86/pci/legacy.c | 2 | ||||
-rw-r--r-- | arch/x86/pci/numaq_32.c | 2 | ||||
-rw-r--r-- | drivers/acpi/pci_root.c | 18 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpci_hotplug_pci.c | 29 | ||||
-rw-r--r-- | drivers/pci/hotplug/cpqphp_ctrl.c | 57 | ||||
-rw-r--r-- | drivers/pci/hotplug/pciehp_pci.c | 44 | ||||
-rw-r--r-- | drivers/pci/hotplug/sgi_hotplug.c | 63 | ||||
-rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 36 | ||||
-rw-r--r-- | drivers/pci/pci-acpi.c | 19 | ||||
-rw-r--r-- | drivers/pci/pci.c | 30 | ||||
-rw-r--r-- | drivers/pci/pci.h | 3 | ||||
-rw-r--r-- | drivers/pci/probe.c | 66 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 1 | ||||
-rw-r--r-- | include/linux/pci.h | 2 |
23 files changed, 176 insertions, 228 deletions
diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h index 089eeba..76c4e73 100644 --- a/arch/frv/mb93090-mb00/pci-frv.h +++ b/arch/frv/mb93090-mb00/pci-frv.h @@ -31,7 +31,6 @@ void pcibios_resource_survey(void); /* pci-vdk.c */ extern int __nongpreldata pcibios_last_bus; -extern struct pci_bus *__nongpreldata pci_root_bus; extern struct pci_ops *__nongpreldata pci_root_ops; /* pci-irq.c */ diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c index 71e9bcf..1152a1e 100644 --- a/arch/frv/mb93090-mb00/pci-vdk.c +++ b/arch/frv/mb93090-mb00/pci-vdk.c @@ -26,7 +26,6 @@ unsigned int __nongpreldata pci_probe = 1; int __nongpreldata pcibios_last_bus = -1; -struct pci_bus *__nongpreldata pci_root_bus; struct pci_ops *__nongpreldata pci_root_ops; /* @@ -416,8 +415,7 @@ int __init pcibios_init(void) printk("PCI: Probing PCI hardware\n"); pci_add_resource(&resources, &pci_ioport_resource); pci_add_resource(&resources, &pci_iomem_resource); - pci_root_bus = pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, - &resources); + pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources); pcibios_irq_init(); pcibios_fixup_peer_bridges(); diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c index 5faa66c..00e59c7 100644 --- a/arch/ia64/pci/pci.c +++ b/arch/ia64/pci/pci.c @@ -396,6 +396,14 @@ out1: return NULL; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct pci_controller *controller = bridge->bus->sysdata; + + ACPI_HANDLE_SET(&bridge->dev, controller->acpi_handle); + return 0; +} + static int __devinit is_valid_resource(struct pci_dev *dev, int idx) { unsigned int i, type_mask = IORESOURCE_IO | IORESOURCE_MEM; diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h index 1194fe4..7fa66a0 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.h +++ b/arch/mn10300/unit-asb2305/pci-asb2305.h @@ -36,7 +36,6 @@ extern void pcibios_resource_survey(void); /* pci.c */ extern int pcibios_last_bus; -extern struct pci_bus *pci_root_bus; extern struct pci_ops *pci_root_ops; extern struct irq_routing_table *pcibios_get_irq_routing_table(void); diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c index e205948..426bf51 100644 --- a/arch/mn10300/unit-asb2305/pci.c +++ b/arch/mn10300/unit-asb2305/pci.c @@ -24,7 +24,6 @@ unsigned int pci_probe = 1; int pcibios_last_bus = -1; -struct pci_bus *pci_root_bus; struct pci_ops *pci_root_ops; /* @@ -377,8 +376,7 @@ static int __init pcibios_init(void) pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset); pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset); - pci_root_bus = pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, - &resources); + pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources); pcibios_irq_init(); pcibios_fixup_irqs(); diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index dba7805..9f437e9 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -14,6 +14,9 @@ struct pci_sysdata { int domain; /* PCI domain */ int node; /* NUMA node */ +#ifdef CONFIG_ACPI + void *acpi; /* ACPI-specific data */ +#endif #ifdef CONFIG_X86_64 void *iommu; /* IOMMU private data */ #endif diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h index 73e8eef..0126f10 100644 --- a/arch/x86/include/asm/pci_x86.h +++ b/arch/x86/include/asm/pci_x86.h @@ -54,7 +54,6 @@ void pcibios_set_cache_line_size(void); /* pci-pc.c */ extern int pcibios_last_bus; -extern struct pci_bus *pci_root_bus; extern struct pci_ops pci_root_ops; void pcibios_scan_specific_bus(int busn); diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 0c01261f..3d49094 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -522,6 +522,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) sd = &info->sd; sd->domain = domain; sd->node = node; + sd->acpi = device->handle; /* * Maybe the desired pci bus has been already scanned. In such case * it is unnecessary to scan the pci bus with the given domain,busnum. @@ -593,6 +594,14 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) return bus; } +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + struct pci_sysdata *sd = bridge->bus->sysdata; + + ACPI_HANDLE_SET(&bridge->dev, sd->acpi); + return 0; +} + int __init pci_acpi_init(void) { struct pci_dev *dev = NULL; diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 412e128..505731b 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -34,7 +34,6 @@ int noioapicreroute = 1; #endif int pcibios_last_bus = -1; unsigned long pirq_table_addr; -struct pci_bus *pci_root_bus; const struct pci_raw_ops *__read_mostly raw_pci_ops; const struct pci_raw_ops *__read_mostly raw_pci_ext_ops; diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index a1df191..a9e8308 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c @@ -30,7 +30,7 @@ int __init pci_legacy_init(void) } printk("PCI: Probing PCI hardware\n"); - pci_root_bus = pcibios_scan_root(0); + pcibios_scan_root(0); return 0; } diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c index 83e125b..00edfe6 100644 --- a/arch/x86/pci/numaq_32.c +++ b/arch/x86/pci/numaq_32.c @@ -152,7 +152,7 @@ int __init pci_numaq_init(void) raw_pci_ops = &pci_direct_conf1_mq; - pci_root_bus = pcibios_scan_root(0); + pcibios_scan_root(0); if (num_online_nodes() > 1) for_each_online_node(quad) { if (quad == 0) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index fd59f57..417487a 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -107,24 +107,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) } EXPORT_SYMBOL(acpi_pci_unregister_driver); -acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) -{ - struct acpi_pci_root *root; - acpi_handle handle = NULL; - - mutex_lock(&acpi_pci_root_lock); - list_for_each_entry(root, &acpi_pci_roots, node) - if ((root->segment == (u16) seg) && - (root->secondary.start == (u16) bus)) { - handle = root->device->handle; - break; - } - mutex_unlock(&acpi_pci_root_lock); - return handle; -} - -EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle); - /** * acpi_is_root_bridge - determine whether an ACPI CA node is a PCI root bridge * @handle - the ACPI CA node in question. diff --git a/drivers/pci/hotplug/cpci_hotplug_pci.c b/drivers/pci/hotplug/cpci_hotplug_pci.c index dcc75c7..d8add34 100644 --- a/drivers/pci/hotplug/cpci_hotplug_pci.c +++ b/drivers/pci/hotplug/cpci_hotplug_pci.c @@ -252,8 +252,8 @@ int cpci_led_off(struct slot* slot) int __ref cpci_configure_slot(struct slot *slot) { + struct pci_dev *dev; struct pci_bus *parent; - int fn; dbg("%s - enter", __func__); @@ -282,18 +282,13 @@ int __ref cpci_configure_slot(struct slot *slot) } parent = slot->dev->bus; - for (fn = 0; fn < 8; fn++) { - struct pci_dev *dev; - - dev = pci_get_slot(parent, - PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); - if (!dev) + list_for_each_entry(dev, &parent->devices, bus_list) + if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) pci_hp_add_bridge(dev); - pci_dev_put(dev); - } + pci_assign_unassigned_bridge_resources(parent->self); @@ -305,8 +300,7 @@ int __ref cpci_configure_slot(struct slot *slot) int cpci_unconfigure_slot(struct slot* slot) { - int i; - struct pci_dev *dev; + struct pci_dev *dev, *temp; dbg("%s - enter", __func__); if (!slot->dev) { @@ -314,13 +308,12 @@ int cpci_unconfigure_slot(struct slot* slot) return -ENODEV; } - for (i = 0; i < 8; i++) { - dev = pci_get_slot(slot->bus, - PCI_DEVFN(PCI_SLOT(slot->devfn), i)); - if (dev) { - pci_stop_and_remove_bus_device(dev); - pci_dev_put(dev); - } + list_for_each_entry_safe(dev, temp, &slot->bus->devices, bus_list) { + if (PCI_SLOT(dev->devfn) != PCI_SLOT(slot->devfn)) + continue; + pci_dev_get(dev); + pci_stop_and_remove_bus_device(dev); + pci_dev_put(dev); } pci_dev_put(slot->dev); slot->dev = NULL; diff --git a/drivers/pci/hotplug/cpqphp_ctrl.c b/drivers/pci/hotplug/cpqphp_ctrl.c index 36112fe..d282019 100644 --- a/drivers/pci/hotplug/cpqphp_ctrl.c +++ b/drivers/pci/hotplug/cpqphp_ctrl.c @@ -1900,8 +1900,7 @@ static void interrupt_event_handler(struct controller *ctrl) dbg("power fault\n"); } else { /* refresh notification */ - if (p_slot) - update_slot_info(ctrl, p_slot); + update_slot_info(ctrl, p_slot); } ctrl->event_queue[loop].event_type = 0; @@ -2520,44 +2519,28 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func /* If we have IO resources copy them and fill in the bridge's * IO range registers */ - if (io_node) { - memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); - io_node->next = NULL; + memcpy(hold_IO_node, io_node, sizeof(struct pci_resource)); + io_node->next = NULL; - /* set IO base and Limit registers */ - temp_byte = io_node->base >> 8; - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte); + /* set IO base and Limit registers */ + temp_byte = io_node->base >> 8; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_BASE, temp_byte); - temp_byte = (io_node->base + io_node->length - 1) >> 8; - rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - } else { - kfree(hold_IO_node); - hold_IO_node = NULL; - } - - /* If we have memory resources copy them and fill in the - * bridge's memory range registers. Otherwise, fill in the - * range registers with values that disable them. */ - if (mem_node) { - memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); - mem_node->next = NULL; - - /* set Mem base and Limit registers */ - temp_word = mem_node->base >> 16; - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + temp_byte = (io_node->base + io_node->length - 1) >> 8; + rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte); - temp_word = (mem_node->base + mem_node->length - 1) >> 16; - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); - } else { - temp_word = 0xFFFF; - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); + /* Copy the memory resources and fill in the bridge's memory + * range registers. + */ + memcpy(hold_mem_node, mem_node, sizeof(struct pci_resource)); + mem_node->next = NULL; - temp_word = 0x0000; - rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); + /* set Mem base and Limit registers */ + temp_word = mem_node->base >> 16; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_BASE, temp_word); - kfree(hold_mem_node); - hold_mem_node = NULL; - } + temp_word = (mem_node->base + mem_node->length - 1) >> 16; + rc = pci_bus_write_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word); memcpy(hold_p_mem_node, p_mem_node, sizeof(struct pci_resource)); p_mem_node->next = NULL; @@ -2627,7 +2610,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func /* Return unused bus resources * First use the temporary node to store information for * the board */ - if (hold_bus_node && bus_node && temp_resources.bus_head) { + if (bus_node && temp_resources.bus_head) { hold_bus_node->length = bus_node->base - hold_bus_node->base; hold_bus_node->next = func->bus_head; @@ -2751,7 +2734,7 @@ static int configure_new_function(struct controller *ctrl, struct pci_func *func } /* If we have prefetchable memory space available and there * is some left at the end, return the unused portion */ - if (hold_p_mem_node && temp_resources.p_mem_head) { + if (temp_resources.p_mem_head) { p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head), &hold_p_mem_node, 0x100000); diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index 09cecaf..aac7a40 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -39,7 +39,7 @@ int pciehp_configure_device(struct slot *p_slot) struct pci_dev *dev; struct pci_dev *bridge = p_slot->ctrl->pcie->port; struct pci_bus *parent = bridge->subordinate; - int num, fn; + int num; struct controller *ctrl = p_slot->ctrl; dev = pci_get_slot(parent, PCI_DEVFN(0, 0)); @@ -57,28 +57,18 @@ int pciehp_configure_device(struct slot *p_slot) return -ENODEV; } - for (fn = 0; fn < 8; fn++) { - dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); - if (!dev) - continue; + list_for_each_entry(dev, &parent->devices, bus_list) if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) pci_hp_add_bridge(dev); - pci_dev_put(dev); - } pci_assign_unassigned_bridge_resources(bridge); - for (fn = 0; fn < 8; fn++) { - dev = pci_get_slot(parent, PCI_DEVFN(0, fn)); - if (!dev) + list_for_each_entry(dev, &parent->devices, bus_list) { + if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) continue; - if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) { - pci_dev_put(dev); - continue; - } + pci_configure_slot(dev); - pci_dev_put(dev); } pci_bus_add_devices(parent); @@ -89,9 +79,9 @@ int pciehp_configure_device(struct slot *p_slot) int pciehp_unconfigure_device(struct slot *p_slot) { int ret, rc = 0; - int j; u8 bctl = 0; u8 presence = 0; + struct pci_dev *dev, *temp; struct pci_bus *parent = p_slot->ctrl->pcie->port->subordinate; u16 command; struct controller *ctrl = p_slot->ctrl; @@ -102,33 +92,31 @@ int pciehp_unconfigure_device(struct slot *p_slot) if (ret) presence = 0; - for (j = 0; j < 8; j++) { - struct pci_dev *temp = pci_get_slot(parent, PCI_DEVFN(0, j)); - if (!temp) - continue; - if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { - pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); + list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { + pci_dev_get(dev); + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) { + pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl); if (bctl & PCI_BRIDGE_CTL_VGA) { ctrl_err(ctrl, "Cannot remove display device %s\n", - pci_name(temp)); - pci_dev_put(temp); + pci_name(dev)); + pci_dev_put(dev); rc = -EINVAL; break; } } - pci_stop_and_remove_bus_device(temp); + pci_stop_and_remove_bus_device(dev); /* * Ensure that no new Requests will be generated from * the device. */ if (presence) { - pci_read_config_word(temp, PCI_COMMAND, &command); + pci_read_config_word(dev, PCI_COMMAND, &command); command &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_SERR); command |= PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(temp, PCI_COMMAND, command); + pci_write_config_word(dev, PCI_COMMAND, command); } - pci_dev_put(temp); + pci_dev_put(dev); } return rc; diff --git a/drivers/pci/hotplug/sgi_hotplug.c b/drivers/pci/hotplug/sgi_hotplug.c index ae606b3..180e760 100644 --- a/drivers/pci/hotplug/sgi_hotplug.c +++ b/drivers/pci/hotplug/sgi_hotplug.c @@ -334,7 +334,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) struct slot *slot = bss_hotplug_slot->private; struct pci_bus *new_bus = NULL; struct pci_dev *dev; - int func, num_funcs; + int num_funcs; int new_ppb = 0; int rc; char *ssdt = NULL; @@ -381,29 +381,26 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) * to the Linux PCI interface and tell the drivers * about them. */ - for (func = 0; func < num_funcs; func++) { - dev = pci_get_slot(slot->pci_bus, - PCI_DEVFN(slot->device_num + 1, - PCI_FUNC(func))); - if (dev) { - /* Need to do slot fixup on PPB before fixup of children - * (PPB's pcidev_info needs to be in pcidev_info list - * before child's SN_PCIDEV_INFO() call to setup - * pdi_host_pcidev_info). - */ - pcibios_fixup_device_resources(dev); - if (SN_ACPI_BASE_SUPPORT()) - sn_acpi_slot_fixup(dev); - else - sn_io_slot_fixup(dev); - if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - pci_hp_add_bridge(dev); - if (dev->subordinate) { - new_bus = dev->subordinate; - new_ppb = 1; - } + list_for_each_entry(dev, &slot->pci_bus->devices, bus_list) { + if (PCI_SLOT(dev->devfn) != slot->device_num + 1) + continue; + + /* Need to do slot fixup on PPB before fixup of children + * (PPB's pcidev_info needs to be in pcidev_info list + * before child's SN_PCIDEV_INFO() call to setup + * pdi_host_pcidev_info). + */ + pcibios_fixup_device_resources(dev); + if (SN_ACPI_BASE_SUPPORT()) + sn_acpi_slot_fixup(dev); + else + sn_io_slot_fixup(dev); + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_hp_add_bridge(dev); + if (dev->subordinate) { + new_bus = dev->subordinate; + new_ppb = 1; } - pci_dev_put(dev); } } @@ -481,8 +478,7 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) static int disable_slot(struct hotplug_slot *bss_hotplug_slot) { struct slot *slot = bss_hotplug_slot->private; - struct pci_dev *dev; - int func; + struct pci_dev *dev, *temp; int rc; acpi_owner_id ssdt_id = 0; @@ -542,15 +538,14 @@ static int disable_slot(struct hotplug_slot *bss_hotplug_slot) } /* Free the SN resources assigned to the Linux device.*/ - for (func = 0; func < 8; func++) { - dev = pci_get_slot(slot->pci_bus, - PCI_DEVFN(slot->device_num + 1, - PCI_FUNC(func))); - if (dev) { - sn_bus_free_data(dev); - pci_stop_and_remove_bus_device(dev); - pci_dev_put(dev); - } + list_for_each_entry_safe(dev, temp, &slot->pci_bus->devices, bus_list) { + if (PCI_SLOT(dev->devfn) != slot->device_num + 1) + continue; + + pci_dev_get(dev); + sn_bus_free_data(dev); + pci_stop_and_remove_bus_device(dev); + pci_dev_put(dev); } /* Remove the SSDT for the slot from the ACPI namespace */ diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index c627ed9..b0e8313 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c @@ -40,7 +40,7 @@ int __ref shpchp_configure_device(struct slot *p_slot) struct controller *ctrl = p_slot->ctrl; struct pci_dev *bridge = ctrl->pci_dev; struct pci_bus *parent = bridge->subordinate; - int num, fn; + int num; dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); if (dev) { @@ -57,24 +57,20 @@ int __ref shpchp_configure_device(struct slot *p_slot) return -ENODEV; } - for (fn = 0; fn < 8; fn++) { - dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); - if (!dev) + list_for_each_entry(dev, &parent->devices, bus_list) { + if (PCI_SLOT(dev->devfn) != p_slot->device) continue; if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) pci_hp_add_bridge(dev); - pci_dev_put(dev); } pci_assign_unassigned_bridge_resources(bridge); - for (fn = 0; fn < 8; fn++) { - dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn)); - if (!dev) + list_for_each_entry(dev, &parent->devices, bus_list) { + if (PCI_SLOT(dev->devfn) != p_slot->device) continue; pci_configure_slot(dev); - pci_dev_put(dev); } pci_bus_add_devices(parent); @@ -85,32 +81,32 @@ int __ref shpchp_configure_device(struct slot *p_slot) int shpchp_unconfigure_device(struct slot *p_slot) { int rc = 0; - int j; u8 bctl = 0; struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate; + struct pci_dev *dev, *temp; struct controller *ctrl = p_slot->ctrl; ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n", __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device); - for (j = 0; j < 8 ; j++) { - struct pci_dev *temp = pci_get_slot(parent, - (p_slot->device << 3) | j); - if (!temp) + list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) { + if (PCI_SLOT(dev->devfn) != p_slot->device) continue; - if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) { - pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl); + + pci_dev_get(dev); + if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { + pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl); if (bctl & PCI_BRIDGE_CTL_VGA) { ctrl_err(ctrl, "Cannot remove display device %s\n", - pci_name(temp)); - pci_dev_put(temp); + pci_name(dev)); + pci_dev_put(dev); rc = -EINVAL; break; } } - pci_stop_and_remove_bus_device(temp); - pci_dev_put(temp); + pci_stop_and_remove_bus_device(dev); + pci_dev_put(dev); } return rc; } diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 42736e2..1c2587c 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -302,24 +302,6 @@ static int acpi_pci_find_device(struct device *dev, acpi_handle *handle) return 0; } -static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle) -{ - int num; - unsigned int seg, bus; - - /* - * The string should be the same as root bridge's name - * Please look at 'pci_scan_bus_parented' - */ - num = sscanf(dev_name(dev), "pci%04x:%02x", &seg, &bus); - if (num != 2) - return -ENODEV; - *handle = acpi_get_pci_rootbridge_handle(seg, bus); - if (!*handle) - return -ENODEV; - return 0; -} - static void pci_acpi_setup(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -378,7 +360,6 @@ static void pci_acpi_cleanup(struct device *dev) static struct acpi_bus_type acpi_pci_bus = { .bus = &pci_bus_type, .find_device = acpi_pci_find_device, - .find_bridge = acpi_pci_find_root_bridge, .setup = pci_acpi_setup, .cleanup = pci_acpi_cleanup, }; diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 0c4f641..177a50f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1151,8 +1151,7 @@ int pci_reenable_device(struct pci_dev *dev) return 0; } -static int __pci_enable_device_flags(struct pci_dev *dev, - resource_size_t flags) +static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) { int err; int i, bars = 0; @@ -1196,7 +1195,7 @@ static int __pci_enable_device_flags(struct pci_dev *dev, */ int pci_enable_device_io(struct pci_dev *dev) { - return __pci_enable_device_flags(dev, IORESOURCE_IO); + return pci_enable_device_flags(dev, IORESOURCE_IO); } /** @@ -1209,7 +1208,7 @@ int pci_enable_device_io(struct pci_dev *dev) */ int pci_enable_device_mem(struct pci_dev *dev) { - return __pci_enable_device_flags(dev, IORESOURCE_MEM); + return pci_enable_device_flags(dev, IORESOURCE_MEM); } /** @@ -1225,7 +1224,7 @@ int pci_enable_device_mem(struct pci_dev *dev) */ int pci_enable_device(struct pci_dev *dev) { - return __pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO); + return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO); } /* @@ -2043,10 +2042,13 @@ void pci_free_cap_save_buffers(struct pci_dev *dev) } /** - * pci_enable_ari - enable ARI forwarding if hardware support it + * pci_configure_ari - enable or disable ARI forwarding * @dev: the PCI device + * + * If @dev and its upstream bridge both support ARI, enable ARI in the + * bridge. Otherwise, disable ARI in the bridge. */ -void pci_enable_ari(struct pci_dev *dev) +void pci_configure_ari(struct pci_dev *dev) { u32 cap; struct pci_dev *bridge; @@ -2054,9 +2056,6 @@ void pci_enable_ari(struct pci_dev *dev) if (pcie_ari_disabled || !pci_is_pcie(dev) || dev->devfn) return; - if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) - return; - bridge = dev->bus->self; if (!bridge) return; @@ -2065,8 +2064,15 @@ void pci_enable_ari(struct pci_dev *dev) if (!(cap & PCI_EXP_DEVCAP2_ARI)) return; - pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, PCI_EXP_DEVCTL2_ARI); - bridge->ari_enabled = 1; + if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI)) { + pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2, + PCI_EXP_DEVCTL2_ARI); + bridge->ari_enabled = 1; + } else { + pcie_capability_clear_word(bridge, PCI_EXP_DEVCTL2, + PCI_EXP_DEVCTL2_ARI); + bridge->ari_enabled = 0; + } } /** diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d295e7b..7346ee6 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -203,7 +203,8 @@ extern int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type, struct resource *res, unsigned int reg); extern int pci_resource_bar(struct pci_dev *dev, int resno, enum pci_bar_type *type); -extern void pci_enable_ari(struct pci_dev *dev); +extern void pci_configure_ari(struct pci_dev *dev); + /** * pci_ari_enabled - query ARI forwarding status * @bus: the PCI bus diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 281d90f..b494066 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1295,7 +1295,7 @@ static void pci_init_capabilities(struct pci_dev *dev) pci_vpd_pci22_init(dev); /* Alternative Routing-ID Forwarding */ - pci_enable_ari(dev); + pci_configure_ari(dev); /* Single Root I/O Virtualization */ pci_iov_init(dev); @@ -1371,31 +1371,31 @@ struct pci_dev *__ref pci_scan_single_device(struct pci_bus *bus, int devfn) } EXPORT_SYMBOL(pci_scan_single_device); -static unsigned next_ari_fn(struct pci_dev *dev, unsigned fn) +static unsigned next_fn(struct pci_bus *bus, struct pci_dev *dev, unsigned fn) { - u16 cap; - unsigned pos, next_fn; + int pos; + u16 cap = 0; + unsigned next_fn; - if (!dev) - return 0; + if (pci_ari_enabled(bus)) { + if (!dev) + return 0; + pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); + if (!pos) + return 0; - pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ARI); - if (!pos) - return 0; - pci_read_config_word(dev, pos + 4, &cap); - next_fn = cap >> 8; - if (next_fn <= fn) - return 0; - return next_fn; -} + pci_read_config_word(dev, pos + PCI_ARI_CAP, &cap); + next_fn = PCI_ARI_CAP_NFN(cap); + if (next_fn <= fn) + return 0; /* protect against malformed list */ -static unsigned next_trad_fn(struct pci_dev *dev, unsigned fn) -{ - return (fn + 1) % 8; -} + return next_fn; + } + + /* dev may be NULL for non-contiguous multifunction devices */ + if (!dev || dev->multifunction) + return (fn + 1) % 8; -static unsigned no_next_fn(struct pci_dev *dev, unsigned fn) -{ return 0; } @@ -1428,7 +1428,6 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) { unsigned fn, nr = 0; struct pci_dev *dev; - unsigned (*next_fn)(struct pci_dev *, unsigned) = no_next_fn; if (only_one_child(bus) && (devfn > 0)) return 0; /* Already scanned the entire slot */ @@ -1439,12 +1438,7 @@ int pci_scan_slot(struct pci_bus *bus, int devfn) if (!dev->is_added) nr++; - if (pci_ari_enabled(bus)) - next_fn = next_ari_fn; - else if (dev->multifunction) - next_fn = next_trad_fn; - - for (fn = next_fn(dev, 0); fn > 0; fn = next_fn(dev, fn)) { + for (fn = next_fn(bus, dev, 0); fn > 0; fn = next_fn(bus, dev, fn)) { dev = pci_scan_single_device(bus, devfn + fn); if (dev) { if (!dev->is_added) @@ -1655,6 +1649,18 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus) return max; } +/** + * pcibios_root_bridge_prepare - Platform-specific host bridge setup. + * @bridge: Host bridge to set up. + * + * Default empty implementation. Replace with an architecture-specific setup + * routine, if necessary. + */ +int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) +{ + return 0; +} + struct pci_bus *pci_create_root_bus(struct device *parent, int bus, struct pci_ops *ops, void *sysdata, struct list_head *resources) { @@ -1688,6 +1694,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, bridge->dev.parent = parent; bridge->dev.release = pci_release_bus_bridge_dev; dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(b), bus); + error = pcibios_root_bridge_prepare(bridge); + if (error) + goto bridge_dev_reg_err; + error = device_register(&bridge->dev); if (error) goto bridge_dev_reg_err; diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index d26c0d7..5ce8d5e8 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -408,7 +408,6 @@ struct acpi_pci_root { /* helper */ acpi_handle acpi_get_child(acpi_handle, u64); int acpi_is_root_bridge(acpi_handle); -acpi_handle acpi_get_pci_rootbridge_handle(unsigned int, unsigned int); struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle); #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)ACPI_HANDLE(dev)) diff --git a/include/linux/pci.h b/include/linux/pci.h index 8ee7e4e..056d3d6 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -379,6 +379,8 @@ void pci_set_host_bridge_release(struct pci_host_bridge *bridge, void (*release_fn)(struct pci_host_bridge *), void *release_data); +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge); + /* * The first PCI_BRIDGE_RESOURCE_NUM PCI bus resources (those that correspond * to P2P or CardBus bridge windows) go in a table. Additional ones (for |