summaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/acpi_pcihp.c
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2008-12-17 12:09:12 +0900
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-01-07 11:13:11 -0800
commite8c331e963c58b83db24b7d0e39e8c07f687dbc6 (patch)
treeda9e7df2441da952dc11bd732b0171d3170fa8bf /drivers/pci/hotplug/acpi_pcihp.c
parente046cbd6c05ee859244245d7beeac395cd0057b3 (diff)
PCI hotplug: introduce functions for ACPI slot detection
Some ACPI related PCI hotplug code can be shared among PCI hotplug drivers. This patch introduces the following functions in drivers/pci/hotplug/acpi_pcihp.c to share the code, and changes acpiphp and pciehp to use them. - int acpi_pci_detect_ejectable(struct pci_bus *pbus) This checks if the specified PCI bus has ejectable slots. - int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle) This checks if the specified handle is ejectable ACPI PCI slot. The 'pbus' parameter is needed to check if 'handle' is PCI related ACPI object. This patch also introduces the following inline function in include/linux/pci-acpi.h, which is useful to get ACPI handle of the PCI bridge from struct pci_bus of the bridge's secondary bus. - static inline acpi_handle acpi_pci_get_bridge_handle(struct pci_bus *pbus) This returns ACPI handle of the PCI bridge which generates PCI bus specified by 'pbus'. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/hotplug/acpi_pcihp.c')
-rw-r--r--drivers/pci/hotplug/acpi_pcihp.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c
index e17ef54f0ef..c62ab8d240a 100644
--- a/drivers/pci/hotplug/acpi_pcihp.c
+++ b/drivers/pci/hotplug/acpi_pcihp.c
@@ -501,5 +501,74 @@ int acpi_root_bridge(acpi_handle handle)
}
EXPORT_SYMBOL_GPL(acpi_root_bridge);
+
+static int is_ejectable(acpi_handle handle)
+{
+ acpi_status status;
+ acpi_handle tmp;
+ unsigned long long removable;
+ status = acpi_get_handle(handle, "_ADR", &tmp);
+ if (ACPI_FAILURE(status))
+ return 0;
+ status = acpi_get_handle(handle, "_EJ0", &tmp);
+ if (ACPI_SUCCESS(status))
+ return 1;
+ status = acpi_evaluate_integer(handle, "_RMV", NULL, &removable);
+ if (ACPI_SUCCESS(status) && removable)
+ return 1;
+ return 0;
+}
+
+/**
+ * acpi_pcihp_check_ejectable - check if handle is ejectable ACPI PCI slot
+ * @pbus: the PCI bus of the PCI slot corresponding to 'handle'
+ * @handle: ACPI handle to check
+ *
+ * Return 1 if handle is ejectable PCI slot, 0 otherwise.
+ */
+int acpi_pci_check_ejectable(struct pci_bus *pbus, acpi_handle handle)
+{
+ acpi_handle bridge_handle, parent_handle;
+
+ if (!(bridge_handle = acpi_pci_get_bridge_handle(pbus)))
+ return 0;
+ if ((ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))))
+ return 0;
+ if (bridge_handle != parent_handle)
+ return 0;
+ return is_ejectable(handle);
+}
+EXPORT_SYMBOL_GPL(acpi_pci_check_ejectable);
+
+static acpi_status
+check_hotplug(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+ int *found = (int *)context;
+ if (is_ejectable(handle)) {
+ *found = 1;
+ return AE_CTRL_TERMINATE;
+ }
+ return AE_OK;
+}
+
+/**
+ * acpi_pci_detect_ejectable - check if the PCI bus has ejectable slots
+ * @pbus - PCI bus to scan
+ *
+ * Returns 1 if the PCI bus has ACPI based ejectable slots, 0 otherwise.
+ */
+int acpi_pci_detect_ejectable(struct pci_bus *pbus)
+{
+ acpi_handle handle;
+ int found = 0;
+
+ if (!(handle = acpi_pci_get_bridge_handle(pbus)))
+ return 0;
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, (u32)1,
+ check_hotplug, (void *)&found, NULL);
+ return found;
+}
+EXPORT_SYMBOL_GPL(acpi_pci_detect_ejectable);
+
module_param(debug_acpi, bool, 0644);
MODULE_PARM_DESC(debug_acpi, "Debugging mode for ACPI enabled or not");