From: Bjorn Helgaas Date: Mon, 24 Sep 2012 22:36:10 +0000 (-0600) Subject: Merge branch 'pci/taku-acpi-pci-host-bridge-v3' into next X-Git-Tag: v3.7-rc1~177^2~2 X-Git-Url: https://repo.jachan.dev/linux.git/commitdiff_plain/18d63c35a265465b7137c4ea9c6b135aada13c3c?hp=-c Merge branch 'pci/taku-acpi-pci-host-bridge-v3' into next --- 18d63c35a265465b7137c4ea9c6b135aada13c3c diff --combined drivers/acpi/pci_root.c index 72a2c98bc429,13f9b5ba3354..bce469c0b48a --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@@ -27,7 -27,7 +27,7 @@@ #include #include #include - #include + #include #include #include #include @@@ -71,9 -71,11 +71,11 @@@ static struct acpi_driver acpi_pci_root }, }; + /* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */ + static DEFINE_MUTEX(acpi_pci_root_lock); static LIST_HEAD(acpi_pci_roots); + static LIST_HEAD(acpi_pci_drivers); - static struct acpi_pci_driver *sub_driver; static DEFINE_MUTEX(osc_lock); int acpi_pci_register_driver(struct acpi_pci_driver *driver) @@@ -81,55 -83,46 +83,46 @@@ int n = 0; struct acpi_pci_root *root; - struct acpi_pci_driver **pptr = &sub_driver; - while (*pptr) - pptr = &(*pptr)->next; - *pptr = driver; - - if (!driver->add) - return 0; - - list_for_each_entry(root, &acpi_pci_roots, node) { - driver->add(root->device->handle); - n++; - } + mutex_lock(&acpi_pci_root_lock); + list_add_tail(&driver->node, &acpi_pci_drivers); + if (driver->add) + list_for_each_entry(root, &acpi_pci_roots, node) { + driver->add(root); + n++; + } + mutex_unlock(&acpi_pci_root_lock); return n; } - EXPORT_SYMBOL(acpi_pci_register_driver); void acpi_pci_unregister_driver(struct acpi_pci_driver *driver) { struct acpi_pci_root *root; - struct acpi_pci_driver **pptr = &sub_driver; - while (*pptr) { - if (*pptr == driver) - break; - pptr = &(*pptr)->next; - } - BUG_ON(!*pptr); - *pptr = (*pptr)->next; - - if (!driver->remove) - return; - - list_for_each_entry(root, &acpi_pci_roots, node) - driver->remove(root->device->handle); + mutex_lock(&acpi_pci_root_lock); + list_del(&driver->node); + if (driver->remove) + list_for_each_entry(root, &acpi_pci_roots, node) + driver->remove(root); + mutex_unlock(&acpi_pci_root_lock); } - 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)) - return root->device->handle; - return NULL; + (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); @@@ -277,12 -270,15 +270,15 @@@ static acpi_status acpi_pci_osc_support struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle) { struct acpi_pci_root *root; + struct acpi_device *device; - list_for_each_entry(root, &acpi_pci_roots, node) { - if (root->device->handle == handle) - return root; - } - return NULL; + if (acpi_bus_get_device(handle, &device) || + acpi_match_device_ids(device, root_device_ids)) + return NULL; + + root = acpi_driver_data(device); + + return root; } EXPORT_SYMBOL_GPL(acpi_pci_find_root); @@@ -518,8 -514,9 +514,9 @@@ static int __devinit acpi_pci_root_add( * TBD: Need PCI interface for enumeration/configuration of roots. */ - /* TBD: Locking */ + mutex_lock(&acpi_pci_root_lock); list_add_tail(&root->node, &acpi_pci_roots); + mutex_unlock(&acpi_pci_root_lock); printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", acpi_device_name(device), acpi_device_bid(device), @@@ -538,7 -535,7 +535,7 @@@ "Bus %04x:%02x not present in PCI namespace\n", root->segment, (unsigned int)root->secondary.start); result = -ENODEV; - goto end; + goto out_del_root; } /* @@@ -548,7 -545,7 +545,7 @@@ */ result = acpi_pci_bind_root(device); if (result) - goto end; + goto out_del_root; /* * PCI Routing Table @@@ -573,15 -570,8 +570,15 @@@ OSC_CLOCK_PWR_CAPABILITY_SUPPORT; if (pci_msi_enabled()) flags |= OSC_MSI_SUPPORT; - if (flags != base_flags) - acpi_pci_osc_support(root, flags); + if (flags != base_flags) { + status = acpi_pci_osc_support(root, flags); + if (ACPI_FAILURE(status)) { + dev_info(root->bus->bridge, "ACPI _OSC support " + "notification failed, disabling PCIe ASPM\n"); + pcie_no_aspm(); + flags = base_flags; + } + } if (!pcie_ports_disabled && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) { @@@ -633,9 -623,11 +630,11 @@@ return 0; + out_del_root: + mutex_lock(&acpi_pci_root_lock); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); end: - if (!list_empty(&root->node)) - list_del(&root->node); kfree(root); return result; } @@@ -643,18 -635,34 +642,34 @@@ static int acpi_pci_root_start(struct acpi_device *device) { struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_driver *driver; + + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry(driver, &acpi_pci_drivers, node) + if (driver->add) + driver->add(root); + mutex_unlock(&acpi_pci_root_lock); pci_bus_add_devices(root->bus); + return 0; } static int acpi_pci_root_remove(struct acpi_device *device, int type) { struct acpi_pci_root *root = acpi_driver_data(device); + struct acpi_pci_driver *driver; + + mutex_lock(&acpi_pci_root_lock); + list_for_each_entry(driver, &acpi_pci_drivers, node) + if (driver->remove) + driver->remove(root); device_set_run_wake(root->bus->bridge, false); pci_acpi_remove_bus_pm_notifier(device); + list_del(&root->node); + mutex_unlock(&acpi_pci_root_lock); kfree(root); return 0; } diff --combined include/linux/acpi.h index 4f2a76224509,6906e6fb82ea..90be98981102 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@@ -96,7 -96,7 +96,7 @@@ void acpi_table_print_madt_entry (struc void acpi_numa_slit_init (struct acpi_table_slit *slit); void acpi_numa_processor_affinity_init (struct acpi_srat_cpu_affinity *pa); void acpi_numa_x2apic_affinity_init(struct acpi_srat_x2apic_cpu_affinity *pa); -void acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); +int acpi_numa_memory_affinity_init (struct acpi_srat_mem_affinity *ma); void acpi_numa_arch_fixup(void); #ifdef CONFIG_ACPI_HOTPLUG_CPU @@@ -138,9 -138,9 +138,9 @@@ void acpi_penalize_isa_irq(int irq, in void acpi_pci_irq_disable (struct pci_dev *dev); struct acpi_pci_driver { - struct acpi_pci_driver *next; - int (*add)(acpi_handle handle); - void (*remove)(acpi_handle handle); + struct list_head node; + int (*add)(struct acpi_pci_root *root); + void (*remove)(struct acpi_pci_root *root); }; int acpi_pci_register_driver(struct acpi_pci_driver *driver);