]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge branch 'pci/jiang-acpiphp' into next
authorBjorn Helgaas <bhelgaas@google.com>
Mon, 24 Sep 2012 22:36:48 +0000 (16:36 -0600)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 24 Sep 2012 22:36:48 +0000 (16:36 -0600)
1  2 
drivers/pci/hotplug/acpiphp_glue.c

index 466233b481b1b0cac3afe25d15f93357e8d1347f,e6da3927c497fb8ed60db4c3bd7975359ebc082f..3d6d4fd1e3c5fedfa07bed77f4fb0768b7bfe626
@@@ -115,6 -115,35 +115,35 @@@ static const struct acpi_dock_ops acpip
        .handler = handle_hotplug_event_func,
  };
  
+ /* Check whether the PCI device is managed by native PCIe hotplug driver */
+ static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev)
+ {
+       u32 reg32;
+       acpi_handle tmp;
+       struct acpi_pci_root *root;
+       /* Check whether the PCIe port supports native PCIe hotplug */
+       if (pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &reg32))
+               return false;
+       if (!(reg32 & PCI_EXP_SLTCAP_HPC))
+               return false;
+       /*
+        * Check whether native PCIe hotplug has been enabled for
+        * this PCIe hierarchy.
+        */
+       tmp = acpi_find_root_bridge_handle(pdev);
+       if (!tmp)
+               return false;
+       root = acpi_pci_find_root(tmp);
+       if (!root)
+               return false;
+       if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
+               return false;
+       return true;
+ }
  /* callback routine to register each ACPI PCI slot object */
  static acpi_status
  register_slot(acpi_handle handle, u32 lvl, void *context, void **rv)
        function = adr & 0xffff;
  
        pdev = pbus->self;
-       if (pdev && pci_is_pcie(pdev)) {
-               tmp = acpi_find_root_bridge_handle(pdev);
-               if (tmp) {
-                       struct acpi_pci_root *root = acpi_pci_find_root(tmp);
-                       if (root && (root->osc_control_set &
-                                       OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
-                               return AE_OK;
-               }
-       }
+       if (pdev && device_is_managed_by_native_pciehp(pdev))
+               return AE_OK;
  
        newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL);
        if (!newfunc)
@@@ -382,10 -403,10 +403,10 @@@ static inline void config_p2p_bridge_fl
  
  
  /* allocate and initialize host bridge data structure */
 -static void add_host_bridge(acpi_handle *handle)
 +static void add_host_bridge(struct acpi_pci_root *root)
  {
        struct acpiphp_bridge *bridge;
 -      struct acpi_pci_root *root = acpi_pci_find_root(handle);
 +      acpi_handle handle = root->device->handle;
  
        bridge = kzalloc(sizeof(struct acpiphp_bridge), GFP_KERNEL);
        if (bridge == NULL)
@@@ -468,12 -489,11 +489,12 @@@ find_p2p_bridge(acpi_handle handle, u3
  
  
  /* find hot-pluggable slots, and then find P2P bridge */
 -static int add_bridge(acpi_handle handle)
 +static int add_bridge(struct acpi_pci_root *root)
  {
        acpi_status status;
        unsigned long long tmp;
        acpi_handle dummy_handle;
 +      acpi_handle handle = root->device->handle;
  
        /* if the bridge doesn't have _STA, we assume it is always there */
        status = acpi_get_handle(handle, "_STA", &dummy_handle);
        /* check if this bridge has ejectable slots */
        if (detect_ejectable_slots(handle) > 0) {
                dbg("found PCI host-bus bridge with hot-pluggable slots\n");
 -              add_host_bridge(handle);
 +              add_host_bridge(root);
        }
  
        /* search P2P bridges under this host bridge */
@@@ -589,10 -609,9 +610,10 @@@ cleanup_p2p_bridge(acpi_handle handle, 
        return AE_OK;
  }
  
 -static void remove_bridge(acpi_handle handle)
 +static void remove_bridge(struct acpi_pci_root *root)
  {
        struct acpiphp_bridge *bridge;
 +      acpi_handle handle = root->device->handle;
  
        /* cleanup p2p bridges under this host bridge
           in a depth-first manner */
@@@ -871,6 -890,17 +892,6 @@@ static int __ref enable_device(struct a
        return retval;
  }
  
 -static void disable_bridges(struct pci_bus *bus)
 -{
 -      struct pci_dev *dev;
 -      list_for_each_entry(dev, &bus->devices, bus_list) {
 -              if (dev->subordinate) {
 -                      disable_bridges(dev->subordinate);
 -                      pci_disable_device(dev);
 -              }
 -      }
 -}
 -
  /* return first device in slot, acquiring a reference on it */
  static struct pci_dev *dev_in_slot(struct acpiphp_slot *slot)
  {
@@@ -922,7 -952,12 +943,7 @@@ static int disable_device(struct acpiph
         * here.
         */
        while ((pdev = dev_in_slot(slot))) {
 -              pci_stop_bus_device(pdev);
 -              if (pdev->subordinate) {
 -                      disable_bridges(pdev->subordinate);
 -                      pci_disable_device(pdev);
 -              }
 -              __pci_remove_bus_device(pdev);
 +              pci_stop_and_remove_bus_device(pdev);
                pci_dev_put(pdev);
        }
  
@@@ -1463,6 -1498,34 +1484,6 @@@ int __init acpiphp_get_num_slots(void
  }
  
  
 -#if 0
 -/**
 - * acpiphp_for_each_slot - call function for each slot
 - * @fn: callback function
 - * @data: context to be passed to callback function
 - */
 -static int acpiphp_for_each_slot(acpiphp_callback fn, void *data)
 -{
 -      struct list_head *node;
 -      struct acpiphp_bridge *bridge;
 -      struct acpiphp_slot *slot;
 -      int retval = 0;
 -
 -      list_for_each (node, &bridge_list) {
 -              bridge = (struct acpiphp_bridge *)node;
 -              for (slot = bridge->slots; slot; slot = slot->next) {
 -                      retval = fn(slot, data);
 -                      if (!retval)
 -                              goto err_exit;
 -              }
 -      }
 -
 - err_exit:
 -      return retval;
 -}
 -#endif
 -
 -
  /**
   * acpiphp_enable_slot - power on slot
   * @slot: ACPI PHP slot