aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/scan.c
diff options
context:
space:
mode:
authorPatrick Mochel <mochel@linux.intel.com>2006-12-07 07:56:27 -0500
committerLen Brown <len.brown@intel.com>2006-12-15 23:38:34 -0500
commit5d9464a46918ced087c351a10f38cee95725f85b (patch)
treeacb45582f9c43a867a60cc5fa8ae2c6197dc1d2d /drivers/acpi/scan.c
parentd43ec68e9837dfa6618ab473622683fdbf6e68a9 (diff)
ACPI: add ACPI bus_type for driver model
Add ACPI bus_type for Linux driver model. 1. .shutdown method is added into acpi_driver.ops needed by bus_type operations. 2. remove useless parameter 'int state' in .resume method. 3. change parameter 'int state' to 'pm_message_t state' in .suspend method. Note: The new .uevent method mark ACPI drivers by PNPID instead of by name. Udev script needs to look for "HWID=" or "COMPTID=" to load ACPI drivers as a result. Signed-off-by: Li Shaohua <shaohua.li@intel.com> Signed-off-by: Zhang Rui <rui.zhang@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/scan.c')
-rw-r--r--drivers/acpi/scan.c158
1 files changed, 91 insertions, 67 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 5b42948ea97f..464746257d8e 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -222,100 +222,124 @@ acpi_eject_store(struct acpi_device *device, const char *buf, size_t count)
222/* -------------------------------------------------------------------------- 222/* --------------------------------------------------------------------------
223 ACPI Bus operations 223 ACPI Bus operations
224 -------------------------------------------------------------------------- */ 224 -------------------------------------------------------------------------- */
225static int root_suspend(struct acpi_device * acpi_dev, pm_message_t state) 225static int acpi_device_suspend(struct device *dev, pm_message_t state)
226{ 226{
227 struct acpi_device * dev, * next; 227 struct acpi_device *acpi_dev = to_acpi_device(dev);
228 int result; 228 struct acpi_driver *acpi_drv = acpi_dev->driver;
229 229
230 spin_lock(&acpi_device_lock); 230 if (acpi_drv && acpi_drv->ops.suspend)
231 list_for_each_entry_safe_reverse(dev, next, &acpi_device_list, g_list) { 231 return acpi_drv->ops.suspend(acpi_dev, state);
232 if (dev->driver && dev->driver->ops.suspend) {
233 spin_unlock(&acpi_device_lock);
234 result = dev->driver->ops.suspend(dev, 0);
235 if (result) {
236 printk(KERN_ERR PREFIX "[%s - %s] Suspend failed: %d\n",
237 acpi_device_name(dev),
238 acpi_device_bid(dev), result);
239 }
240 spin_lock(&acpi_device_lock);
241 }
242 }
243 spin_unlock(&acpi_device_lock);
244 return 0; 232 return 0;
245} 233}
246 234
247static int acpi_device_suspend(struct device * dev, pm_message_t state) 235static int acpi_device_resume(struct device *dev)
248{ 236{
249 struct acpi_device * acpi_dev = to_acpi_device(dev); 237 struct acpi_device *acpi_dev = to_acpi_device(dev);
238 struct acpi_driver *acpi_drv = acpi_dev->driver;
250 239
251 /* 240 if (acpi_drv && acpi_drv->ops.resume)
252 * For now, we should only register 1 generic device - 241 return acpi_drv->ops.resume(acpi_dev);
253 * the ACPI root device - and from there, we walk the
254 * tree of ACPI devices to suspend each one using the
255 * ACPI driver methods.
256 */
257 if (acpi_dev->handle == ACPI_ROOT_OBJECT)
258 root_suspend(acpi_dev, state);
259 return 0; 242 return 0;
260} 243}
261 244
262static int root_resume(struct acpi_device * acpi_dev) 245static int acpi_bus_match(struct device *dev, struct device_driver *drv)
263{ 246{
264 struct acpi_device * dev, * next; 247 struct acpi_device *acpi_dev = to_acpi_device(dev);
265 int result; 248 struct acpi_driver *acpi_drv = to_acpi_driver(drv);
266 249
267 spin_lock(&acpi_device_lock); 250 if (acpi_drv->ops.match)
268 list_for_each_entry_safe(dev, next, &acpi_device_list, g_list) { 251 return !acpi_drv->ops.match(acpi_dev, acpi_drv);
269 if (dev->driver && dev->driver->ops.resume) { 252 return !acpi_match_ids(acpi_dev, acpi_drv->ids);
270 spin_unlock(&acpi_device_lock); 253}
271 result = dev->driver->ops.resume(dev, 0); 254
272 if (result) { 255static int acpi_device_uevent(struct device *dev, char **envp, int num_envp,
273 printk(KERN_ERR PREFIX "[%s - %s] resume failed: %d\n", 256 char *buffer, int buffer_size)
274 acpi_device_name(dev), 257{
275 acpi_device_bid(dev), result); 258 struct acpi_device *acpi_dev = to_acpi_device(dev);
276 } 259 int i = 0, length = 0, ret = 0;
277 spin_lock(&acpi_device_lock); 260
261 if (acpi_dev->flags.hardware_id)
262 ret = add_uevent_var(envp, num_envp, &i,
263 buffer, buffer_size, &length,
264 "HWID=%s", acpi_dev->pnp.hardware_id);
265 if (ret)
266 return -ENOMEM;
267 if (acpi_dev->flags.compatible_ids) {
268 int j;
269 struct acpi_compatible_id_list *cid_list;
270
271 cid_list = acpi_dev->pnp.cid_list;
272
273 for (j = 0; j < cid_list->count; j++) {
274 ret = add_uevent_var(envp, num_envp, &i, buffer,
275 buffer_size, &length, "COMPTID=%s",
276 cid_list->id[j].value);
277 if (ret)
278 return -ENOMEM;
278 } 279 }
279 } 280 }
280 spin_unlock(&acpi_device_lock); 281
282 envp[i] = NULL;
281 return 0; 283 return 0;
282} 284}
283 285
284static int acpi_device_resume(struct device * dev) 286static int acpi_bus_driver_init(struct acpi_device *, struct acpi_driver *);
287static int acpi_start_single_object(struct acpi_device *);
288static int acpi_device_probe(struct device * dev)
285{ 289{
286 struct acpi_device * acpi_dev = to_acpi_device(dev); 290 struct acpi_device *acpi_dev = to_acpi_device(dev);
291 struct acpi_driver *acpi_drv = to_acpi_driver(dev->driver);
292 int ret;
293
294 ret = acpi_bus_driver_init(acpi_dev, acpi_drv);
295 if (!ret) {
296 acpi_start_single_object(acpi_dev);
297 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
298 "Found driver [%s] for device [%s]\n",
299 acpi_drv->name, acpi_dev->pnp.bus_id));
300 get_device(dev);
301 }
302 return ret;
303}
287 304
288 /* 305static int acpi_device_remove(struct device * dev)
289 * For now, we should only register 1 generic device - 306{
290 * the ACPI root device - and from there, we walk the 307 struct acpi_device *acpi_dev = to_acpi_device(dev);
291 * tree of ACPI devices to resume each one using the 308 struct acpi_driver *acpi_drv = acpi_dev->driver;
292 * ACPI driver methods. 309
293 */ 310 if (acpi_drv) {
294 if (acpi_dev->handle == ACPI_ROOT_OBJECT) 311 if (acpi_drv->ops.stop)
295 root_resume(acpi_dev); 312 acpi_drv->ops.stop(acpi_dev, ACPI_BUS_REMOVAL_NORMAL);
313 if (acpi_drv->ops.remove)
314 acpi_drv->ops.remove(acpi_dev, ACPI_BUS_REMOVAL_NORMAL);
315 }
316 acpi_dev->driver = NULL;
317 acpi_driver_data(dev) = NULL;
318
319 put_device(dev);
296 return 0; 320 return 0;
297} 321}
298 322
299/** 323static void acpi_device_shutdown(struct device *dev)
300 * acpi_bus_match - match device IDs to driver's supported IDs
301 * @device: the device that we are trying to match to a driver
302 * @driver: driver whose device id table is being checked
303 *
304 * Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
305 * matches the specified driver's criteria.
306 */
307static int
308acpi_bus_match(struct acpi_device *device, struct acpi_driver *driver)
309{ 324{
310 if (driver && driver->ops.match) 325 struct acpi_device *acpi_dev = to_acpi_device(dev);
311 return driver->ops.match(device, driver); 326 struct acpi_driver *acpi_drv = acpi_dev->driver;
312 return acpi_match_ids(device, driver->ids); 327
328 if (acpi_drv && acpi_drv->ops.shutdown)
329 acpi_drv->ops.shutdown(acpi_dev);
330
331 return ;
313} 332}
314 333
315static struct bus_type acpi_bus_type = { 334static struct bus_type acpi_bus_type = {
316 .name = "acpi", 335 .name = "acpi",
317 .suspend = acpi_device_suspend, 336 .suspend = acpi_device_suspend,
318 .resume = acpi_device_resume, 337 .resume = acpi_device_resume,
338 .shutdown = acpi_device_shutdown,
339 .match = acpi_bus_match,
340 .probe = acpi_device_probe,
341 .remove = acpi_device_remove,
342 .uevent = acpi_device_uevent,
319}; 343};
320 344
321static void acpi_device_register(struct acpi_device *device, 345static void acpi_device_register(struct acpi_device *device,
@@ -449,7 +473,7 @@ static void acpi_driver_attach(struct acpi_driver *drv)
449 continue; 473 continue;
450 spin_unlock(&acpi_device_lock); 474 spin_unlock(&acpi_device_lock);
451 475
452 if (!acpi_bus_match(dev, drv)) { 476 if (!acpi_bus_match(&(dev->dev), &(drv->drv))) {
453 if (!acpi_bus_driver_init(dev, drv)) { 477 if (!acpi_bus_driver_init(dev, drv)) {
454 acpi_start_single_object(dev); 478 acpi_start_single_object(dev);
455 atomic_inc(&drv->references); 479 atomic_inc(&drv->references);
@@ -551,7 +575,7 @@ static int acpi_bus_find_driver(struct acpi_device *device)
551 575
552 atomic_inc(&driver->references); 576 atomic_inc(&driver->references);
553 spin_unlock(&acpi_device_lock); 577 spin_unlock(&acpi_device_lock);
554 if (!acpi_bus_match(device, driver)) { 578 if (!acpi_bus_match(&(device->dev), &(driver->drv))) {
555 result = acpi_bus_driver_init(device, driver); 579 result = acpi_bus_driver_init(device, driver);
556 if (!result) 580 if (!result)
557 goto Done; 581 goto Done;