aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-30 08:27:29 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-01-30 08:27:29 -0500
commitca589f9469641916f4f9bd6a820012a27102ef63 (patch)
tree2bce51955303a0d33e2c52d37f0052ac19c1d445
parent8b4e2fa4ff72ba2c9f01af8def15d4c4eeeeed64 (diff)
ACPI / scan: Introduce struct acpi_scan_handler
Introduce struct acpi_scan_handler for representing objects that will do configuration tasks depending on ACPI device nodes' hardware IDs (HIDs). Currently, those tasks are done either directly by the ACPI namespace scanning code or by ACPI device drivers designed specifically for this purpose. None of the above is desirable, however, because doing that directly in the namespace scanning code makes that code overly complicated and difficult to follow and doing that in "special" device drivers leads to a great deal of confusion about their role and to confusing interactions with the driver core (for example, sysfs directories are created for those drivers, but they are completely unnecessary and only increase the kernel's memory footprint in vain). Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Yinghai Lu <yinghai@kernel.org> Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Acked-by: Toshi Kani <toshi.kani@hp.com>
-rw-r--r--Documentation/acpi/scan_handlers.txt77
-rw-r--r--drivers/acpi/scan.c60
-rw-r--r--include/acpi/acpi_bus.h14
3 files changed, 144 insertions, 7 deletions
diff --git a/Documentation/acpi/scan_handlers.txt b/Documentation/acpi/scan_handlers.txt
new file mode 100644
index 000000000000..3246ccf15992
--- /dev/null
+++ b/Documentation/acpi/scan_handlers.txt
@@ -0,0 +1,77 @@
1ACPI Scan Handlers
2
3Copyright (C) 2012, Intel Corporation
4Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
5
6During system initialization and ACPI-based device hot-add, the ACPI namespace
7is scanned in search of device objects that generally represent various pieces
8of hardware. This causes a struct acpi_device object to be created and
9registered with the driver core for every device object in the ACPI namespace
10and the hierarchy of those struct acpi_device objects reflects the namespace
11layout (i.e. parent device objects in the namespace are represented by parent
12struct acpi_device objects and analogously for their children). Those struct
13acpi_device objects are referred to as "device nodes" in what follows, but they
14should not be confused with struct device_node objects used by the Device Trees
15parsing code (although their role is analogous to the role of those objects).
16
17During ACPI-based device hot-remove device nodes representing pieces of hardware
18being removed are unregistered and deleted.
19
20The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
21initialization of device nodes, such as retrieving common configuration
22information from the device objects represented by them and populating them with
23appropriate data, but some of them require additional handling after they have
24been registered. For example, if the given device node represents a PCI host
25bridge, its registration should cause the PCI bus under that bridge to be
26enumerated and PCI devices on that bus to be registered with the driver core.
27Similarly, if the device node represents a PCI interrupt link, it is necessary
28to configure that link so that the kernel can use it.
29
30Those additional configuration tasks usually depend on the type of the hardware
31component represented by the given device node which can be determined on the
32basis of the device node's hardware ID (HID). They are performed by objects
33called ACPI scan handlers represented by the following structure:
34
35struct acpi_scan_handler {
36 const struct acpi_device_id *ids;
37 struct list_head list_node;
38 int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
39 void (*detach)(struct acpi_device *dev);
40};
41
42where ids is the list of IDs of device nodes the given handler is supposed to
43take care of, list_node is the hook to the global list of ACPI scan handlers
44maintained by the ACPI core and the .attach() and .detach() callbacks are
45executed, respectively, after registration of new device nodes and before
46unregistration of device nodes the handler attached to previously.
47
48The namespace scanning function, acpi_bus_scan(), first registers all of the
49device nodes in the given namespace scope with the driver core. Then, it tries
50to match a scan handler against each of them using the ids arrays of the
51available scan handlers. If a matching scan handler is found, its .attach()
52callback is executed for the given device node. If that callback returns 1,
53that means that the handler has claimed the device node and is now responsible
54for carrying out any additional configuration tasks related to it. It also will
55be responsible for preparing the device node for unregistration in that case.
56The device node's handler field is then populated with the address of the scan
57handler that has claimed it.
58
59If the .attach() callback returns 0, it means that the device node is not
60interesting to the given scan handler and may be matched against the next scan
61handler in the list. If it returns a (negative) error code, that means that
62the namespace scan should be terminated due to a serious error. The error code
63returned should then reflect the type of the error.
64
65The namespace trimming function, acpi_bus_trim(), first executes .detach()
66callbacks from the scan handlers of all device nodes in the given namespace
67scope (if they have scan handlers). Next, it unregisters all of the device
68nodes in that scope.
69
70ACPI scan handlers can be added to the list maintained by the ACPI core with the
71help of the acpi_scan_add_handler() function taking a pointer to the new scan
72handler as an argument. The order in which scan handlers are added to the list
73is the order in which they are matched against device nodes during namespace
74scans.
75
76All scan handles must be added to the list before acpi_bus_scan() is run for the
77first time and they cannot be removed from it.
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index fe9f2c926663..1453cd0672fb 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_platform_device_ids[] = {
53static LIST_HEAD(acpi_device_list); 53static LIST_HEAD(acpi_device_list);
54static LIST_HEAD(acpi_bus_id_list); 54static LIST_HEAD(acpi_bus_id_list);
55static DEFINE_MUTEX(acpi_scan_lock); 55static DEFINE_MUTEX(acpi_scan_lock);
56static LIST_HEAD(acpi_scan_handlers_list);
56DEFINE_MUTEX(acpi_device_lock); 57DEFINE_MUTEX(acpi_device_lock);
57LIST_HEAD(acpi_wakeup_device_list); 58LIST_HEAD(acpi_wakeup_device_list);
58 59
@@ -62,6 +63,15 @@ struct acpi_device_bus_id{
62 struct list_head node; 63 struct list_head node;
63}; 64};
64 65
66int acpi_scan_add_handler(struct acpi_scan_handler *handler)
67{
68 if (!handler || !handler->attach)
69 return -EINVAL;
70
71 list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
72 return 0;
73}
74
65/* 75/*
66 * Creates hid/cid(s) string needed for modalias and uevent 76 * Creates hid/cid(s) string needed for modalias and uevent
67 * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get: 77 * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
@@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl_not_used,
1570 return AE_OK; 1580 return AE_OK;
1571} 1581}
1572 1582
1583static int acpi_scan_attach_handler(struct acpi_device *device)
1584{
1585 struct acpi_scan_handler *handler;
1586 int ret = 0;
1587
1588 list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
1589 const struct acpi_device_id *id;
1590
1591 id = __acpi_match_device(device, handler->ids);
1592 if (!id)
1593 continue;
1594
1595 ret = handler->attach(device, id);
1596 if (ret > 0) {
1597 device->handler = handler;
1598 break;
1599 } else if (ret < 0) {
1600 break;
1601 }
1602 }
1603 return ret;
1604}
1605
1573static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used, 1606static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
1574 void *not_used, void **ret_not_used) 1607 void *not_used, void **ret_not_used)
1575{ 1608{
1576 const struct acpi_device_id *id; 1609 const struct acpi_device_id *id;
1577 acpi_status status = AE_OK;
1578 struct acpi_device *device; 1610 struct acpi_device *device;
1579 unsigned long long sta_not_used; 1611 unsigned long long sta_not_used;
1580 int type_not_used; 1612 int ret;
1581 1613
1582 /* 1614 /*
1583 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating 1615 * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
1584 * namespace walks prematurely. 1616 * namespace walks prematurely.
1585 */ 1617 */
1586 if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used)) 1618 if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
1587 return AE_OK; 1619 return AE_OK;
1588 1620
1589 if (acpi_bus_get_device(handle, &device)) 1621 if (acpi_bus_get_device(handle, &device))
@@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
1593 if (id) { 1625 if (id) {
1594 /* This is a known good platform device. */ 1626 /* This is a known good platform device. */
1595 acpi_create_platform_device(device, id->driver_data); 1627 acpi_create_platform_device(device, id->driver_data);
1596 } else if (device_attach(&device->dev) < 0) { 1628 return AE_OK;
1597 status = AE_CTRL_DEPTH;
1598 } 1629 }
1599 return status; 1630
1631 ret = acpi_scan_attach_handler(device);
1632 if (ret)
1633 return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
1634
1635 ret = device_attach(&device->dev);
1636 return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
1600} 1637}
1601 1638
1602/** 1639/**
@@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detach(acpi_handle handle, u32 lvl_not_used,
1639 struct acpi_device *device = NULL; 1676 struct acpi_device *device = NULL;
1640 1677
1641 if (!acpi_bus_get_device(handle, &device)) { 1678 if (!acpi_bus_get_device(handle, &device)) {
1679 struct acpi_scan_handler *dev_handler = device->handler;
1680
1642 device->removal_type = ACPI_BUS_REMOVAL_EJECT; 1681 device->removal_type = ACPI_BUS_REMOVAL_EJECT;
1643 device_release_driver(&device->dev); 1682 if (dev_handler) {
1683 if (dev_handler->detach)
1684 dev_handler->detach(device);
1685
1686 device->handler = NULL;
1687 } else {
1688 device_release_driver(&device->dev);
1689 }
1644 } 1690 }
1645 return AE_OK; 1691 return AE_OK;
1646} 1692}
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index ad0a86ac5cce..41850cb21730 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -84,6 +84,18 @@ struct acpi_driver;
84struct acpi_device; 84struct acpi_device;
85 85
86/* 86/*
87 * ACPI Scan Handler
88 * -----------------
89 */
90
91struct acpi_scan_handler {
92 const struct acpi_device_id *ids;
93 struct list_head list_node;
94 int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
95 void (*detach)(struct acpi_device *dev);
96};
97
98/*
87 * ACPI Driver 99 * ACPI Driver
88 * ----------- 100 * -----------
89 */ 101 */
@@ -269,6 +281,7 @@ struct acpi_device {
269 struct acpi_device_wakeup wakeup; 281 struct acpi_device_wakeup wakeup;
270 struct acpi_device_perf performance; 282 struct acpi_device_perf performance;
271 struct acpi_device_dir dir; 283 struct acpi_device_dir dir;
284 struct acpi_scan_handler *handler;
272 struct acpi_driver *driver; 285 struct acpi_driver *driver;
273 void *driver_data; 286 void *driver_data;
274 struct device dev; 287 struct device dev;
@@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_bus_event *event);
382static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) 395static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
383 { return 0; } 396 { return 0; }
384#endif 397#endif
398int acpi_scan_add_handler(struct acpi_scan_handler *handler);
385int acpi_bus_register_driver(struct acpi_driver *driver); 399int acpi_bus_register_driver(struct acpi_driver *driver);
386void acpi_bus_unregister_driver(struct acpi_driver *driver); 400void acpi_bus_unregister_driver(struct acpi_driver *driver);
387int acpi_bus_scan(acpi_handle handle); 401int acpi_bus_scan(acpi_handle handle);