aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2008-08-11 01:40:22 -0400
committerLen Brown <len.brown@intel.com>2008-10-22 18:00:50 -0400
commit39a0ad871000d2a016a4fa113a6e53d22aabf25d (patch)
treee4ff7eabccc74b2d16e80d78c2e255d2d004cd4d
parent6415e12ba0f92a54f02d9c4ecaa3c82f35f3d335 (diff)
ACPI : Load device driver according to the status of acpi device
According to ACPI spec when the status of some device is not present but functional, the device is valid and the children of this device should be enumerated. It means that the device should be added to linux acpi device tree. But the device driver for this device should not be loaded. The detailed info can be found in the section 6.3.7 of ACPI 3.0b spec. _STA may return bit 0 clear (not present) with bit 3 set (device is functional). This case is used to indicate a valid device for which no device driver should be loaded (for example, a bridge device.). Children of this device may be present and valid. OS should continue enumeration below a device whose _STA returns this bit combination http://bugzilla.kernel.org/show_bug.cgi?id=3358 Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/bus.c16
-rw-r--r--drivers/acpi/scan.c35
-rw-r--r--drivers/pnp/pnpacpi/core.c6
3 files changed, 38 insertions, 19 deletions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 945cd2f2807d..e9b116d2b56d 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -112,21 +112,21 @@ int acpi_bus_get_status(struct acpi_device *device)
112 } 112 }
113 113
114 /* 114 /*
115 * Otherwise we assume the status of our parent (unless we don't 115 * According to ACPI spec some device can be present and functional
116 * have one, in which case status is implied). 116 * even if the parent is not present but functional.
117 * In such conditions the child device should not inherit the status
118 * from the parent.
117 */ 119 */
118 else if (device->parent)
119 device->status = device->parent->status;
120 else 120 else
121 STRUCT_TO_INT(device->status) = 121 STRUCT_TO_INT(device->status) =
122 ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | 122 ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED |
123 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING; 123 ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING;
124 124
125 if (device->status.functional && !device->status.present) { 125 if (device->status.functional && !device->status.present) {
126 printk(KERN_WARNING PREFIX "Device [%s] status [%08x]: " 126 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]: "
127 "functional but not present; setting present\n", 127 "functional but not present;\n",
128 device->pnp.bus_id, (u32) STRUCT_TO_INT(device->status)); 128 device->pnp.bus_id,
129 device->status.present = 1; 129 (u32) STRUCT_TO_INT(device->status)));
130 } 130 }
131 131
132 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n", 132 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] status [%08x]\n",
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index ad0679843bd5..89c112ef9e14 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -276,6 +276,13 @@ int acpi_match_device_ids(struct acpi_device *device,
276{ 276{
277 const struct acpi_device_id *id; 277 const struct acpi_device_id *id;
278 278
279 /*
280 * If the device is not present, it is unnecessary to load device
281 * driver for it.
282 */
283 if (!device->status.present)
284 return -ENODEV;
285
279 if (device->flags.hardware_id) { 286 if (device->flags.hardware_id) {
280 for (id = ids; id->id[0]; id++) { 287 for (id = ids; id->id[0]; id++) {
281 if (!strcmp((char*)id->id, device->pnp.hardware_id)) 288 if (!strcmp((char*)id->id, device->pnp.hardware_id))
@@ -1222,15 +1229,18 @@ acpi_add_single_object(struct acpi_device **child,
1222 result = -ENODEV; 1229 result = -ENODEV;
1223 goto end; 1230 goto end;
1224 } 1231 }
1225 if (!device->status.present) { 1232 /*
1226 /* Bay and dock should be handled even if absent */ 1233 * When the device is neither present nor functional, the
1227 if (!ACPI_SUCCESS( 1234 * device should not be added to Linux ACPI device tree.
1228 acpi_is_child_device(device, acpi_bay_match)) && 1235 * When the status of the device is not present but functinal,
1229 !ACPI_SUCCESS( 1236 * it should be added to Linux ACPI tree. For example : bay
1230 acpi_is_child_device(device, acpi_dock_match))) { 1237 * device , dock device.
1231 result = -ENODEV; 1238 * In such conditions it is unncessary to check whether it is
1232 goto end; 1239 * bay device or dock device.
1233 } 1240 */
1241 if (!device->status.present && !device->status.functional) {
1242 result = -ENODEV;
1243 goto end;
1234 } 1244 }
1235 break; 1245 break;
1236 default: 1246 default:
@@ -1411,7 +1421,12 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
1411 * TBD: Need notifications and other detection mechanisms 1421 * TBD: Need notifications and other detection mechanisms
1412 * in place before we can fully implement this. 1422 * in place before we can fully implement this.
1413 */ 1423 */
1414 if (child->status.present) { 1424 /*
1425 * When the device is not present but functional, it is also
1426 * necessary to scan the children of this device.
1427 */
1428 if (child->status.present || (!child->status.present &&
1429 child->status.functional)) {
1415 status = acpi_get_next_object(ACPI_TYPE_ANY, chandle, 1430 status = acpi_get_next_object(ACPI_TYPE_ANY, chandle,
1416 NULL, NULL); 1431 NULL, NULL);
1417 if (ACPI_SUCCESS(status)) { 1432 if (ACPI_SUCCESS(status)) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index c1b9ea34977b..98b9df7776e9 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -148,9 +148,13 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
148 acpi_status status; 148 acpi_status status;
149 struct pnp_dev *dev; 149 struct pnp_dev *dev;
150 150
151 /*
152 * If a PnPacpi device is not present , the device
153 * driver should not be loaded.
154 */
151 status = acpi_get_handle(device->handle, "_CRS", &temp); 155 status = acpi_get_handle(device->handle, "_CRS", &temp);
152 if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) || 156 if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
153 is_exclusive_device(device)) 157 is_exclusive_device(device) || (!device->status.present))
154 return 0; 158 return 0;
155 159
156 dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device)); 160 dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));