aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLi Shaohua <shaohua.li@intel.com>2006-12-07 07:56:41 -0500
committerLen Brown <len.brown@intel.com>2006-12-15 23:38:34 -0500
commitc4168bff32e218b8400cb48b48adb9b7f7bb31b8 (patch)
tree48605aa258cf7acf108cb7c1a3419c4b7dc0e415
parentf883d9db008deb20d4969c26475100cec2b7f6f8 (diff)
ACPI: add acpi_bus_ops in acpi_device
Add acpi_bus_ops in acpi_device to support acpi hot plug. NOTE: Two methods .add and .start in acpi_driver.ops are called separately to probe ACPI devices, while only .probe method is called in driver model. As executing .add and .start separately is critical for ACPI device hot plug, we use acpi_bus_ops to distinguish different code path. Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/scan.c55
-rw-r--r--include/acpi/acpi_bus.h1
2 files changed, 29 insertions, 27 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 97f6bbd6ef3c..2a82645c9dfe 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -212,7 +212,8 @@ static int acpi_device_probe(struct device * dev)
212 212
213 ret = acpi_bus_driver_init(acpi_dev, acpi_drv); 213 ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
214 if (!ret) { 214 if (!ret) {
215 acpi_start_single_object(acpi_dev); 215 if (acpi_dev->bus_ops.acpi_op_start)
216 acpi_start_single_object(acpi_dev);
216 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 217 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
217 "Found driver [%s] for device [%s]\n", 218 "Found driver [%s] for device [%s]\n",
218 acpi_drv->name, acpi_dev->pnp.bus_id)); 219 acpi_drv->name, acpi_dev->pnp.bus_id));
@@ -305,7 +306,6 @@ static void acpi_device_unregister(struct acpi_device *device, int type)
305 list_del(&device->g_list); 306 list_del(&device->g_list);
306 307
307 list_del(&device->wakeup_list); 308 list_del(&device->wakeup_list);
308
309 spin_unlock(&acpi_device_lock); 309 spin_unlock(&acpi_device_lock);
310 310
311 acpi_detach_data(device->handle, acpi_bus_data_handler); 311 acpi_detach_data(device->handle, acpi_bus_data_handler);
@@ -876,7 +876,8 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice)
876 876
877static int 877static int
878acpi_add_single_object(struct acpi_device **child, 878acpi_add_single_object(struct acpi_device **child,
879 struct acpi_device *parent, acpi_handle handle, int type) 879 struct acpi_device *parent, acpi_handle handle, int type,
880 struct acpi_bus_ops *ops)
880{ 881{
881 int result = 0; 882 int result = 0;
882 struct acpi_device *device = NULL; 883 struct acpi_device *device = NULL;
@@ -894,6 +895,8 @@ acpi_add_single_object(struct acpi_device **child,
894 895
895 device->handle = handle; 896 device->handle = handle;
896 device->parent = parent; 897 device->parent = parent;
898 device->bus_ops = *ops; /* workround for not call .start */
899
897 900
898 acpi_device_get_busid(device, handle, type); 901 acpi_device_get_busid(device, handle, type);
899 902
@@ -1079,14 +1082,14 @@ static int acpi_bus_scan(struct acpi_device *start, struct acpi_bus_ops *ops)
1079 1082
1080 if (ops->acpi_op_add) 1083 if (ops->acpi_op_add)
1081 status = acpi_add_single_object(&child, parent, 1084 status = acpi_add_single_object(&child, parent,
1082 chandle, type); 1085 chandle, type, ops);
1083 else 1086 else
1084 status = acpi_bus_get_device(chandle, &child); 1087 status = acpi_bus_get_device(chandle, &child);
1085 1088
1086 if (ACPI_FAILURE(status)) 1089 if (ACPI_FAILURE(status))
1087 continue; 1090 continue;
1088 1091
1089 if (ops->acpi_op_start) { 1092 if (ops->acpi_op_start && !(ops->acpi_op_add)) {
1090 status = acpi_start_single_object(child); 1093 status = acpi_start_single_object(child);
1091 if (ACPI_FAILURE(status)) 1094 if (ACPI_FAILURE(status))
1092 continue; 1095 continue;
@@ -1124,13 +1127,13 @@ acpi_bus_add(struct acpi_device **child,
1124 int result; 1127 int result;
1125 struct acpi_bus_ops ops; 1128 struct acpi_bus_ops ops;
1126 1129
1130 memset(&ops, 0, sizeof(ops));
1131 ops.acpi_op_add = 1;
1127 1132
1128 result = acpi_add_single_object(child, parent, handle, type); 1133 result = acpi_add_single_object(child, parent, handle, type, &ops);
1129 if (!result) { 1134 if (!result)
1130 memset(&ops, 0, sizeof(ops));
1131 ops.acpi_op_add = 1;
1132 result = acpi_bus_scan(*child, &ops); 1135 result = acpi_bus_scan(*child, &ops);
1133 } 1136
1134 return result; 1137 return result;
1135} 1138}
1136 1139
@@ -1216,28 +1219,30 @@ static int acpi_bus_scan_fixed(struct acpi_device *root)
1216{ 1219{
1217 int result = 0; 1220 int result = 0;
1218 struct acpi_device *device = NULL; 1221 struct acpi_device *device = NULL;
1219 1222 struct acpi_bus_ops ops;
1220 1223
1221 if (!root) 1224 if (!root)
1222 return -ENODEV; 1225 return -ENODEV;
1223 1226
1227 memset(&ops, 0, sizeof(ops));
1228 ops.acpi_op_add = 1;
1229 ops.acpi_op_start = 1;
1230
1224 /* 1231 /*
1225 * Enumerate all fixed-feature devices. 1232 * Enumerate all fixed-feature devices.
1226 */ 1233 */
1227 if (acpi_fadt.pwr_button == 0) { 1234 if (acpi_fadt.pwr_button == 0) {
1228 result = acpi_add_single_object(&device, acpi_root, 1235 result = acpi_add_single_object(&device, acpi_root,
1229 NULL, 1236 NULL,
1230 ACPI_BUS_TYPE_POWER_BUTTON); 1237 ACPI_BUS_TYPE_POWER_BUTTON,
1231 if (!result) 1238 &ops);
1232 result = acpi_start_single_object(device);
1233 } 1239 }
1234 1240
1235 if (acpi_fadt.sleep_button == 0) { 1241 if (acpi_fadt.sleep_button == 0) {
1236 result = acpi_add_single_object(&device, acpi_root, 1242 result = acpi_add_single_object(&device, acpi_root,
1237 NULL, 1243 NULL,
1238 ACPI_BUS_TYPE_SLEEP_BUTTON); 1244 ACPI_BUS_TYPE_SLEEP_BUTTON,
1239 if (!result) 1245 &ops);
1240 result = acpi_start_single_object(device);
1241 } 1246 }
1242 1247
1243 return result; 1248 return result;
@@ -1252,6 +1257,10 @@ static int __init acpi_scan_init(void)
1252 if (acpi_disabled) 1257 if (acpi_disabled)
1253 return 0; 1258 return 0;
1254 1259
1260 memset(&ops, 0, sizeof(ops));
1261 ops.acpi_op_add = 1;
1262 ops.acpi_op_start = 1;
1263
1255 result = bus_register(&acpi_bus_type); 1264 result = bus_register(&acpi_bus_type);
1256 if (result) { 1265 if (result) {
1257 /* We don't want to quit even if we failed to add suspend/resume */ 1266 /* We don't want to quit even if we failed to add suspend/resume */
@@ -1262,11 +1271,7 @@ static int __init acpi_scan_init(void)
1262 * Create the root device in the bus's device tree 1271 * Create the root device in the bus's device tree
1263 */ 1272 */
1264 result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT, 1273 result = acpi_add_single_object(&acpi_root, NULL, ACPI_ROOT_OBJECT,
1265 ACPI_BUS_TYPE_SYSTEM); 1274 ACPI_BUS_TYPE_SYSTEM, &ops);
1266 if (result)
1267 goto Done;
1268
1269 result = acpi_start_single_object(acpi_root);
1270 if (result) 1275 if (result)
1271 goto Done; 1276 goto Done;
1272 1277
@@ -1274,12 +1279,8 @@ static int __init acpi_scan_init(void)
1274 * Enumerate devices in the ACPI namespace. 1279 * Enumerate devices in the ACPI namespace.
1275 */ 1280 */
1276 result = acpi_bus_scan_fixed(acpi_root); 1281 result = acpi_bus_scan_fixed(acpi_root);
1277 if (!result) { 1282 if (!result)
1278 memset(&ops, 0, sizeof(ops));
1279 ops.acpi_op_add = 1;
1280 ops.acpi_op_start = 1;
1281 result = acpi_bus_scan(acpi_root, &ops); 1283 result = acpi_bus_scan(acpi_root, &ops);
1282 }
1283 1284
1284 if (result) 1285 if (result)
1285 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL); 1286 acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 598fab352814..8976dbea63ca 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -300,6 +300,7 @@ struct acpi_device {
300 struct acpi_driver *driver; 300 struct acpi_driver *driver;
301 void *driver_data; 301 void *driver_data;
302 struct device dev; 302 struct device dev;
303 struct acpi_bus_ops bus_ops; /* workaround for different code path for hotplug */
303}; 304};
304 305
305#define acpi_driver_data(d) ((d)->driver_data) 306#define acpi_driver_data(d) ((d)->driver_data)