]> Git Repo - linux.git/commitdiff
Merge branch 'pci/taku-acpi-pci-host-bridge-v3' into next
authorBjorn Helgaas <[email protected]>
Mon, 24 Sep 2012 22:36:10 +0000 (16:36 -0600)
committerBjorn Helgaas <[email protected]>
Mon, 24 Sep 2012 22:36:10 +0000 (16:36 -0600)
1  2 
drivers/acpi/pci_root.c
include/linux/acpi.h

diff --combined drivers/acpi/pci_root.c
index 72a2c98bc4298e8518e7d2b388f0e2d5d3abdc5f,13f9b5ba3354bf43fddb58d3eb12933418e7ccd5..bce469c0b48a05bc29ecd4c9dfdd9aef9e6d4ea7
@@@ -27,7 -27,7 +27,7 @@@
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/types.h>
- #include <linux/spinlock.h>
+ #include <linux/mutex.h>
  #include <linux/pm.h>
  #include <linux/pm_runtime.h>
  #include <linux/pci.h>
@@@ -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)
        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),
                            "Bus %04x:%02x not present in PCI namespace\n",
                            root->segment, (unsigned int)root->secondary.start);
                result = -ENODEV;
-               goto end;
+               goto out_del_root;
        }
  
        /*
         */
        result = acpi_pci_bind_root(device);
        if (result)
-               goto end;
+               goto out_del_root;
  
        /*
         * PCI Routing Table
                        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) {
  
        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;
  }
  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 4f2a76224509ef5c652a8503153ca73435b9dde1,6906e6fb82ea1ca90758ac06e9b0d0adbcdd820a..90be9898110202f918a3d75d72da9437bb249bc5
@@@ -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);
This page took 0.088932 seconds and 4 git commands to generate.