aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2008-02-23 00:54:24 -0500
committerLen Brown <len.brown@intel.com>2008-02-23 01:32:56 -0500
commit1071695f17daf050638e0bc550db647f8237c3bb (patch)
tree4770e712c2293d0156fbb53bebc6fa059a8a99eb /drivers/acpi
parent39273b58a409cd6d65c9732bdca00bacd1626672 (diff)
ACPI: crosslink ACPI and "real" device nodes
Add cross-links between ACPI device and "real" devices in sysfs, exposing otherwise-hidden interrelationships between the various device nodes for ACPI stuff. As a representative example, one hardware device is exposed as two logical devices (PNP and ACPI): .../pnp0/00:06/ .../LNXSYSTM:00/device:00/PNP0A03:00/device:15/PNP0B00:00/ The PNP device gets a "firmware_node" link pointing to the ACPI device, and is what a Linux device driver binds to. The ACPI device has instead a "physical_node" link pointing back to the PNP device. Other firmware frameworks, like OpenFirmware, could do the same thing to couple their firmware tables to the rest of the system. (Based on a patch from Zhang Rui. This version is modified to not depend on the patch makig ACPI initialize driver model wakeup flags.) Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/glue.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index eda0978b57c6..06f8634fe58b 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -142,6 +142,7 @@ EXPORT_SYMBOL(acpi_get_physical_device);
142 142
143static int acpi_bind_one(struct device *dev, acpi_handle handle) 143static int acpi_bind_one(struct device *dev, acpi_handle handle)
144{ 144{
145 struct acpi_device *acpi_dev;
145 acpi_status status; 146 acpi_status status;
146 147
147 if (dev->archdata.acpi_handle) { 148 if (dev->archdata.acpi_handle) {
@@ -157,6 +158,16 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
157 } 158 }
158 dev->archdata.acpi_handle = handle; 159 dev->archdata.acpi_handle = handle;
159 160
161 status = acpi_bus_get_device(handle, &acpi_dev);
162 if (!ACPI_FAILURE(status)) {
163 int ret;
164
165 ret = sysfs_create_link(&dev->kobj, &acpi_dev->dev.kobj,
166 "firmware_node");
167 ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
168 "physical_node");
169 }
170
160 return 0; 171 return 0;
161} 172}
162 173
@@ -165,8 +176,17 @@ static int acpi_unbind_one(struct device *dev)
165 if (!dev->archdata.acpi_handle) 176 if (!dev->archdata.acpi_handle)
166 return 0; 177 return 0;
167 if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) { 178 if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
179 struct acpi_device *acpi_dev;
180
168 /* acpi_get_physical_device increase refcnt by one */ 181 /* acpi_get_physical_device increase refcnt by one */
169 put_device(dev); 182 put_device(dev);
183
184 if (!acpi_bus_get_device(dev->archdata.acpi_handle,
185 &acpi_dev)) {
186 sysfs_remove_link(&dev->kobj, "firmware_node");
187 sysfs_remove_link(&acpi_dev->dev.kobj, "physical_node");
188 }
189
170 acpi_detach_data(dev->archdata.acpi_handle, 190 acpi_detach_data(dev->archdata.acpi_handle,
171 acpi_glue_data_handler); 191 acpi_glue_data_handler);
172 dev->archdata.acpi_handle = NULL; 192 dev->archdata.acpi_handle = NULL;