diff options
| -rw-r--r-- | drivers/pci/hotplug/acpiphp_glue.c | 41 |
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index ad6fd6695495..e6da3927c497 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -115,6 +115,35 @@ static const struct acpi_dock_ops acpiphp_dock_ops = { | |||
| 115 | .handler = handle_hotplug_event_func, | 115 | .handler = handle_hotplug_event_func, |
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | /* Check whether the PCI device is managed by native PCIe hotplug driver */ | ||
| 119 | static bool device_is_managed_by_native_pciehp(struct pci_dev *pdev) | ||
| 120 | { | ||
| 121 | u32 reg32; | ||
| 122 | acpi_handle tmp; | ||
| 123 | struct acpi_pci_root *root; | ||
| 124 | |||
| 125 | /* Check whether the PCIe port supports native PCIe hotplug */ | ||
| 126 | if (pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, ®32)) | ||
| 127 | return false; | ||
| 128 | if (!(reg32 & PCI_EXP_SLTCAP_HPC)) | ||
| 129 | return false; | ||
| 130 | |||
| 131 | /* | ||
| 132 | * Check whether native PCIe hotplug has been enabled for | ||
| 133 | * this PCIe hierarchy. | ||
| 134 | */ | ||
| 135 | tmp = acpi_find_root_bridge_handle(pdev); | ||
| 136 | if (!tmp) | ||
| 137 | return false; | ||
| 138 | root = acpi_pci_find_root(tmp); | ||
| 139 | if (!root) | ||
| 140 | return false; | ||
| 141 | if (!(root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) | ||
| 142 | return false; | ||
| 143 | |||
| 144 | return true; | ||
| 145 | } | ||
| 146 | |||
| 118 | /* callback routine to register each ACPI PCI slot object */ | 147 | /* callback routine to register each ACPI PCI slot object */ |
| 119 | static acpi_status | 148 | static acpi_status |
| 120 | register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | 149 | register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) |
| @@ -142,16 +171,8 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 142 | function = adr & 0xffff; | 171 | function = adr & 0xffff; |
| 143 | 172 | ||
| 144 | pdev = pbus->self; | 173 | pdev = pbus->self; |
| 145 | if (pdev && pci_is_pcie(pdev)) { | 174 | if (pdev && device_is_managed_by_native_pciehp(pdev)) |
| 146 | tmp = acpi_find_root_bridge_handle(pdev); | 175 | return AE_OK; |
| 147 | if (tmp) { | ||
| 148 | struct acpi_pci_root *root = acpi_pci_find_root(tmp); | ||
| 149 | |||
| 150 | if (root && (root->osc_control_set & | ||
| 151 | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)) | ||
| 152 | return AE_OK; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | 176 | ||
| 156 | newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); | 177 | newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); |
| 157 | if (!newfunc) | 178 | if (!newfunc) |
