* [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
@ 2013-01-28 12:59 ` Rafael J. Wysocki
2013-01-29 2:04 ` Yasuaki Ishimatsu
2013-01-29 2:35 ` Toshi Kani
2013-01-28 13:00 ` [PATCH 2/4] ACPI / PCI: Make PCI root driver use struct acpi_scan_handler Rafael J. Wysocki
` (6 subsequent siblings)
7 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 12:59 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
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>
---
Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
include/acpi/acpi_bus.h | 14 ++++++
3 files changed, 144 insertions(+), 7 deletions(-)
Index: test/include/acpi/acpi_bus.h
===================================================================
--- test.orig/include/acpi/acpi_bus.h
+++ test/include/acpi/acpi_bus.h
@@ -84,6 +84,18 @@ struct acpi_driver;
struct acpi_device;
/*
+ * ACPI Scan Handler
+ * -----------------
+ */
+
+struct acpi_scan_handler {
+ const struct acpi_device_id *ids;
+ struct list_head list_node;
+ int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
+ void (*detach)(struct acpi_device *dev);
+};
+
+/*
* ACPI Driver
* -----------
*/
@@ -269,6 +281,7 @@ struct acpi_device {
struct acpi_device_wakeup wakeup;
struct acpi_device_perf performance;
struct acpi_device_dir dir;
+ struct acpi_scan_handler *handler;
struct acpi_driver *driver;
void *driver_data;
struct device dev;
@@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
{ return 0; }
#endif
+int acpi_scan_add_handler(struct acpi_scan_handler *handler);
int acpi_bus_register_driver(struct acpi_driver *driver);
void acpi_bus_unregister_driver(struct acpi_driver *driver);
int acpi_bus_scan(acpi_handle handle);
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
static DEFINE_MUTEX(acpi_scan_lock);
+static LIST_HEAD(acpi_scan_handlers_list);
DEFINE_MUTEX(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
@@ -62,6 +63,15 @@ struct acpi_device_bus_id{
struct list_head node;
};
+int acpi_scan_add_handler(struct acpi_scan_handler *handler)
+{
+ if (!handler || !handler->attach)
+ return -EINVAL;
+
+ list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
+ return 0;
+}
+
/*
* Creates hid/cid(s) string needed for modalias and uevent
* e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
@@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
return AE_OK;
}
+static int acpi_scan_attach_handler(struct acpi_device *device)
+{
+ struct acpi_scan_handler *handler;
+ int ret = 0;
+
+ list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
+ const struct acpi_device_id *id;
+
+ id = __acpi_match_device(device, handler->ids);
+ if (!id)
+ continue;
+
+ ret = handler->attach(device, id);
+ if (ret > 0) {
+ device->handler = handler;
+ break;
+ } else if (ret < 0) {
+ break;
+ }
+ }
+ return ret;
+}
+
static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
void *not_used, void **ret_not_used)
{
const struct acpi_device_id *id;
- acpi_status status = AE_OK;
struct acpi_device *device;
unsigned long long sta_not_used;
- int type_not_used;
+ int ret;
/*
* Ignore errors ignored by acpi_bus_check_add() to avoid terminating
* namespace walks prematurely.
*/
- if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
+ if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
return AE_OK;
if (acpi_bus_get_device(handle, &device))
@@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
if (id) {
/* This is a known good platform device. */
acpi_create_platform_device(device, id->driver_data);
- } else if (device_attach(&device->dev) < 0) {
- status = AE_CTRL_DEPTH;
+ return AE_OK;
}
- return status;
+
+ ret = acpi_scan_attach_handler(device);
+ if (ret)
+ return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
+
+ ret = device_attach(&device->dev);
+ return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
}
/**
@@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
struct acpi_device *device = NULL;
if (!acpi_bus_get_device(handle, &device)) {
+ struct acpi_scan_handler *dev_handler = device->handler;
+
device->removal_type = ACPI_BUS_REMOVAL_EJECT;
- device_release_driver(&device->dev);
+ if (dev_handler) {
+ if (dev_handler->detach)
+ dev_handler->detach(device);
+
+ device->handler = NULL;
+ } else {
+ device_release_driver(&device->dev);
+ }
}
return AE_OK;
}
Index: test/Documentation/acpi/scan_handlers.txt
===================================================================
--- /dev/null
+++ test/Documentation/acpi/scan_handlers.txt
@@ -0,0 +1,77 @@
+ACPI Scan Handlers
+
+Copyright (C) 2012, Intel Corporation
+Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+During system initialization and ACPI-based device hot-add, the ACPI namespace
+is scanned in search of device objects that generally represent various pieces
+of hardware. This causes a struct acpi_device object to be created and
+registered with the driver core for every device object in the ACPI namespace
+and the hierarchy of those struct acpi_device objects reflects the namespace
+layout (i.e. parent device objects in the namespace are represented by parent
+struct acpi_device objects and analogously for their children). Those struct
+acpi_device objects are referred to as "device nodes" in what follows, but they
+should not be confused with struct device_node objects used by the Device Trees
+parsing code (although their role is analogous to the role of those objects).
+
+During ACPI-based device hot-remove device nodes representing pieces of hardware
+being removed are unregistered and deleted.
+
+The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
+initialization of device nodes, such as retrieving common configuration
+information from the device objects represented by them and populating them with
+appropriate data, but some of them require additional handling after they have
+been registered. For example, if the given device node represents a PCI host
+bridge, its registration should cause the PCI bus under that bridge to be
+enumerated and PCI devices on that bus to be registered with the driver core.
+Similarly, if the device node represents a PCI interrupt link, it is necessary
+to configure that link so that the kernel can use it.
+
+Those additional configuration tasks usually depend on the type of the hardware
+component represented by the given device node which can be determined on the
+basis of the device node's hardware ID (HID). They are performed by objects
+called ACPI scan handlers represented by the following structure:
+
+struct acpi_scan_handler {
+ const struct acpi_device_id *ids;
+ struct list_head list_node;
+ int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
+ void (*detach)(struct acpi_device *dev);
+};
+
+where ids is the list of IDs of device nodes the given handler is supposed to
+take care of, list_node is the hook to the global list of ACPI scan handlers
+maintained by the ACPI core and the .attach() and .detach() callbacks are
+executed, respectively, after registration of new device nodes and before
+unregistration of device nodes the handler attached to previously.
+
+The namespace scanning function, acpi_bus_scan(), first registers all of the
+device nodes in the given namespace scope with the driver core. Then, it tries
+to match a scan handler against each of them using the ids arrays of the
+available scan handlers. If a matching scan handler is found, its .attach()
+callback is executed for the given device node. If that callback returns 1,
+that means that the handler has claimed the device node and is now responsible
+for carrying out any additional configuration tasks related to it. It also will
+be responsible for preparing the device node for unregistration in that case.
+The device node's handler field is then populated with the address of the scan
+handler that has claimed it.
+
+If the .attach() callback returns 0, it means that the device node is not
+interesting to the given scan handler and may be matched against the next scan
+handler in the list. If it returns a (negative) error code, that means that
+the namespace scan should be terminated due to a serious error. The error code
+returned should then reflect the type of the error.
+
+The namespace trimming function, acpi_bus_trim(), first executes .detach()
+callbacks from the scan handlers of all device nodes in the given namespace
+scope (if they have scan handlers). Next, it unregisters all of the device
+nodes in that scope.
+
+ACPI scan handlers can be added to the list maintained by the ACPI core with the
+help of the acpi_scan_add_handler() function taking a pointer to the new scan
+handler as an argument. The order in which scan handlers are added to the list
+is the order in which they are matched against device nodes during namespace
+scans.
+
+All scan handles must be added to the list before acpi_bus_scan() is run for the
+first time and they cannot be removed from it.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-28 12:59 ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
@ 2013-01-29 2:04 ` Yasuaki Ishimatsu
2013-01-29 2:29 ` Yasuaki Ishimatsu
2013-01-29 2:35 ` Toshi Kani
1 sibling, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29 2:04 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
Hi Rafael,
2013/01/28 21:59, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> 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: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
I have a comment. Please see below.
> Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> include/acpi/acpi_bus.h | 14 ++++++
> 3 files changed, 144 insertions(+), 7 deletions(-)
>
> Index: test/include/acpi/acpi_bus.h
> ===================================================================
> --- test.orig/include/acpi/acpi_bus.h
> +++ test/include/acpi/acpi_bus.h
> @@ -84,6 +84,18 @@ struct acpi_driver;
> struct acpi_device;
>
> /*
> + * ACPI Scan Handler
> + * -----------------
> + */
> +
> +struct acpi_scan_handler {
> + const struct acpi_device_id *ids;
> + struct list_head list_node;
> + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> + void (*detach)(struct acpi_device *dev);
> +};
> +
> +/*
> * ACPI Driver
> * -----------
> */
> @@ -269,6 +281,7 @@ struct acpi_device {
> struct acpi_device_wakeup wakeup;
> struct acpi_device_perf performance;
> struct acpi_device_dir dir;
> + struct acpi_scan_handler *handler;
> struct acpi_driver *driver;
> void *driver_data;
> struct device dev;
> @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> { return 0; }
> #endif
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> int acpi_bus_register_driver(struct acpi_driver *driver);
> void acpi_bus_unregister_driver(struct acpi_driver *driver);
> int acpi_bus_scan(acpi_handle handle);
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> static LIST_HEAD(acpi_device_list);
> static LIST_HEAD(acpi_bus_id_list);
> static DEFINE_MUTEX(acpi_scan_lock);
> +static LIST_HEAD(acpi_scan_handlers_list);
> DEFINE_MUTEX(acpi_device_lock);
> LIST_HEAD(acpi_wakeup_device_list);
>
> @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> struct list_head node;
> };
>
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> +{
> + if (!handler || !handler->attach)
> + return -EINVAL;
> +
> + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> + return 0;
> +}
> +
> /*
> * Creates hid/cid(s) string needed for modalias and uevent
> * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> return AE_OK;
> }
>
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> + struct acpi_scan_handler *handler;
> + int ret = 0;
> +
> + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> + const struct acpi_device_id *id;
> +
> + id = __acpi_match_device(device, handler->ids);
> + if (!id)
> + continue;
> +
> + ret = handler->attach(device, id);
> + if (ret > 0) {
> + device->handler = handler;
> + break;
> + } else if (ret < 0) {
> + break;
> + }
> + }
> + return ret;
> +}
> +
> static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
> void *not_used, void **ret_not_used)
> {
> const struct acpi_device_id *id;
> - acpi_status status = AE_OK;
> struct acpi_device *device;
> unsigned long long sta_not_used;
> - int type_not_used;
> + int ret;
>
> /*
> * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
> * namespace walks prematurely.
> */
> - if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> + if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
> return AE_OK;
>
> if (acpi_bus_get_device(handle, &device))
> @@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
> if (id) {
> /* This is a known good platform device. */
> acpi_create_platform_device(device, id->driver_data);
> - } else if (device_attach(&device->dev) < 0) {
> - status = AE_CTRL_DEPTH;
> + return AE_OK;
> }
> - return status;
> +
> + ret = acpi_scan_attach_handler(device);
> + if (ret)
> + return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
acpi_scan_attach_hanlder() returns only 0 or -EINVAL.
How about just return AE_CTRL_DEPTH?
Thanks,
Yasuaki Ishimatsu
> +
> + ret = device_attach(&device->dev);
> + return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
> }
>
> /**
> @@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
> struct acpi_device *device = NULL;
>
> if (!acpi_bus_get_device(handle, &device)) {
> + struct acpi_scan_handler *dev_handler = device->handler;
> +
> device->removal_type = ACPI_BUS_REMOVAL_EJECT;
> - device_release_driver(&device->dev);
> + if (dev_handler) {
> + if (dev_handler->detach)
> + dev_handler->detach(device);
> +
> + device->handler = NULL;
> + } else {
> + device_release_driver(&device->dev);
> + }
> }
> return AE_OK;
> }
> Index: test/Documentation/acpi/scan_handlers.txt
> ===================================================================
> --- /dev/null
> +++ test/Documentation/acpi/scan_handlers.txt
> @@ -0,0 +1,77 @@
> +ACPI Scan Handlers
> +
> +Copyright (C) 2012, Intel Corporation
> +Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> +
> +During system initialization and ACPI-based device hot-add, the ACPI namespace
> +is scanned in search of device objects that generally represent various pieces
> +of hardware. This causes a struct acpi_device object to be created and
> +registered with the driver core for every device object in the ACPI namespace
> +and the hierarchy of those struct acpi_device objects reflects the namespace
> +layout (i.e. parent device objects in the namespace are represented by parent
> +struct acpi_device objects and analogously for their children). Those struct
> +acpi_device objects are referred to as "device nodes" in what follows, but they
> +should not be confused with struct device_node objects used by the Device Trees
> +parsing code (although their role is analogous to the role of those objects).
> +
> +During ACPI-based device hot-remove device nodes representing pieces of hardware
> +being removed are unregistered and deleted.
> +
> +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
> +initialization of device nodes, such as retrieving common configuration
> +information from the device objects represented by them and populating them with
> +appropriate data, but some of them require additional handling after they have
> +been registered. For example, if the given device node represents a PCI host
> +bridge, its registration should cause the PCI bus under that bridge to be
> +enumerated and PCI devices on that bus to be registered with the driver core.
> +Similarly, if the device node represents a PCI interrupt link, it is necessary
> +to configure that link so that the kernel can use it.
> +
> +Those additional configuration tasks usually depend on the type of the hardware
> +component represented by the given device node which can be determined on the
> +basis of the device node's hardware ID (HID). They are performed by objects
> +called ACPI scan handlers represented by the following structure:
> +
> +struct acpi_scan_handler {
> + const struct acpi_device_id *ids;
> + struct list_head list_node;
> + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> + void (*detach)(struct acpi_device *dev);
> +};
> +
> +where ids is the list of IDs of device nodes the given handler is supposed to
> +take care of, list_node is the hook to the global list of ACPI scan handlers
> +maintained by the ACPI core and the .attach() and .detach() callbacks are
> +executed, respectively, after registration of new device nodes and before
> +unregistration of device nodes the handler attached to previously.
> +
> +The namespace scanning function, acpi_bus_scan(), first registers all of the
> +device nodes in the given namespace scope with the driver core. Then, it tries
> +to match a scan handler against each of them using the ids arrays of the
> +available scan handlers. If a matching scan handler is found, its .attach()
> +callback is executed for the given device node. If that callback returns 1,
> +that means that the handler has claimed the device node and is now responsible
> +for carrying out any additional configuration tasks related to it. It also will
> +be responsible for preparing the device node for unregistration in that case.
> +The device node's handler field is then populated with the address of the scan
> +handler that has claimed it.
> +
> +If the .attach() callback returns 0, it means that the device node is not
> +interesting to the given scan handler and may be matched against the next scan
> +handler in the list. If it returns a (negative) error code, that means that
> +the namespace scan should be terminated due to a serious error. The error code
> +returned should then reflect the type of the error.
> +
> +The namespace trimming function, acpi_bus_trim(), first executes .detach()
> +callbacks from the scan handlers of all device nodes in the given namespace
> +scope (if they have scan handlers). Next, it unregisters all of the device
> +nodes in that scope.
> +
> +ACPI scan handlers can be added to the list maintained by the ACPI core with the
> +help of the acpi_scan_add_handler() function taking a pointer to the new scan
> +handler as an argument. The order in which scan handlers are added to the list
> +is the order in which they are matched against device nodes during namespace
> +scans.
> +
> +All scan handles must be added to the list before acpi_bus_scan() is run for the
> +first time and they cannot be removed from it.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 2:04 ` Yasuaki Ishimatsu
@ 2013-01-29 2:29 ` Yasuaki Ishimatsu
0 siblings, 0 replies; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29 2:29 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
2013/01/29 11:04, Yasuaki Ishimatsu wrote:
> Hi Rafael,
>
> 2013/01/28 21:59, Rafael J. Wysocki wrote:
>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>
>> 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: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
>
> I have a comment. Please see below.
>
>> Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
>> drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
>> include/acpi/acpi_bus.h | 14 ++++++
>> 3 files changed, 144 insertions(+), 7 deletions(-)
>>
>> Index: test/include/acpi/acpi_bus.h
>> ===================================================================
>> --- test.orig/include/acpi/acpi_bus.h
>> +++ test/include/acpi/acpi_bus.h
>> @@ -84,6 +84,18 @@ struct acpi_driver;
>> struct acpi_device;
>>
>> /*
>> + * ACPI Scan Handler
>> + * -----------------
>> + */
>> +
>> +struct acpi_scan_handler {
>> + const struct acpi_device_id *ids;
>> + struct list_head list_node;
>> + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
>> + void (*detach)(struct acpi_device *dev);
>> +};
>> +
>> +/*
>> * ACPI Driver
>> * -----------
>> */
>> @@ -269,6 +281,7 @@ struct acpi_device {
>> struct acpi_device_wakeup wakeup;
>> struct acpi_device_perf performance;
>> struct acpi_device_dir dir;
>> + struct acpi_scan_handler *handler;
>> struct acpi_driver *driver;
>> void *driver_data;
>> struct device dev;
>> @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
>> static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
>> { return 0; }
>> #endif
>> +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
>> int acpi_bus_register_driver(struct acpi_driver *driver);
>> void acpi_bus_unregister_driver(struct acpi_driver *driver);
>> int acpi_bus_scan(acpi_handle handle);
>> Index: test/drivers/acpi/scan.c
>> ===================================================================
>> --- test.orig/drivers/acpi/scan.c
>> +++ test/drivers/acpi/scan.c
>> @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
>> static LIST_HEAD(acpi_device_list);
>> static LIST_HEAD(acpi_bus_id_list);
>> static DEFINE_MUTEX(acpi_scan_lock);
>> +static LIST_HEAD(acpi_scan_handlers_list);
>> DEFINE_MUTEX(acpi_device_lock);
>> LIST_HEAD(acpi_wakeup_device_list);
>>
>> @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
>> struct list_head node;
>> };
>>
>> +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
>> +{
>> + if (!handler || !handler->attach)
>> + return -EINVAL;
>> +
>> + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
>> + return 0;
>> +}
>> +
>> /*
>> * Creates hid/cid(s) string needed for modalias and uevent
>> * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
>> @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
>> return AE_OK;
>> }
>>
>> +static int acpi_scan_attach_handler(struct acpi_device *device)
>> +{
>> + struct acpi_scan_handler *handler;
>> + int ret = 0;
>> +
>> + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
>> + const struct acpi_device_id *id;
>> +
>> + id = __acpi_match_device(device, handler->ids);
>> + if (!id)
>> + continue;
>> +
>> + ret = handler->attach(device, id);
>> + if (ret > 0) {
>> + device->handler = handler;
>> + break;
>> + } else if (ret < 0) {
>> + break;
>> + }
>> + }
>> + return ret;
>> +}
>> +
>> static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
>> void *not_used, void **ret_not_used)
>> {
>> const struct acpi_device_id *id;
>> - acpi_status status = AE_OK;
>> struct acpi_device *device;
>> unsigned long long sta_not_used;
>> - int type_not_used;
>> + int ret;
>>
>> /*
>> * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
>> * namespace walks prematurely.
>> */
>> - if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
>> + if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
>> return AE_OK;
>>
>> if (acpi_bus_get_device(handle, &device))
>> @@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
>> if (id) {
>> /* This is a known good platform device. */
>> acpi_create_platform_device(device, id->driver_data);
>> - } else if (device_attach(&device->dev) < 0) {
>> - status = AE_CTRL_DEPTH;
>> + return AE_OK;
>> }
>> - return status;
>> +
>
>> + ret = acpi_scan_attach_handler(device);
>> + if (ret)
>> + return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
>
> acpi_scan_attach_hanlder() returns only 0 or -EINVAL.
> How about just return AE_CTRL_DEPTH?
I am wrong. Please forget it.
Thanks,
Yasuaki Ishimatsu
>
> Thanks,
> Yasuaki Ishimatsu
>
>> +
>> + ret = device_attach(&device->dev);
>> + return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
>> }
>>
>> /**
>> @@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
>> struct acpi_device *device = NULL;
>>
>> if (!acpi_bus_get_device(handle, &device)) {
>> + struct acpi_scan_handler *dev_handler = device->handler;
>> +
>> device->removal_type = ACPI_BUS_REMOVAL_EJECT;
>> - device_release_driver(&device->dev);
>> + if (dev_handler) {
>> + if (dev_handler->detach)
>> + dev_handler->detach(device);
>> +
>> + device->handler = NULL;
>> + } else {
>> + device_release_driver(&device->dev);
>> + }
>> }
>> return AE_OK;
>> }
>> Index: test/Documentation/acpi/scan_handlers.txt
>> ===================================================================
>> --- /dev/null
>> +++ test/Documentation/acpi/scan_handlers.txt
>> @@ -0,0 +1,77 @@
>> +ACPI Scan Handlers
>> +
>> +Copyright (C) 2012, Intel Corporation
>> +Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> +
>> +During system initialization and ACPI-based device hot-add, the ACPI namespace
>> +is scanned in search of device objects that generally represent various pieces
>> +of hardware. This causes a struct acpi_device object to be created and
>> +registered with the driver core for every device object in the ACPI namespace
>> +and the hierarchy of those struct acpi_device objects reflects the namespace
>> +layout (i.e. parent device objects in the namespace are represented by parent
>> +struct acpi_device objects and analogously for their children). Those struct
>> +acpi_device objects are referred to as "device nodes" in what follows, but they
>> +should not be confused with struct device_node objects used by the Device Trees
>> +parsing code (although their role is analogous to the role of those objects).
>> +
>> +During ACPI-based device hot-remove device nodes representing pieces of hardware
>> +being removed are unregistered and deleted.
>> +
>> +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
>> +initialization of device nodes, such as retrieving common configuration
>> +information from the device objects represented by them and populating them with
>> +appropriate data, but some of them require additional handling after they have
>> +been registered. For example, if the given device node represents a PCI host
>> +bridge, its registration should cause the PCI bus under that bridge to be
>> +enumerated and PCI devices on that bus to be registered with the driver core.
>> +Similarly, if the device node represents a PCI interrupt link, it is necessary
>> +to configure that link so that the kernel can use it.
>> +
>> +Those additional configuration tasks usually depend on the type of the hardware
>> +component represented by the given device node which can be determined on the
>> +basis of the device node's hardware ID (HID). They are performed by objects
>> +called ACPI scan handlers represented by the following structure:
>> +
>> +struct acpi_scan_handler {
>> + const struct acpi_device_id *ids;
>> + struct list_head list_node;
>> + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
>> + void (*detach)(struct acpi_device *dev);
>> +};
>> +
>> +where ids is the list of IDs of device nodes the given handler is supposed to
>> +take care of, list_node is the hook to the global list of ACPI scan handlers
>> +maintained by the ACPI core and the .attach() and .detach() callbacks are
>> +executed, respectively, after registration of new device nodes and before
>> +unregistration of device nodes the handler attached to previously.
>> +
>> +The namespace scanning function, acpi_bus_scan(), first registers all of the
>> +device nodes in the given namespace scope with the driver core. Then, it tries
>> +to match a scan handler against each of them using the ids arrays of the
>> +available scan handlers. If a matching scan handler is found, its .attach()
>> +callback is executed for the given device node. If that callback returns 1,
>> +that means that the handler has claimed the device node and is now responsible
>> +for carrying out any additional configuration tasks related to it. It also will
>> +be responsible for preparing the device node for unregistration in that case.
>> +The device node's handler field is then populated with the address of the scan
>> +handler that has claimed it.
>> +
>> +If the .attach() callback returns 0, it means that the device node is not
>> +interesting to the given scan handler and may be matched against the next scan
>> +handler in the list. If it returns a (negative) error code, that means that
>> +the namespace scan should be terminated due to a serious error. The error code
>> +returned should then reflect the type of the error.
>> +
>> +The namespace trimming function, acpi_bus_trim(), first executes .detach()
>> +callbacks from the scan handlers of all device nodes in the given namespace
>> +scope (if they have scan handlers). Next, it unregisters all of the device
>> +nodes in that scope.
>> +
>> +ACPI scan handlers can be added to the list maintained by the ACPI core with the
>> +help of the acpi_scan_add_handler() function taking a pointer to the new scan
>> +handler as an argument. The order in which scan handlers are added to the list
>> +is the order in which they are matched against device nodes during namespace
>> +scans.
>> +
>> +All scan handles must be added to the list before acpi_bus_scan() is run for the
>> +first time and they cannot be removed from it.
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-28 12:59 ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
2013-01-29 2:04 ` Yasuaki Ishimatsu
@ 2013-01-29 2:35 ` Toshi Kani
2013-01-29 11:28 ` Rafael J. Wysocki
1 sibling, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 2:35 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> 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>
> ---
> Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> include/acpi/acpi_bus.h | 14 ++++++
> 3 files changed, 144 insertions(+), 7 deletions(-)
>
> Index: test/include/acpi/acpi_bus.h
> ===================================================================
> --- test.orig/include/acpi/acpi_bus.h
> +++ test/include/acpi/acpi_bus.h
> @@ -84,6 +84,18 @@ struct acpi_driver;
> struct acpi_device;
>
> /*
> + * ACPI Scan Handler
> + * -----------------
> + */
> +
> +struct acpi_scan_handler {
> + const struct acpi_device_id *ids;
> + struct list_head list_node;
> + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> + void (*detach)(struct acpi_device *dev);
> +};
> +
> +/*
> * ACPI Driver
> * -----------
> */
> @@ -269,6 +281,7 @@ struct acpi_device {
> struct acpi_device_wakeup wakeup;
> struct acpi_device_perf performance;
> struct acpi_device_dir dir;
> + struct acpi_scan_handler *handler;
> struct acpi_driver *driver;
> void *driver_data;
> struct device dev;
> @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> { return 0; }
> #endif
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> int acpi_bus_register_driver(struct acpi_driver *driver);
> void acpi_bus_unregister_driver(struct acpi_driver *driver);
> int acpi_bus_scan(acpi_handle handle);
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> static LIST_HEAD(acpi_device_list);
> static LIST_HEAD(acpi_bus_id_list);
> static DEFINE_MUTEX(acpi_scan_lock);
> +static LIST_HEAD(acpi_scan_handlers_list);
> DEFINE_MUTEX(acpi_device_lock);
> LIST_HEAD(acpi_wakeup_device_list);
>
> @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> struct list_head node;
> };
>
> +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> +{
> + if (!handler || !handler->attach)
> + return -EINVAL;
> +
> + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> + return 0;
> +}
> +
> /*
> * Creates hid/cid(s) string needed for modalias and uevent
> * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> return AE_OK;
> }
>
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> + struct acpi_scan_handler *handler;
> + int ret = 0;
> +
> + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> + const struct acpi_device_id *id;
> +
> + id = __acpi_match_device(device, handler->ids);
> + if (!id)
> + continue;
> +
> + ret = handler->attach(device, id);
> + if (ret > 0) {
> + device->handler = handler;
> + break;
> + } else if (ret < 0) {
> + break;
> + }
> + }
> + return ret;
> +}
Now that we have full control over the attach logic, it would be great
if we can update it to match with the ACPI spec -- HID has priority over
CIDs, and CIDs are also listed in their priority. For example, Device-X
has HID and CID. In this case, this Device-X should be attached to
Handler-A since it supports HID. The current logic simply chooses a
handler whichever registered before.
Device-X: HID PNPID-A, CID PNPID-B
Handler-A: PNPID-A
Handler-B: PNPID-B
So, the attach logic should be something like:
list_for_each_entry(hwid, acpi_device->pnp.ids,) {
list_for_each_entry(,&acpi_scan_handlers_list,)
check if this handler supports a given hwid
}
Thanks,
-Toshi
> +
> static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
> void *not_used, void **ret_not_used)
> {
> const struct acpi_device_id *id;
> - acpi_status status = AE_OK;
> struct acpi_device *device;
> unsigned long long sta_not_used;
> - int type_not_used;
> + int ret;
>
> /*
> * Ignore errors ignored by acpi_bus_check_add() to avoid terminating
> * namespace walks prematurely.
> */
> - if (acpi_bus_type_and_status(handle, &type_not_used, &sta_not_used))
> + if (acpi_bus_type_and_status(handle, &ret, &sta_not_used))
> return AE_OK;
>
> if (acpi_bus_get_device(handle, &device))
> @@ -1593,10 +1625,15 @@ static acpi_status acpi_bus_device_attac
> if (id) {
> /* This is a known good platform device. */
> acpi_create_platform_device(device, id->driver_data);
> - } else if (device_attach(&device->dev) < 0) {
> - status = AE_CTRL_DEPTH;
> + return AE_OK;
> }
> - return status;
> +
> + ret = acpi_scan_attach_handler(device);
> + if (ret)
> + return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
> +
> + ret = device_attach(&device->dev);
> + return ret >= 0 ? AE_OK : AE_CTRL_DEPTH;
> }
>
> /**
> @@ -1639,8 +1676,17 @@ static acpi_status acpi_bus_device_detac
> struct acpi_device *device = NULL;
>
> if (!acpi_bus_get_device(handle, &device)) {
> + struct acpi_scan_handler *dev_handler = device->handler;
> +
> device->removal_type = ACPI_BUS_REMOVAL_EJECT;
> - device_release_driver(&device->dev);
> + if (dev_handler) {
> + if (dev_handler->detach)
> + dev_handler->detach(device);
> +
> + device->handler = NULL;
> + } else {
> + device_release_driver(&device->dev);
> + }
> }
> return AE_OK;
> }
> Index: test/Documentation/acpi/scan_handlers.txt
> ===================================================================
> --- /dev/null
> +++ test/Documentation/acpi/scan_handlers.txt
> @@ -0,0 +1,77 @@
> +ACPI Scan Handlers
> +
> +Copyright (C) 2012, Intel Corporation
> +Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> +
> +During system initialization and ACPI-based device hot-add, the ACPI namespace
> +is scanned in search of device objects that generally represent various pieces
> +of hardware. This causes a struct acpi_device object to be created and
> +registered with the driver core for every device object in the ACPI namespace
> +and the hierarchy of those struct acpi_device objects reflects the namespace
> +layout (i.e. parent device objects in the namespace are represented by parent
> +struct acpi_device objects and analogously for their children). Those struct
> +acpi_device objects are referred to as "device nodes" in what follows, but they
> +should not be confused with struct device_node objects used by the Device Trees
> +parsing code (although their role is analogous to the role of those objects).
> +
> +During ACPI-based device hot-remove device nodes representing pieces of hardware
> +being removed are unregistered and deleted.
> +
> +The core ACPI namespace scanning code in drivers/acpi/scan.c carries out basic
> +initialization of device nodes, such as retrieving common configuration
> +information from the device objects represented by them and populating them with
> +appropriate data, but some of them require additional handling after they have
> +been registered. For example, if the given device node represents a PCI host
> +bridge, its registration should cause the PCI bus under that bridge to be
> +enumerated and PCI devices on that bus to be registered with the driver core.
> +Similarly, if the device node represents a PCI interrupt link, it is necessary
> +to configure that link so that the kernel can use it.
> +
> +Those additional configuration tasks usually depend on the type of the hardware
> +component represented by the given device node which can be determined on the
> +basis of the device node's hardware ID (HID). They are performed by objects
> +called ACPI scan handlers represented by the following structure:
> +
> +struct acpi_scan_handler {
> + const struct acpi_device_id *ids;
> + struct list_head list_node;
> + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> + void (*detach)(struct acpi_device *dev);
> +};
> +
> +where ids is the list of IDs of device nodes the given handler is supposed to
> +take care of, list_node is the hook to the global list of ACPI scan handlers
> +maintained by the ACPI core and the .attach() and .detach() callbacks are
> +executed, respectively, after registration of new device nodes and before
> +unregistration of device nodes the handler attached to previously.
> +
> +The namespace scanning function, acpi_bus_scan(), first registers all of the
> +device nodes in the given namespace scope with the driver core. Then, it tries
> +to match a scan handler against each of them using the ids arrays of the
> +available scan handlers. If a matching scan handler is found, its .attach()
> +callback is executed for the given device node. If that callback returns 1,
> +that means that the handler has claimed the device node and is now responsible
> +for carrying out any additional configuration tasks related to it. It also will
> +be responsible for preparing the device node for unregistration in that case.
> +The device node's handler field is then populated with the address of the scan
> +handler that has claimed it.
> +
> +If the .attach() callback returns 0, it means that the device node is not
> +interesting to the given scan handler and may be matched against the next scan
> +handler in the list. If it returns a (negative) error code, that means that
> +the namespace scan should be terminated due to a serious error. The error code
> +returned should then reflect the type of the error.
> +
> +The namespace trimming function, acpi_bus_trim(), first executes .detach()
> +callbacks from the scan handlers of all device nodes in the given namespace
> +scope (if they have scan handlers). Next, it unregisters all of the device
> +nodes in that scope.
> +
> +ACPI scan handlers can be added to the list maintained by the ACPI core with the
> +help of the acpi_scan_add_handler() function taking a pointer to the new scan
> +handler as an argument. The order in which scan handlers are added to the list
> +is the order in which they are matched against device nodes during namespace
> +scans.
> +
> +All scan handles must be added to the list before acpi_bus_scan() is run for the
> +first time and they cannot be removed from it.
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 2:35 ` Toshi Kani
@ 2013-01-29 11:28 ` Rafael J. Wysocki
2013-01-29 14:50 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 11:28 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > 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>
> > ---
> > Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> > drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> > include/acpi/acpi_bus.h | 14 ++++++
> > 3 files changed, 144 insertions(+), 7 deletions(-)
> >
> > Index: test/include/acpi/acpi_bus.h
> > ===================================================================
> > --- test.orig/include/acpi/acpi_bus.h
> > +++ test/include/acpi/acpi_bus.h
> > @@ -84,6 +84,18 @@ struct acpi_driver;
> > struct acpi_device;
> >
> > /*
> > + * ACPI Scan Handler
> > + * -----------------
> > + */
> > +
> > +struct acpi_scan_handler {
> > + const struct acpi_device_id *ids;
> > + struct list_head list_node;
> > + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > + void (*detach)(struct acpi_device *dev);
> > +};
> > +
> > +/*
> > * ACPI Driver
> > * -----------
> > */
> > @@ -269,6 +281,7 @@ struct acpi_device {
> > struct acpi_device_wakeup wakeup;
> > struct acpi_device_perf performance;
> > struct acpi_device_dir dir;
> > + struct acpi_scan_handler *handler;
> > struct acpi_driver *driver;
> > void *driver_data;
> > struct device dev;
> > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > { return 0; }
> > #endif
> > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > int acpi_bus_register_driver(struct acpi_driver *driver);
> > void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > int acpi_bus_scan(acpi_handle handle);
> > Index: test/drivers/acpi/scan.c
> > ===================================================================
> > --- test.orig/drivers/acpi/scan.c
> > +++ test/drivers/acpi/scan.c
> > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > static LIST_HEAD(acpi_device_list);
> > static LIST_HEAD(acpi_bus_id_list);
> > static DEFINE_MUTEX(acpi_scan_lock);
> > +static LIST_HEAD(acpi_scan_handlers_list);
> > DEFINE_MUTEX(acpi_device_lock);
> > LIST_HEAD(acpi_wakeup_device_list);
> >
> > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > struct list_head node;
> > };
> >
> > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > +{
> > + if (!handler || !handler->attach)
> > + return -EINVAL;
> > +
> > + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > + return 0;
> > +}
> > +
> > /*
> > * Creates hid/cid(s) string needed for modalias and uevent
> > * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > return AE_OK;
> > }
> >
> > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > +{
> > + struct acpi_scan_handler *handler;
> > + int ret = 0;
> > +
> > + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > + const struct acpi_device_id *id;
> > +
> > + id = __acpi_match_device(device, handler->ids);
> > + if (!id)
> > + continue;
> > +
> > + ret = handler->attach(device, id);
> > + if (ret > 0) {
> > + device->handler = handler;
> > + break;
> > + } else if (ret < 0) {
> > + break;
> > + }
> > + }
> > + return ret;
> > +}
>
> Now that we have full control over the attach logic, it would be great
> if we can update it to match with the ACPI spec -- HID has priority over
> CIDs, and CIDs are also listed in their priority. For example, Device-X
> has HID and CID. In this case, this Device-X should be attached to
> Handler-A since it supports HID. The current logic simply chooses a
> handler whichever registered before.
>
> Device-X: HID PNPID-A, CID PNPID-B
> Handler-A: PNPID-A
> Handler-B: PNPID-B
>
> So, the attach logic should be something like:
>
> list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> list_for_each_entry(,&acpi_scan_handlers_list,)
> check if this handler supports a given hwid
> }
OK, I see the problem, but I think it's better to address it in a separate
patch on top of the current series.
I'm not sure what approach is best, though. Do you think there should be two
passes the first of which will check HIDs only and the second one will check
CIDs? Or do you have something different in mind?
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 11:28 ` Rafael J. Wysocki
@ 2013-01-29 14:50 ` Toshi Kani
2013-01-29 21:32 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 14:50 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > 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>
> > > ---
> > > Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> > > drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> > > include/acpi/acpi_bus.h | 14 ++++++
> > > 3 files changed, 144 insertions(+), 7 deletions(-)
> > >
> > > Index: test/include/acpi/acpi_bus.h
> > > ===================================================================
> > > --- test.orig/include/acpi/acpi_bus.h
> > > +++ test/include/acpi/acpi_bus.h
> > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > struct acpi_device;
> > >
> > > /*
> > > + * ACPI Scan Handler
> > > + * -----------------
> > > + */
> > > +
> > > +struct acpi_scan_handler {
> > > + const struct acpi_device_id *ids;
> > > + struct list_head list_node;
> > > + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > + void (*detach)(struct acpi_device *dev);
> > > +};
> > > +
> > > +/*
> > > * ACPI Driver
> > > * -----------
> > > */
> > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > struct acpi_device_wakeup wakeup;
> > > struct acpi_device_perf performance;
> > > struct acpi_device_dir dir;
> > > + struct acpi_scan_handler *handler;
> > > struct acpi_driver *driver;
> > > void *driver_data;
> > > struct device dev;
> > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > { return 0; }
> > > #endif
> > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > int acpi_bus_register_driver(struct acpi_driver *driver);
> > > void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > int acpi_bus_scan(acpi_handle handle);
> > > Index: test/drivers/acpi/scan.c
> > > ===================================================================
> > > --- test.orig/drivers/acpi/scan.c
> > > +++ test/drivers/acpi/scan.c
> > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > static LIST_HEAD(acpi_device_list);
> > > static LIST_HEAD(acpi_bus_id_list);
> > > static DEFINE_MUTEX(acpi_scan_lock);
> > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > DEFINE_MUTEX(acpi_device_lock);
> > > LIST_HEAD(acpi_wakeup_device_list);
> > >
> > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > struct list_head node;
> > > };
> > >
> > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > +{
> > > + if (!handler || !handler->attach)
> > > + return -EINVAL;
> > > +
> > > + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > + return 0;
> > > +}
> > > +
> > > /*
> > > * Creates hid/cid(s) string needed for modalias and uevent
> > > * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > return AE_OK;
> > > }
> > >
> > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > +{
> > > + struct acpi_scan_handler *handler;
> > > + int ret = 0;
> > > +
> > > + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > + const struct acpi_device_id *id;
> > > +
> > > + id = __acpi_match_device(device, handler->ids);
> > > + if (!id)
> > > + continue;
> > > +
> > > + ret = handler->attach(device, id);
> > > + if (ret > 0) {
> > > + device->handler = handler;
> > > + break;
> > > + } else if (ret < 0) {
> > > + break;
> > > + }
> > > + }
> > > + return ret;
> > > +}
> >
> > Now that we have full control over the attach logic, it would be great
> > if we can update it to match with the ACPI spec -- HID has priority over
> > CIDs, and CIDs are also listed in their priority. For example, Device-X
> > has HID and CID. In this case, this Device-X should be attached to
> > Handler-A since it supports HID. The current logic simply chooses a
> > handler whichever registered before.
> >
> > Device-X: HID PNPID-A, CID PNPID-B
> > Handler-A: PNPID-A
> > Handler-B: PNPID-B
> >
> > So, the attach logic should be something like:
> >
> > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > list_for_each_entry(,&acpi_scan_handlers_list,)
> > check if this handler supports a given hwid
> > }
>
> OK, I see the problem, but I think it's better to address it in a separate
> patch on top of the current series.
I agree.
> I'm not sure what approach is best, though. Do you think there should be two
> passes the first of which will check HIDs only and the second one will check
> CIDs? Or do you have something different in mind?
HID and CIDs are already listed in their priority order in
acpi_device->pnp.ids. So, the single pass like I described above should
work.
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 14:50 ` Toshi Kani
@ 2013-01-29 21:32 ` Rafael J. Wysocki
2013-01-29 22:57 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 21:32 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > >
> > > > 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>
> > > > ---
> > > > Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> > > > drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> > > > include/acpi/acpi_bus.h | 14 ++++++
> > > > 3 files changed, 144 insertions(+), 7 deletions(-)
> > > >
> > > > Index: test/include/acpi/acpi_bus.h
> > > > ===================================================================
> > > > --- test.orig/include/acpi/acpi_bus.h
> > > > +++ test/include/acpi/acpi_bus.h
> > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > struct acpi_device;
> > > >
> > > > /*
> > > > + * ACPI Scan Handler
> > > > + * -----------------
> > > > + */
> > > > +
> > > > +struct acpi_scan_handler {
> > > > + const struct acpi_device_id *ids;
> > > > + struct list_head list_node;
> > > > + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > + void (*detach)(struct acpi_device *dev);
> > > > +};
> > > > +
> > > > +/*
> > > > * ACPI Driver
> > > > * -----------
> > > > */
> > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > struct acpi_device_wakeup wakeup;
> > > > struct acpi_device_perf performance;
> > > > struct acpi_device_dir dir;
> > > > + struct acpi_scan_handler *handler;
> > > > struct acpi_driver *driver;
> > > > void *driver_data;
> > > > struct device dev;
> > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > { return 0; }
> > > > #endif
> > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > int acpi_bus_scan(acpi_handle handle);
> > > > Index: test/drivers/acpi/scan.c
> > > > ===================================================================
> > > > --- test.orig/drivers/acpi/scan.c
> > > > +++ test/drivers/acpi/scan.c
> > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > static LIST_HEAD(acpi_device_list);
> > > > static LIST_HEAD(acpi_bus_id_list);
> > > > static DEFINE_MUTEX(acpi_scan_lock);
> > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > DEFINE_MUTEX(acpi_device_lock);
> > > > LIST_HEAD(acpi_wakeup_device_list);
> > > >
> > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > struct list_head node;
> > > > };
> > > >
> > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > +{
> > > > + if (!handler || !handler->attach)
> > > > + return -EINVAL;
> > > > +
> > > > + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > + return 0;
> > > > +}
> > > > +
> > > > /*
> > > > * Creates hid/cid(s) string needed for modalias and uevent
> > > > * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > return AE_OK;
> > > > }
> > > >
> > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > +{
> > > > + struct acpi_scan_handler *handler;
> > > > + int ret = 0;
> > > > +
> > > > + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > + const struct acpi_device_id *id;
> > > > +
> > > > + id = __acpi_match_device(device, handler->ids);
> > > > + if (!id)
> > > > + continue;
> > > > +
> > > > + ret = handler->attach(device, id);
> > > > + if (ret > 0) {
> > > > + device->handler = handler;
> > > > + break;
> > > > + } else if (ret < 0) {
> > > > + break;
> > > > + }
> > > > + }
> > > > + return ret;
> > > > +}
> > >
> > > Now that we have full control over the attach logic, it would be great
> > > if we can update it to match with the ACPI spec -- HID has priority over
> > > CIDs, and CIDs are also listed in their priority. For example, Device-X
> > > has HID and CID. In this case, this Device-X should be attached to
> > > Handler-A since it supports HID. The current logic simply chooses a
> > > handler whichever registered before.
> > >
> > > Device-X: HID PNPID-A, CID PNPID-B
> > > Handler-A: PNPID-A
> > > Handler-B: PNPID-B
> > >
> > > So, the attach logic should be something like:
> > >
> > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > list_for_each_entry(,&acpi_scan_handlers_list,)
> > > check if this handler supports a given hwid
> > > }
> >
> > OK, I see the problem, but I think it's better to address it in a separate
> > patch on top of the current series.
>
> I agree.
>
> > I'm not sure what approach is best, though. Do you think there should be two
> > passes the first of which will check HIDs only and the second one will check
> > CIDs? Or do you have something different in mind?
>
> HID and CIDs are already listed in their priority order in
> acpi_device->pnp.ids. So, the single pass like I described above should
> work.
Well, I'm not sure if I understand you correctly.
The device is given and we need to find a handler for it. So, it looks like
we first should check if any handler matches the HID. This has to be a pass
through all handlers. If there's no match, we need to check if any handler
matches any of the device IDs. That will be the second pass, won't it?
The difficulty is that the first item in pnp.ids need not be *the* HID.
It only will be the HID if ACPI_VALID_HID is set in the device info in
acpi_device_set_id(). So perhaps we need to add a hid_valid bit in
device->flags and only do the "HID pass" if that is set?
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 21:32 ` Rafael J. Wysocki
@ 2013-01-29 22:57 ` Toshi Kani
2013-01-29 23:19 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 22:57 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > >
> > > > > 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>
> > > > > ---
> > > > > Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> > > > > drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> > > > > include/acpi/acpi_bus.h | 14 ++++++
> > > > > 3 files changed, 144 insertions(+), 7 deletions(-)
> > > > >
> > > > > Index: test/include/acpi/acpi_bus.h
> > > > > ===================================================================
> > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > +++ test/include/acpi/acpi_bus.h
> > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > > struct acpi_device;
> > > > >
> > > > > /*
> > > > > + * ACPI Scan Handler
> > > > > + * -----------------
> > > > > + */
> > > > > +
> > > > > +struct acpi_scan_handler {
> > > > > + const struct acpi_device_id *ids;
> > > > > + struct list_head list_node;
> > > > > + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > + void (*detach)(struct acpi_device *dev);
> > > > > +};
> > > > > +
> > > > > +/*
> > > > > * ACPI Driver
> > > > > * -----------
> > > > > */
> > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > > struct acpi_device_wakeup wakeup;
> > > > > struct acpi_device_perf performance;
> > > > > struct acpi_device_dir dir;
> > > > > + struct acpi_scan_handler *handler;
> > > > > struct acpi_driver *driver;
> > > > > void *driver_data;
> > > > > struct device dev;
> > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > > static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > > { return 0; }
> > > > > #endif
> > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > > int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > > void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > > int acpi_bus_scan(acpi_handle handle);
> > > > > Index: test/drivers/acpi/scan.c
> > > > > ===================================================================
> > > > > --- test.orig/drivers/acpi/scan.c
> > > > > +++ test/drivers/acpi/scan.c
> > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > > static LIST_HEAD(acpi_device_list);
> > > > > static LIST_HEAD(acpi_bus_id_list);
> > > > > static DEFINE_MUTEX(acpi_scan_lock);
> > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > > DEFINE_MUTEX(acpi_device_lock);
> > > > > LIST_HEAD(acpi_wakeup_device_list);
> > > > >
> > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > > struct list_head node;
> > > > > };
> > > > >
> > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > +{
> > > > > + if (!handler || !handler->attach)
> > > > > + return -EINVAL;
> > > > > +
> > > > > + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > + return 0;
> > > > > +}
> > > > > +
> > > > > /*
> > > > > * Creates hid/cid(s) string needed for modalias and uevent
> > > > > * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > > return AE_OK;
> > > > > }
> > > > >
> > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > +{
> > > > > + struct acpi_scan_handler *handler;
> > > > > + int ret = 0;
> > > > > +
> > > > > + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > + const struct acpi_device_id *id;
> > > > > +
> > > > > + id = __acpi_match_device(device, handler->ids);
> > > > > + if (!id)
> > > > > + continue;
> > > > > +
> > > > > + ret = handler->attach(device, id);
> > > > > + if (ret > 0) {
> > > > > + device->handler = handler;
> > > > > + break;
> > > > > + } else if (ret < 0) {
> > > > > + break;
> > > > > + }
> > > > > + }
> > > > > + return ret;
> > > > > +}
> > > >
> > > > Now that we have full control over the attach logic, it would be great
> > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > CIDs, and CIDs are also listed in their priority. For example, Device-X
> > > > has HID and CID. In this case, this Device-X should be attached to
> > > > Handler-A since it supports HID. The current logic simply chooses a
> > > > handler whichever registered before.
> > > >
> > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > Handler-A: PNPID-A
> > > > Handler-B: PNPID-B
> > > >
> > > > So, the attach logic should be something like:
> > > >
> > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > check if this handler supports a given hwid
> > > > }
> > >
> > > OK, I see the problem, but I think it's better to address it in a separate
> > > patch on top of the current series.
> >
> > I agree.
> >
> > > I'm not sure what approach is best, though. Do you think there should be two
> > > passes the first of which will check HIDs only and the second one will check
> > > CIDs? Or do you have something different in mind?
> >
> > HID and CIDs are already listed in their priority order in
> > acpi_device->pnp.ids. So, the single pass like I described above should
> > work.
>
> Well, I'm not sure if I understand you correctly.
>
> The device is given and we need to find a handler for it. So, it looks like
> we first should check if any handler matches the HID. This has to be a pass
> through all handlers. If there's no match, we need to check if any handler
> matches any of the device IDs. That will be the second pass, won't it?
acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
acpi_device_set_id() checks HID before CIDs. So, the first pass is to
check with the first entry of pnp.ids. If no handler is found, then
check the second entry, and so on.
> The difficulty is that the first item in pnp.ids need not be *the* HID.
> It only will be the HID if ACPI_VALID_HID is set in the device info in
> acpi_device_set_id(). So perhaps we need to add a hid_valid bit in
> device->flags and only do the "HID pass" if that is set?
I do not think such bit is necessary for this. _HID is required (unless
it has _ADR), but _CID is optional. So, the valid cases are that a
device object has HID only, has both HID and CID(s), or has none of them
(i.e. _ADR device). If there is a device with CID only, this is a FW
bug and we just have to check with CID then.
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 22:57 ` Toshi Kani
@ 2013-01-29 23:19 ` Rafael J. Wysocki
2013-01-29 23:27 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 23:19 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Tuesday, January 29, 2013 03:57:10 PM Toshi Kani wrote:
> On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> > On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > >
> > > > > > 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>
> > > > > > ---
> > > > > > Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> > > > > > drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> > > > > > include/acpi/acpi_bus.h | 14 ++++++
> > > > > > 3 files changed, 144 insertions(+), 7 deletions(-)
> > > > > >
> > > > > > Index: test/include/acpi/acpi_bus.h
> > > > > > ===================================================================
> > > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > > +++ test/include/acpi/acpi_bus.h
> > > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > > > struct acpi_device;
> > > > > >
> > > > > > /*
> > > > > > + * ACPI Scan Handler
> > > > > > + * -----------------
> > > > > > + */
> > > > > > +
> > > > > > +struct acpi_scan_handler {
> > > > > > + const struct acpi_device_id *ids;
> > > > > > + struct list_head list_node;
> > > > > > + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > > + void (*detach)(struct acpi_device *dev);
> > > > > > +};
> > > > > > +
> > > > > > +/*
> > > > > > * ACPI Driver
> > > > > > * -----------
> > > > > > */
> > > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > > > struct acpi_device_wakeup wakeup;
> > > > > > struct acpi_device_perf performance;
> > > > > > struct acpi_device_dir dir;
> > > > > > + struct acpi_scan_handler *handler;
> > > > > > struct acpi_driver *driver;
> > > > > > void *driver_data;
> > > > > > struct device dev;
> > > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > > > static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > > > { return 0; }
> > > > > > #endif
> > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > > > int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > > > void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > > > int acpi_bus_scan(acpi_handle handle);
> > > > > > Index: test/drivers/acpi/scan.c
> > > > > > ===================================================================
> > > > > > --- test.orig/drivers/acpi/scan.c
> > > > > > +++ test/drivers/acpi/scan.c
> > > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > > > static LIST_HEAD(acpi_device_list);
> > > > > > static LIST_HEAD(acpi_bus_id_list);
> > > > > > static DEFINE_MUTEX(acpi_scan_lock);
> > > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > > > DEFINE_MUTEX(acpi_device_lock);
> > > > > > LIST_HEAD(acpi_wakeup_device_list);
> > > > > >
> > > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > > > struct list_head node;
> > > > > > };
> > > > > >
> > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > > +{
> > > > > > + if (!handler || !handler->attach)
> > > > > > + return -EINVAL;
> > > > > > +
> > > > > > + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > > + return 0;
> > > > > > +}
> > > > > > +
> > > > > > /*
> > > > > > * Creates hid/cid(s) string needed for modalias and uevent
> > > > > > * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > > > return AE_OK;
> > > > > > }
> > > > > >
> > > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > > +{
> > > > > > + struct acpi_scan_handler *handler;
> > > > > > + int ret = 0;
> > > > > > +
> > > > > > + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > > + const struct acpi_device_id *id;
> > > > > > +
> > > > > > + id = __acpi_match_device(device, handler->ids);
> > > > > > + if (!id)
> > > > > > + continue;
> > > > > > +
> > > > > > + ret = handler->attach(device, id);
> > > > > > + if (ret > 0) {
> > > > > > + device->handler = handler;
> > > > > > + break;
> > > > > > + } else if (ret < 0) {
> > > > > > + break;
> > > > > > + }
> > > > > > + }
> > > > > > + return ret;
> > > > > > +}
> > > > >
> > > > > Now that we have full control over the attach logic, it would be great
> > > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > > CIDs, and CIDs are also listed in their priority. For example, Device-X
> > > > > has HID and CID. In this case, this Device-X should be attached to
> > > > > Handler-A since it supports HID. The current logic simply chooses a
> > > > > handler whichever registered before.
> > > > >
> > > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > > Handler-A: PNPID-A
> > > > > Handler-B: PNPID-B
> > > > >
> > > > > So, the attach logic should be something like:
> > > > >
> > > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > > list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > > check if this handler supports a given hwid
> > > > > }
> > > >
> > > > OK, I see the problem, but I think it's better to address it in a separate
> > > > patch on top of the current series.
> > >
> > > I agree.
> > >
> > > > I'm not sure what approach is best, though. Do you think there should be two
> > > > passes the first of which will check HIDs only and the second one will check
> > > > CIDs? Or do you have something different in mind?
> > >
> > > HID and CIDs are already listed in their priority order in
> > > acpi_device->pnp.ids. So, the single pass like I described above should
> > > work.
> >
> > Well, I'm not sure if I understand you correctly.
> >
> > The device is given and we need to find a handler for it. So, it looks like
> > we first should check if any handler matches the HID. This has to be a pass
> > through all handlers. If there's no match, we need to check if any handler
> > matches any of the device IDs. That will be the second pass, won't it?
>
> acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
> acpi_device_set_id() checks HID before CIDs. So, the first pass is to
> check with the first entry of pnp.ids. If no handler is found, then
> check the second entry, and so on.
I'd prefer to check HID and then all CIDs at once in accordance with the
following rule:
1) Use the first handler that matches HID exactly. If there's none:
2) Use the first handler compatible with the given device.
> > The difficulty is that the first item in pnp.ids need not be *the* HID.
> > It only will be the HID if ACPI_VALID_HID is set in the device info in
> > acpi_device_set_id(). So perhaps we need to add a hid_valid bit in
> > device->flags and only do the "HID pass" if that is set?
>
> I do not think such bit is necessary for this. _HID is required (unless
> it has _ADR), but _CID is optional. So, the valid cases are that a
> device object has HID only, has both HID and CID(s), or has none of them
> (i.e. _ADR device). If there is a device with CID only, this is a FW
> bug and we just have to check with CID then.
In addition to that there's a number of objects that we assign artificial HIDs.
I think we should treat them as CIDs rather than as real HIDs in this regard.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 23:19 ` Rafael J. Wysocki
@ 2013-01-29 23:27 ` Toshi Kani
2013-01-30 13:18 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 23:27 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Wed, 2013-01-30 at 00:19 +0100, Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 03:57:10 PM Toshi Kani wrote:
> > On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> > > On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > > > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > >
> > > > > > > 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>
> > > > > > > ---
> > > > > > > Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> > > > > > > drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> > > > > > > include/acpi/acpi_bus.h | 14 ++++++
> > > > > > > 3 files changed, 144 insertions(+), 7 deletions(-)
> > > > > > >
> > > > > > > Index: test/include/acpi/acpi_bus.h
> > > > > > > ===================================================================
> > > > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > > > +++ test/include/acpi/acpi_bus.h
> > > > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > > > > struct acpi_device;
> > > > > > >
> > > > > > > /*
> > > > > > > + * ACPI Scan Handler
> > > > > > > + * -----------------
> > > > > > > + */
> > > > > > > +
> > > > > > > +struct acpi_scan_handler {
> > > > > > > + const struct acpi_device_id *ids;
> > > > > > > + struct list_head list_node;
> > > > > > > + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > > > + void (*detach)(struct acpi_device *dev);
> > > > > > > +};
> > > > > > > +
> > > > > > > +/*
> > > > > > > * ACPI Driver
> > > > > > > * -----------
> > > > > > > */
> > > > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > > > > struct acpi_device_wakeup wakeup;
> > > > > > > struct acpi_device_perf performance;
> > > > > > > struct acpi_device_dir dir;
> > > > > > > + struct acpi_scan_handler *handler;
> > > > > > > struct acpi_driver *driver;
> > > > > > > void *driver_data;
> > > > > > > struct device dev;
> > > > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > > > > static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > > > > { return 0; }
> > > > > > > #endif
> > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > > > > int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > > > > void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > > > > int acpi_bus_scan(acpi_handle handle);
> > > > > > > Index: test/drivers/acpi/scan.c
> > > > > > > ===================================================================
> > > > > > > --- test.orig/drivers/acpi/scan.c
> > > > > > > +++ test/drivers/acpi/scan.c
> > > > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > > > > static LIST_HEAD(acpi_device_list);
> > > > > > > static LIST_HEAD(acpi_bus_id_list);
> > > > > > > static DEFINE_MUTEX(acpi_scan_lock);
> > > > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > > > > DEFINE_MUTEX(acpi_device_lock);
> > > > > > > LIST_HEAD(acpi_wakeup_device_list);
> > > > > > >
> > > > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > > > > struct list_head node;
> > > > > > > };
> > > > > > >
> > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > > > +{
> > > > > > > + if (!handler || !handler->attach)
> > > > > > > + return -EINVAL;
> > > > > > > +
> > > > > > > + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > > > + return 0;
> > > > > > > +}
> > > > > > > +
> > > > > > > /*
> > > > > > > * Creates hid/cid(s) string needed for modalias and uevent
> > > > > > > * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > > > > return AE_OK;
> > > > > > > }
> > > > > > >
> > > > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > > > +{
> > > > > > > + struct acpi_scan_handler *handler;
> > > > > > > + int ret = 0;
> > > > > > > +
> > > > > > > + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > > > + const struct acpi_device_id *id;
> > > > > > > +
> > > > > > > + id = __acpi_match_device(device, handler->ids);
> > > > > > > + if (!id)
> > > > > > > + continue;
> > > > > > > +
> > > > > > > + ret = handler->attach(device, id);
> > > > > > > + if (ret > 0) {
> > > > > > > + device->handler = handler;
> > > > > > > + break;
> > > > > > > + } else if (ret < 0) {
> > > > > > > + break;
> > > > > > > + }
> > > > > > > + }
> > > > > > > + return ret;
> > > > > > > +}
> > > > > >
> > > > > > Now that we have full control over the attach logic, it would be great
> > > > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > > > CIDs, and CIDs are also listed in their priority. For example, Device-X
> > > > > > has HID and CID. In this case, this Device-X should be attached to
> > > > > > Handler-A since it supports HID. The current logic simply chooses a
> > > > > > handler whichever registered before.
> > > > > >
> > > > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > > > Handler-A: PNPID-A
> > > > > > Handler-B: PNPID-B
> > > > > >
> > > > > > So, the attach logic should be something like:
> > > > > >
> > > > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > > > list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > > > check if this handler supports a given hwid
> > > > > > }
> > > > >
> > > > > OK, I see the problem, but I think it's better to address it in a separate
> > > > > patch on top of the current series.
> > > >
> > > > I agree.
> > > >
> > > > > I'm not sure what approach is best, though. Do you think there should be two
> > > > > passes the first of which will check HIDs only and the second one will check
> > > > > CIDs? Or do you have something different in mind?
> > > >
> > > > HID and CIDs are already listed in their priority order in
> > > > acpi_device->pnp.ids. So, the single pass like I described above should
> > > > work.
> > >
> > > Well, I'm not sure if I understand you correctly.
> > >
> > > The device is given and we need to find a handler for it. So, it looks like
> > > we first should check if any handler matches the HID. This has to be a pass
> > > through all handlers. If there's no match, we need to check if any handler
> > > matches any of the device IDs. That will be the second pass, won't it?
> >
> > acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
> > acpi_device_set_id() checks HID before CIDs. So, the first pass is to
> > check with the first entry of pnp.ids. If no handler is found, then
> > check the second entry, and so on.
>
> I'd prefer to check HID and then all CIDs at once in accordance with the
> following rule:
> 1) Use the first handler that matches HID exactly. If there's none:
> 2) Use the first handler compatible with the given device.
What do you mean by all CIDs at once? CIDs also have priority when
there are multiple CIDs. That is, CID[0] takes priority over CID[1].
So, going down the pnp.ids list handles the ordering correctly.
> > > The difficulty is that the first item in pnp.ids need not be *the* HID.
> > > It only will be the HID if ACPI_VALID_HID is set in the device info in
> > > acpi_device_set_id(). So perhaps we need to add a hid_valid bit in
> > > device->flags and only do the "HID pass" if that is set?
> >
> > I do not think such bit is necessary for this. _HID is required (unless
> > it has _ADR), but _CID is optional. So, the valid cases are that a
> > device object has HID only, has both HID and CID(s), or has none of them
> > (i.e. _ADR device). If there is a device with CID only, this is a FW
> > bug and we just have to check with CID then.
>
> In addition to that there's a number of objects that we assign artificial HIDs.
> I think we should treat them as CIDs rather than as real HIDs in this regard.
When an object does not support the _HID/_CID combination, it means that
this type of objects can only support a single characteristic, which is
the same as a device object with HID only. Therefore, an artificial ID
should be considered as an HID.
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler
2013-01-29 23:27 ` Toshi Kani
@ 2013-01-30 13:18 ` Rafael J. Wysocki
2013-02-03 0:52 ` [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-30 13:18 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Tuesday, January 29, 2013 04:27:28 PM Toshi Kani wrote:
> On Wed, 2013-01-30 at 00:19 +0100, Rafael J. Wysocki wrote:
> > On Tuesday, January 29, 2013 03:57:10 PM Toshi Kani wrote:
> > > On Tue, 2013-01-29 at 22:32 +0100, Rafael J. Wysocki wrote:
> > > > On Tuesday, January 29, 2013 07:50:43 AM Toshi Kani wrote:
> > > > > On Tue, 2013-01-29 at 12:28 +0100, Rafael J. Wysocki wrote:
> > > > > > On Monday, January 28, 2013 07:35:39 PM Toshi Kani wrote:
> > > > > > > On Mon, 2013-01-28 at 13:59 +0100, Rafael J. Wysocki wrote:
> > > > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > > > >
> > > > > > > > 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>
> > > > > > > > ---
> > > > > > > > Documentation/acpi/scan_handlers.txt | 77 +++++++++++++++++++++++++++++++++++
> > > > > > > > drivers/acpi/scan.c | 60 ++++++++++++++++++++++++---
> > > > > > > > include/acpi/acpi_bus.h | 14 ++++++
> > > > > > > > 3 files changed, 144 insertions(+), 7 deletions(-)
> > > > > > > >
> > > > > > > > Index: test/include/acpi/acpi_bus.h
> > > > > > > > ===================================================================
> > > > > > > > --- test.orig/include/acpi/acpi_bus.h
> > > > > > > > +++ test/include/acpi/acpi_bus.h
> > > > > > > > @@ -84,6 +84,18 @@ struct acpi_driver;
> > > > > > > > struct acpi_device;
> > > > > > > >
> > > > > > > > /*
> > > > > > > > + * ACPI Scan Handler
> > > > > > > > + * -----------------
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +struct acpi_scan_handler {
> > > > > > > > + const struct acpi_device_id *ids;
> > > > > > > > + struct list_head list_node;
> > > > > > > > + int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
> > > > > > > > + void (*detach)(struct acpi_device *dev);
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +/*
> > > > > > > > * ACPI Driver
> > > > > > > > * -----------
> > > > > > > > */
> > > > > > > > @@ -269,6 +281,7 @@ struct acpi_device {
> > > > > > > > struct acpi_device_wakeup wakeup;
> > > > > > > > struct acpi_device_perf performance;
> > > > > > > > struct acpi_device_dir dir;
> > > > > > > > + struct acpi_scan_handler *handler;
> > > > > > > > struct acpi_driver *driver;
> > > > > > > > void *driver_data;
> > > > > > > > struct device dev;
> > > > > > > > @@ -382,6 +395,7 @@ int acpi_bus_receive_event(struct acpi_b
> > > > > > > > static inline int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
> > > > > > > > { return 0; }
> > > > > > > > #endif
> > > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler);
> > > > > > > > int acpi_bus_register_driver(struct acpi_driver *driver);
> > > > > > > > void acpi_bus_unregister_driver(struct acpi_driver *driver);
> > > > > > > > int acpi_bus_scan(acpi_handle handle);
> > > > > > > > Index: test/drivers/acpi/scan.c
> > > > > > > > ===================================================================
> > > > > > > > --- test.orig/drivers/acpi/scan.c
> > > > > > > > +++ test/drivers/acpi/scan.c
> > > > > > > > @@ -53,6 +53,7 @@ static const struct acpi_device_id acpi_
> > > > > > > > static LIST_HEAD(acpi_device_list);
> > > > > > > > static LIST_HEAD(acpi_bus_id_list);
> > > > > > > > static DEFINE_MUTEX(acpi_scan_lock);
> > > > > > > > +static LIST_HEAD(acpi_scan_handlers_list);
> > > > > > > > DEFINE_MUTEX(acpi_device_lock);
> > > > > > > > LIST_HEAD(acpi_wakeup_device_list);
> > > > > > > >
> > > > > > > > @@ -62,6 +63,15 @@ struct acpi_device_bus_id{
> > > > > > > > struct list_head node;
> > > > > > > > };
> > > > > > > >
> > > > > > > > +int acpi_scan_add_handler(struct acpi_scan_handler *handler)
> > > > > > > > +{
> > > > > > > > + if (!handler || !handler->attach)
> > > > > > > > + return -EINVAL;
> > > > > > > > +
> > > > > > > > + list_add_tail(&handler->list_node, &acpi_scan_handlers_list);
> > > > > > > > + return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > /*
> > > > > > > > * Creates hid/cid(s) string needed for modalias and uevent
> > > > > > > > * e.g. on a device with hid:IBM0001 and cid:ACPI0001 you get:
> > > > > > > > @@ -1570,20 +1580,42 @@ static acpi_status acpi_bus_check_add(ac
> > > > > > > > return AE_OK;
> > > > > > > > }
> > > > > > > >
> > > > > > > > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > > > > > > > +{
> > > > > > > > + struct acpi_scan_handler *handler;
> > > > > > > > + int ret = 0;
> > > > > > > > +
> > > > > > > > + list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > > > > > > > + const struct acpi_device_id *id;
> > > > > > > > +
> > > > > > > > + id = __acpi_match_device(device, handler->ids);
> > > > > > > > + if (!id)
> > > > > > > > + continue;
> > > > > > > > +
> > > > > > > > + ret = handler->attach(device, id);
> > > > > > > > + if (ret > 0) {
> > > > > > > > + device->handler = handler;
> > > > > > > > + break;
> > > > > > > > + } else if (ret < 0) {
> > > > > > > > + break;
> > > > > > > > + }
> > > > > > > > + }
> > > > > > > > + return ret;
> > > > > > > > +}
> > > > > > >
> > > > > > > Now that we have full control over the attach logic, it would be great
> > > > > > > if we can update it to match with the ACPI spec -- HID has priority over
> > > > > > > CIDs, and CIDs are also listed in their priority. For example, Device-X
> > > > > > > has HID and CID. In this case, this Device-X should be attached to
> > > > > > > Handler-A since it supports HID. The current logic simply chooses a
> > > > > > > handler whichever registered before.
> > > > > > >
> > > > > > > Device-X: HID PNPID-A, CID PNPID-B
> > > > > > > Handler-A: PNPID-A
> > > > > > > Handler-B: PNPID-B
> > > > > > >
> > > > > > > So, the attach logic should be something like:
> > > > > > >
> > > > > > > list_for_each_entry(hwid, acpi_device->pnp.ids,) {
> > > > > > > list_for_each_entry(,&acpi_scan_handlers_list,)
> > > > > > > check if this handler supports a given hwid
> > > > > > > }
> > > > > >
> > > > > > OK, I see the problem, but I think it's better to address it in a separate
> > > > > > patch on top of the current series.
> > > > >
> > > > > I agree.
> > > > >
> > > > > > I'm not sure what approach is best, though. Do you think there should be two
> > > > > > passes the first of which will check HIDs only and the second one will check
> > > > > > CIDs? Or do you have something different in mind?
> > > > >
> > > > > HID and CIDs are already listed in their priority order in
> > > > > acpi_device->pnp.ids. So, the single pass like I described above should
> > > > > work.
> > > >
> > > > Well, I'm not sure if I understand you correctly.
> > > >
> > > > The device is given and we need to find a handler for it. So, it looks like
> > > > we first should check if any handler matches the HID. This has to be a pass
> > > > through all handlers. If there's no match, we need to check if any handler
> > > > matches any of the device IDs. That will be the second pass, won't it?
> > >
> > > acpi_device->pnp.ids has a list of HID->CID[0]->CID[1]..CID[n] since
> > > acpi_device_set_id() checks HID before CIDs. So, the first pass is to
> > > check with the first entry of pnp.ids. If no handler is found, then
> > > check the second entry, and so on.
> >
> > I'd prefer to check HID and then all CIDs at once in accordance with the
> > following rule:
> > 1) Use the first handler that matches HID exactly. If there's none:
> > 2) Use the first handler compatible with the given device.
>
> What do you mean by all CIDs at once? CIDs also have priority when
> there are multiple CIDs. That is, CID[0] takes priority over CID[1].
> So, going down the pnp.ids list handles the ordering correctly.
OK, I see what you mean now.
> > > > The difficulty is that the first item in pnp.ids need not be *the* HID.
> > > > It only will be the HID if ACPI_VALID_HID is set in the device info in
> > > > acpi_device_set_id(). So perhaps we need to add a hid_valid bit in
> > > > device->flags and only do the "HID pass" if that is set?
> > >
> > > I do not think such bit is necessary for this. _HID is required (unless
> > > it has _ADR), but _CID is optional. So, the valid cases are that a
> > > device object has HID only, has both HID and CID(s), or has none of them
> > > (i.e. _ADR device). If there is a device with CID only, this is a FW
> > > bug and we just have to check with CID then.
> >
> > In addition to that there's a number of objects that we assign artificial HIDs.
> > I think we should treat them as CIDs rather than as real HIDs in this regard.
>
> When an object does not support the _HID/_CID combination, it means that
> this type of objects can only support a single characteristic, which is
> the same as a device object with HID only. Therefore, an artificial ID
> should be considered as an HID.
I'm not sure about that, but it shouldn't really matter a lot anyway. :-)
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
2013-01-30 13:18 ` Rafael J. Wysocki
@ 2013-02-03 0:52 ` Rafael J. Wysocki
2013-02-03 4:54 ` Yinghai Lu
2013-02-05 23:44 ` Toshi Kani
0 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 0:52 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
The IDs of ACPI device nodes stored in their pnp.ids member arrays
are sorted by decreasing priority (i.e. the highest-priority ID is
the first entry). This means that when matching scan handlers to
device nodes, the namespace scanning code should walk the list of
scan handlers for each device node ID instead of walking the list
of device node IDs for each handler (the latter causes the first
handler matching any of the device node IDs to be chosen, although
there may be another handler matching an ID of a higher priority
which should be preferred). Make the code follow this observation.
This change has been suggested and justified by Toshi Kani.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/scan.c | 42 +++++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
return AE_OK;
}
-static int acpi_scan_attach_handler(struct acpi_device *device)
+static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
{
struct acpi_scan_handler *handler;
- int ret = 0;
list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
- const struct acpi_device_id *id;
+ const struct acpi_device_id *devid;
- id = __acpi_match_device(device, handler->ids);
- if (!id)
- continue;
-
- ret = handler->attach(device, id);
- if (ret > 0) {
- device->handler = handler;
- break;
- } else if (ret < 0) {
- break;
+ for (devid = handler->ids; devid->id[0]; devid++) {
+ int ret;
+
+ if (strcmp((char *)devid->id, id))
+ continue;
+
+ ret = handler->attach(device, devid);
+ if (ret > 0) {
+ device->handler = handler;
+ return ret;
+ } else if (ret < 0) {
+ return ret;
+ }
}
}
+ return 0;
+}
+
+static int acpi_scan_attach_handler(struct acpi_device *device)
+{
+ struct acpi_hardware_id *hwid;
+ int ret = 0;
+
+ list_for_each_entry(hwid, &device->pnp.ids, list) {
+ ret = acpi_scan_do_attach_handler(device, hwid->id);
+ if (ret)
+ break;
+
+ }
return ret;
}
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
2013-02-03 0:52 ` [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers Rafael J. Wysocki
@ 2013-02-03 4:54 ` Yinghai Lu
2013-02-03 13:05 ` Rafael J. Wysocki
2013-02-05 23:44 ` Toshi Kani
1 sibling, 1 reply; 71+ messages in thread
From: Yinghai Lu @ 2013-02-03 4:54 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Toshi Kani, ACPI Devel Maling List, Greg Kroah-Hartman,
Bjorn Helgaas, Mika Westerberg, Matthew Garrett, Jiang Liu, LKML
On Sat, Feb 2, 2013 at 4:52 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The IDs of ACPI device nodes stored in their pnp.ids member arrays
> are sorted by decreasing priority (i.e. the highest-priority ID is
> the first entry). This means that when matching scan handlers to
> device nodes, the namespace scanning code should walk the list of
> scan handlers for each device node ID instead of walking the list
> of device node IDs for each handler (the latter causes the first
> handler matching any of the device node IDs to be chosen, although
> there may be another handler matching an ID of a higher priority
> which should be preferred). Make the code follow this observation.
>
> This change has been suggested and justified by Toshi Kani.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
> drivers/acpi/scan.c | 42 +++++++++++++++++++++++++++++-------------
> 1 file changed, 29 insertions(+), 13 deletions(-)
>
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
> return AE_OK;
> }
>
> -static int acpi_scan_attach_handler(struct acpi_device *device)
> +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
> {
> struct acpi_scan_handler *handler;
> - int ret = 0;
>
> list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> - const struct acpi_device_id *id;
> + const struct acpi_device_id *devid;
>
> - id = __acpi_match_device(device, handler->ids);
> - if (!id)
> - continue;
> -
> - ret = handler->attach(device, id);
> - if (ret > 0) {
> - device->handler = handler;
> - break;
> - } else if (ret < 0) {
> - break;
> + for (devid = handler->ids; devid->id[0]; devid++) {
> + int ret;
> +
> + if (strcmp((char *)devid->id, id))
> + continue;
> +
> + ret = handler->attach(device, devid);
> + if (ret > 0) {
> + device->handler = handler;
> + return ret;
> + } else if (ret < 0) {
> + return ret;
> + }
> }
> }
> + return 0;
> +}
> +
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> + struct acpi_hardware_id *hwid;
> + int ret = 0;
> +
> + list_for_each_entry(hwid, &device->pnp.ids, list) {
> + ret = acpi_scan_do_attach_handler(device, hwid->id);
> + if (ret)
> + break;
> +
> + }
> return ret;
> }
>
>
Looks like right to honor the order in pnp.ids.
so there is same problem with acpi_bus_match/acpi_match_device_ids
that need to fixed?
Yinghai
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
2013-02-03 4:54 ` Yinghai Lu
@ 2013-02-03 13:05 ` Rafael J. Wysocki
0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 13:05 UTC (permalink / raw)
To: Yinghai Lu
Cc: Toshi Kani, ACPI Devel Maling List, Greg Kroah-Hartman,
Bjorn Helgaas, Mika Westerberg, Matthew Garrett, Jiang Liu, LKML
On Saturday, February 02, 2013 08:54:46 PM Yinghai Lu wrote:
> On Sat, Feb 2, 2013 at 4:52 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > The IDs of ACPI device nodes stored in their pnp.ids member arrays
> > are sorted by decreasing priority (i.e. the highest-priority ID is
> > the first entry). This means that when matching scan handlers to
> > device nodes, the namespace scanning code should walk the list of
> > scan handlers for each device node ID instead of walking the list
> > of device node IDs for each handler (the latter causes the first
> > handler matching any of the device node IDs to be chosen, although
> > there may be another handler matching an ID of a higher priority
> > which should be preferred). Make the code follow this observation.
> >
> > This change has been suggested and justified by Toshi Kani.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> > drivers/acpi/scan.c | 42 +++++++++++++++++++++++++++++-------------
> > 1 file changed, 29 insertions(+), 13 deletions(-)
> >
> > Index: test/drivers/acpi/scan.c
> > ===================================================================
> > --- test.orig/drivers/acpi/scan.c
> > +++ test/drivers/acpi/scan.c
> > @@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
> > return AE_OK;
> > }
> >
> > -static int acpi_scan_attach_handler(struct acpi_device *device)
> > +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
> > {
> > struct acpi_scan_handler *handler;
> > - int ret = 0;
> >
> > list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> > - const struct acpi_device_id *id;
> > + const struct acpi_device_id *devid;
> >
> > - id = __acpi_match_device(device, handler->ids);
> > - if (!id)
> > - continue;
> > -
> > - ret = handler->attach(device, id);
> > - if (ret > 0) {
> > - device->handler = handler;
> > - break;
> > - } else if (ret < 0) {
> > - break;
> > + for (devid = handler->ids; devid->id[0]; devid++) {
> > + int ret;
> > +
> > + if (strcmp((char *)devid->id, id))
> > + continue;
> > +
> > + ret = handler->attach(device, devid);
> > + if (ret > 0) {
> > + device->handler = handler;
> > + return ret;
> > + } else if (ret < 0) {
> > + return ret;
> > + }
> > }
> > }
> > + return 0;
> > +}
> > +
> > +static int acpi_scan_attach_handler(struct acpi_device *device)
> > +{
> > + struct acpi_hardware_id *hwid;
> > + int ret = 0;
> > +
> > + list_for_each_entry(hwid, &device->pnp.ids, list) {
> > + ret = acpi_scan_do_attach_handler(device, hwid->id);
> > + if (ret)
> > + break;
> > +
> > + }
> > return ret;
> > }
> >
> >
>
> Looks like right to honor the order in pnp.ids.
>
> so there is same problem with acpi_bus_match/acpi_match_device_ids
> that need to fixed?
Yes, there is the same problem, but I'm not sure we can actually fix it.
The driver core walks the list of available drivers for the given bus just
once in bus_probe_device(), so it cannot check all drivers against each of
the given device IDs. So it looks like acpi_bus_match() does all it can do
(one more reason to get rid of the ACPI bus type IMHO).
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers
2013-02-03 0:52 ` [PATCH] ACPI / scan: Follow priorities of IDs when matching scan handlers Rafael J. Wysocki
2013-02-03 4:54 ` Yinghai Lu
@ 2013-02-05 23:44 ` Toshi Kani
1 sibling, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-05 23:44 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Sun, 2013-02-03 at 01:52 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The IDs of ACPI device nodes stored in their pnp.ids member arrays
> are sorted by decreasing priority (i.e. the highest-priority ID is
> the first entry). This means that when matching scan handlers to
> device nodes, the namespace scanning code should walk the list of
> scan handlers for each device node ID instead of walking the list
> of device node IDs for each handler (the latter causes the first
> handler matching any of the device node IDs to be chosen, although
> there may be another handler matching an ID of a higher priority
> which should be preferred). Make the code follow this observation.
>
> This change has been suggested and justified by Toshi Kani.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Looks good! Thanks for making this change. :-)
Acked-by: Toshi Kani <toshi.kani@hp.com>
-Toshi
> ---
> drivers/acpi/scan.c | 42 +++++++++++++++++++++++++++++-------------
> 1 file changed, 29 insertions(+), 13 deletions(-)
>
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1556,26 +1556,42 @@ static acpi_status acpi_bus_check_add(ac
> return AE_OK;
> }
>
> -static int acpi_scan_attach_handler(struct acpi_device *device)
> +static int acpi_scan_do_attach_handler(struct acpi_device *device, char *id)
> {
> struct acpi_scan_handler *handler;
> - int ret = 0;
>
> list_for_each_entry(handler, &acpi_scan_handlers_list, list_node) {
> - const struct acpi_device_id *id;
> + const struct acpi_device_id *devid;
>
> - id = __acpi_match_device(device, handler->ids);
> - if (!id)
> - continue;
> -
> - ret = handler->attach(device, id);
> - if (ret > 0) {
> - device->handler = handler;
> - break;
> - } else if (ret < 0) {
> - break;
> + for (devid = handler->ids; devid->id[0]; devid++) {
> + int ret;
> +
> + if (strcmp((char *)devid->id, id))
> + continue;
> +
> + ret = handler->attach(device, devid);
> + if (ret > 0) {
> + device->handler = handler;
> + return ret;
> + } else if (ret < 0) {
> + return ret;
> + }
> }
> }
> + return 0;
> +}
> +
> +static int acpi_scan_attach_handler(struct acpi_device *device)
> +{
> + struct acpi_hardware_id *hwid;
> + int ret = 0;
> +
> + list_for_each_entry(hwid, &device->pnp.ids, list) {
> + ret = acpi_scan_do_attach_handler(device, hwid->id);
> + if (ret)
> + break;
> +
> + }
> return ret;
> }
>
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 2/4] ACPI / PCI: Make PCI root driver use struct acpi_scan_handler
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
2013-01-28 12:59 ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
@ 2013-01-28 13:00 ` Rafael J. Wysocki
2013-01-28 13:00 ` [PATCH 3/4] ACPI / PCI: Make PCI IRQ link " Rafael J. Wysocki
` (5 subsequent siblings)
7 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 13:00 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Make the ACPI PCI root bridge driver use struct acpi_scan_handler
for representing the object used to enumerate the PCI busses under
PCI host bridges found in the ACPI namespace (and to tear down data
structures representing the bus and devices on it before
unregistering the host bridges' ACPI device nodes).
This simplifies the code slightly and reduces the kernel's memory
footprint by avoiding the registration of a struct device_driver
object with the driver core and creation of its sysfs directory
which is unnecessary.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/internal.h | 2 +-
drivers/acpi/pci_root.c | 38 +++++++++++++++-----------------------
2 files changed, 16 insertions(+), 24 deletions(-)
Index: test/drivers/acpi/pci_root.c
===================================================================
--- test.orig/drivers/acpi/pci_root.c
+++ test/drivers/acpi/pci_root.c
@@ -45,8 +45,9 @@
ACPI_MODULE_NAME("pci_root");
#define ACPI_PCI_ROOT_CLASS "pci_bridge"
#define ACPI_PCI_ROOT_DEVICE_NAME "PCI Root Bridge"
-static int acpi_pci_root_add(struct acpi_device *device);
-static int acpi_pci_root_remove(struct acpi_device *device);
+static int acpi_pci_root_add(struct acpi_device *device,
+ const struct acpi_device_id *not_used);
+static void acpi_pci_root_remove(struct acpi_device *device);
#define ACPI_PCIE_REQ_SUPPORT (OSC_EXT_PCI_CONFIG_SUPPORT \
| OSC_ACTIVE_STATE_PWR_SUPPORT \
@@ -57,16 +58,11 @@ static const struct acpi_device_id root_
{"PNP0A03", 0},
{"", 0},
};
-MODULE_DEVICE_TABLE(acpi, root_device_ids);
-static struct acpi_driver acpi_pci_root_driver = {
- .name = "pci_root",
- .class = ACPI_PCI_ROOT_CLASS,
+static struct acpi_scan_handler pci_root_handler = {
.ids = root_device_ids,
- .ops = {
- .add = acpi_pci_root_add,
- .remove = acpi_pci_root_remove,
- },
+ .attach = acpi_pci_root_add,
+ .detach = acpi_pci_root_remove,
};
/* Lock to protect both acpi_pci_roots and acpi_pci_drivers lists */
@@ -428,7 +424,8 @@ out:
}
EXPORT_SYMBOL(acpi_pci_osc_control_set);
-static int acpi_pci_root_add(struct acpi_device *device)
+static int acpi_pci_root_add(struct acpi_device *device,
+ const struct acpi_device_id *not_used)
{
unsigned long long segment, bus;
acpi_status status;
@@ -614,7 +611,7 @@ static int acpi_pci_root_add(struct acpi
pci_enable_bridges(root->bus);
pci_bus_add_devices(root->bus);
- return 0;
+ return 1;
out_del_root:
mutex_lock(&acpi_pci_root_lock);
@@ -627,7 +624,7 @@ end:
return result;
}
-static int acpi_pci_root_remove(struct acpi_device *device)
+static void acpi_pci_root_remove(struct acpi_device *device)
{
acpi_status status;
acpi_handle handle;
@@ -655,19 +652,14 @@ static int acpi_pci_root_remove(struct a
list_del(&root->node);
mutex_unlock(&acpi_pci_root_lock);
kfree(root);
- return 0;
}
-int __init acpi_pci_root_init(void)
+void __init acpi_pci_root_init(void)
{
acpi_hest_init();
- if (acpi_pci_disabled)
- return 0;
-
- pci_acpi_crs_quirks();
- if (acpi_bus_register_driver(&acpi_pci_root_driver) < 0)
- return -ENODEV;
-
- return 0;
+ if (!acpi_pci_disabled) {
+ pci_acpi_crs_quirks();
+ acpi_scan_add_handler(&pci_root_handler);
+ }
}
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -25,6 +25,7 @@
int init_acpi_device_notify(void);
int acpi_scan_init(void);
+void acpi_pci_root_init(void);
int acpi_sysfs_init(void);
void acpi_csrt_init(void);
@@ -86,7 +87,6 @@ struct acpi_ec {
extern struct acpi_ec *first_ec;
-int acpi_pci_root_init(void);
int acpi_ec_init(void);
int acpi_ec_ecdt_probe(void);
int acpi_boot_ec_enable(void);
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 3/4] ACPI / PCI: Make PCI IRQ link driver use struct acpi_scan_handler
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
2013-01-28 12:59 ` [PATCH 1/4] ACPI / scan: Introduce struct acpi_scan_handler Rafael J. Wysocki
2013-01-28 13:00 ` [PATCH 2/4] ACPI / PCI: Make PCI root driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-01-28 13:00 ` Rafael J. Wysocki
2013-01-28 13:01 ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
` (4 subsequent siblings)
7 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 13:00 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Make the ACPI PCI IRQ link driver use struct acpi_scan_handler
for representing the object used to set up ACPI interrupt links and
to remove data structures used for this purpose before unregistering
the corresponding ACPI device nodes.
This simplifies the code slightly and reduces the kernel's memory
footprint by avoiding the registration of a struct device_driver
object with the driver core and creation of its sysfs directory
which is unnecessary.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/internal.h | 1 +
drivers/acpi/pci_link.c | 47 ++++++++++++++---------------------------------
drivers/acpi/scan.c | 1 +
3 files changed, 16 insertions(+), 33 deletions(-)
Index: test/drivers/acpi/pci_link.c
===================================================================
--- test.orig/drivers/acpi/pci_link.c
+++ test/drivers/acpi/pci_link.c
@@ -53,23 +53,19 @@ ACPI_MODULE_NAME("pci_link");
#define ACPI_PCI_LINK_FILE_STATUS "state"
#define ACPI_PCI_LINK_MAX_POSSIBLE 16
-static int acpi_pci_link_add(struct acpi_device *device);
-static int acpi_pci_link_remove(struct acpi_device *device);
+static int acpi_pci_link_add(struct acpi_device *device,
+ const struct acpi_device_id *not_used);
+static void acpi_pci_link_remove(struct acpi_device *device);
static const struct acpi_device_id link_device_ids[] = {
{"PNP0C0F", 0},
{"", 0},
};
-MODULE_DEVICE_TABLE(acpi, link_device_ids);
-static struct acpi_driver acpi_pci_link_driver = {
- .name = "pci_link",
- .class = ACPI_PCI_LINK_CLASS,
+static struct acpi_scan_handler pci_link_handler = {
.ids = link_device_ids,
- .ops = {
- .add = acpi_pci_link_add,
- .remove = acpi_pci_link_remove,
- },
+ .attach = acpi_pci_link_add,
+ .detach = acpi_pci_link_remove,
};
/*
@@ -692,7 +688,8 @@ int acpi_pci_link_free_irq(acpi_handle h
Driver Interface
-------------------------------------------------------------------------- */
-static int acpi_pci_link_add(struct acpi_device *device)
+static int acpi_pci_link_add(struct acpi_device *device,
+ const struct acpi_device_id *not_used)
{
int result;
struct acpi_pci_link *link;
@@ -746,7 +743,7 @@ static int acpi_pci_link_add(struct acpi
if (result)
kfree(link);
- return result;
+ return result < 0 ? result : 1;
}
static int acpi_pci_link_resume(struct acpi_pci_link *link)
@@ -766,7 +763,7 @@ static void irqrouter_resume(void)
}
}
-static int acpi_pci_link_remove(struct acpi_device *device)
+static void acpi_pci_link_remove(struct acpi_device *device)
{
struct acpi_pci_link *link;
@@ -777,7 +774,6 @@ static int acpi_pci_link_remove(struct a
mutex_unlock(&acpi_link_lock);
kfree(link);
- return 0;
}
/*
@@ -874,20 +870,10 @@ static struct syscore_ops irqrouter_sysc
.resume = irqrouter_resume,
};
-static int __init irqrouter_init_ops(void)
-{
- if (!acpi_disabled && !acpi_noirq)
- register_syscore_ops(&irqrouter_syscore_ops);
-
- return 0;
-}
-
-device_initcall(irqrouter_init_ops);
-
-static int __init acpi_pci_link_init(void)
+void __init acpi_pci_link_init(void)
{
if (acpi_noirq)
- return 0;
+ return;
if (acpi_irq_balance == -1) {
/* no command line switch: enable balancing in IOAPIC mode */
@@ -896,11 +882,6 @@ static int __init acpi_pci_link_init(voi
else
acpi_irq_balance = 0;
}
-
- if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0)
- return -ENODEV;
-
- return 0;
+ register_syscore_ops(&irqrouter_syscore_ops);
+ acpi_scan_add_handler(&pci_link_handler);
}
-
-subsys_initcall(acpi_pci_link_init);
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -26,6 +26,7 @@
int init_acpi_device_notify(void);
int acpi_scan_init(void);
void acpi_pci_root_init(void);
+void acpi_pci_link_init(void);
int acpi_sysfs_init(void);
void acpi_csrt_init(void);
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1774,6 +1774,7 @@ int __init acpi_scan_init(void)
}
acpi_pci_root_init();
+ acpi_pci_link_init();
acpi_csrt_init();
/*
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
` (2 preceding siblings ...)
2013-01-28 13:00 ` [PATCH 3/4] ACPI / PCI: Make PCI IRQ link " Rafael J. Wysocki
@ 2013-01-28 13:01 ` Rafael J. Wysocki
2013-01-29 2:20 ` Yasuaki Ishimatsu
` (2 more replies)
2013-01-28 21:54 ` [PATCH 0/4] ACPI scan handlers Yinghai Lu
` (3 subsequent siblings)
7 siblings, 3 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-28 13:01 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Currently, the ACPI namespace scanning code creates platform device
objects for ACPI device nodes whose IDs match the contents of the
acpi_platform_device_ids[] table. However, this adds a superfluous
special case into acpi_bus_device_attach() and makes it more
difficult to follow than it has to be. It also will make it more
difficult to implement removal code for those platform device objects
in the future.
For the above reasons, introduce a struct acpi_scan_handler object
for creating platform devices and move the code related to that from
acpi_bus_device_attach() to the .attach() callback of that object.
Also move the acpi_platform_device_ids[] table to acpi_platform.c.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/acpi_platform.c | 55 +++++++++++++++++++++++++++++++++++--------
drivers/acpi/internal.h | 7 -----
drivers/acpi/scan.c | 30 -----------------------
3 files changed, 47 insertions(+), 45 deletions(-)
Index: test/drivers/acpi/acpi_platform.c
===================================================================
--- test.orig/drivers/acpi/acpi_platform.c
+++ test/drivers/acpi/acpi_platform.c
@@ -22,6 +22,30 @@
ACPI_MODULE_NAME("platform");
+/* Flags for acpi_create_platform_device */
+#define ACPI_PLATFORM_CLK BIT(0)
+
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+ { "PNP0D40" },
+
+ /* Haswell LPSS devices */
+ { "INT33C0", ACPI_PLATFORM_CLK },
+ { "INT33C1", ACPI_PLATFORM_CLK },
+ { "INT33C2", ACPI_PLATFORM_CLK },
+ { "INT33C3", ACPI_PLATFORM_CLK },
+ { "INT33C4", ACPI_PLATFORM_CLK },
+ { "INT33C5", ACPI_PLATFORM_CLK },
+ { "INT33C6", ACPI_PLATFORM_CLK },
+ { "INT33C7", ACPI_PLATFORM_CLK },
+
+ { }
+};
+
static int acpi_create_platform_clks(struct acpi_device *adev)
{
static struct platform_device *pdev;
@@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
/**
* acpi_create_platform_device - Create platform device for ACPI device node
* @adev: ACPI device node to create a platform device for.
- * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
- * devices.
+ * @id: ACPI device ID used to match @adev.
*
* Check if the given @adev can be represented as a platform device and, if
* that's the case, create and register a platform device, populate its common
@@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
*
* Name of the platform device will be the same as @adev's.
*/
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
- unsigned long flags)
+static int acpi_create_platform_device(struct acpi_device *adev,
+ const struct acpi_device_id *id)
{
+ unsigned long flags = id->driver_data;
struct platform_device *pdev = NULL;
struct acpi_device *acpi_parent;
struct platform_device_info pdevinfo;
@@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
struct resource *resources;
int count;
- if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
+ if (flags & ACPI_PLATFORM_CLK) {
+ int ret = acpi_create_platform_clks(adev);
dev_err(&adev->dev, "failed to create clocks\n");
- return NULL;
+ return ret;
}
/* If the ACPI node already has a physical device attached, skip it. */
if (adev->physical_node_count)
- return NULL;
+ return 0;
INIT_LIST_HEAD(&resource_list);
count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (count <= 0)
- return NULL;
+ return 0;
resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
if (!resources) {
dev_err(&adev->dev, "No memory for resources\n");
acpi_dev_free_resource_list(&resource_list);
- return NULL;
+ return -ENOMEM;
}
count = 0;
list_for_each_entry(rentry, &resource_list, node)
@@ -123,5 +148,15 @@ struct platform_device *acpi_create_plat
}
kfree(resources);
- return pdev;
+ return 1;
+}
+
+static struct acpi_scan_handler platform_handler = {
+ .ids = acpi_platform_device_ids,
+ .attach = acpi_create_platform_device,
+};
+
+void __init acpi_platform_init(void)
+{
+ acpi_scan_add_handler(&platform_handler);
}
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
int acpi_scan_init(void);
void acpi_pci_root_init(void);
void acpi_pci_link_init(void);
+void acpi_platform_init(void);
int acpi_sysfs_init(void);
void acpi_csrt_init(void);
@@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
-------------------------------------------------------------------------- */
struct platform_device;
-/* Flags for acpi_create_platform_device */
-#define ACPI_PLATFORM_CLK BIT(0)
-
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
- unsigned long flags);
-
#endif /* _ACPI_INTERNAL_H_ */
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
static const char *dummy_hid = "device";
-/*
- * The following ACPI IDs are known to be suitable for representing as
- * platform devices.
- */
-static const struct acpi_device_id acpi_platform_device_ids[] = {
-
- { "PNP0D40" },
-
- /* Haswell LPSS devices */
- { "INT33C0", ACPI_PLATFORM_CLK },
- { "INT33C1", ACPI_PLATFORM_CLK },
- { "INT33C2", ACPI_PLATFORM_CLK },
- { "INT33C3", ACPI_PLATFORM_CLK },
- { "INT33C4", ACPI_PLATFORM_CLK },
- { "INT33C5", ACPI_PLATFORM_CLK },
- { "INT33C6", ACPI_PLATFORM_CLK },
- { "INT33C7", ACPI_PLATFORM_CLK },
-
- { }
-};
-
static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
static DEFINE_MUTEX(acpi_scan_lock);
@@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
void *not_used, void **ret_not_used)
{
- const struct acpi_device_id *id;
struct acpi_device *device;
unsigned long long sta_not_used;
int ret;
@@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
if (acpi_bus_get_device(handle, &device))
return AE_CTRL_DEPTH;
- id = __acpi_match_device(device, acpi_platform_device_ids);
- if (id) {
- /* This is a known good platform device. */
- acpi_create_platform_device(device, id->driver_data);
- return AE_OK;
- }
-
ret = acpi_scan_attach_handler(device);
if (ret)
return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
@@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
acpi_pci_root_init();
acpi_pci_link_init();
+ acpi_platform_init();
acpi_csrt_init();
/*
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-28 13:01 ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
@ 2013-01-29 2:20 ` Yasuaki Ishimatsu
2013-01-29 11:36 ` Rafael J. Wysocki
2013-01-29 7:35 ` [PATCH " Mika Westerberg
2013-01-29 8:05 ` Mika Westerberg
2 siblings, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29 2:20 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
Hi Rafael,
2013/01/28 22:01, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Currently, the ACPI namespace scanning code creates platform device
> objects for ACPI device nodes whose IDs match the contents of the
> acpi_platform_device_ids[] table. However, this adds a superfluous
> special case into acpi_bus_device_attach() and makes it more
> difficult to follow than it has to be. It also will make it more
> difficult to implement removal code for those platform device objects
> in the future.
>
> For the above reasons, introduce a struct acpi_scan_handler object
> for creating platform devices and move the code related to that from
> acpi_bus_device_attach() to the .attach() callback of that object.
> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
> drivers/acpi/acpi_platform.c | 55 +++++++++++++++++++++++++++++++++++--------
> drivers/acpi/internal.h | 7 -----
> drivers/acpi/scan.c | 30 -----------------------
> 3 files changed, 47 insertions(+), 45 deletions(-)
>
> Index: test/drivers/acpi/acpi_platform.c
> ===================================================================
> --- test.orig/drivers/acpi/acpi_platform.c
> +++ test/drivers/acpi/acpi_platform.c
> @@ -22,6 +22,30 @@
>
> ACPI_MODULE_NAME("platform");
>
> +/* Flags for acpi_create_platform_device */
> +#define ACPI_PLATFORM_CLK BIT(0)
> +
> +/*
> + * The following ACPI IDs are known to be suitable for representing as
> + * platform devices.
> + */
> +static const struct acpi_device_id acpi_platform_device_ids[] = {
> +
> + { "PNP0D40" },
> +
> + /* Haswell LPSS devices */
> + { "INT33C0", ACPI_PLATFORM_CLK },
> + { "INT33C1", ACPI_PLATFORM_CLK },
> + { "INT33C2", ACPI_PLATFORM_CLK },
> + { "INT33C3", ACPI_PLATFORM_CLK },
> + { "INT33C4", ACPI_PLATFORM_CLK },
> + { "INT33C5", ACPI_PLATFORM_CLK },
> + { "INT33C6", ACPI_PLATFORM_CLK },
> + { "INT33C7", ACPI_PLATFORM_CLK },
> +
> + { }
> +};
> +
> static int acpi_create_platform_clks(struct acpi_device *adev)
> {
> static struct platform_device *pdev;
> @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
> /**
> * acpi_create_platform_device - Create platform device for ACPI device node
> * @adev: ACPI device node to create a platform device for.
> - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> - * devices.
> + * @id: ACPI device ID used to match @adev.
> *
> * Check if the given @adev can be represented as a platform device and, if
> * that's the case, create and register a platform device, populate its common
> @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
> *
> * Name of the platform device will be the same as @adev's.
> */
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> - unsigned long flags)
> +static int acpi_create_platform_device(struct acpi_device *adev,
> + const struct acpi_device_id *id)
> {
> + unsigned long flags = id->driver_data;
> struct platform_device *pdev = NULL;
> struct acpi_device *acpi_parent;
> struct platform_device_info pdevinfo;
> @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
> struct resource *resources;
> int count;
>
> - if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> + if (flags & ACPI_PLATFORM_CLK) {
> + int ret = acpi_create_platform_clks(adev);
> dev_err(&adev->dev, "failed to create clocks\n");
> - return NULL;
> + return ret;
> }
If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
always retruns with dev_err() messages. Why?
Thanks,
Yasuaki Ishimatsu
>
> /* If the ACPI node already has a physical device attached, skip it. */
> if (adev->physical_node_count)
> - return NULL;
> + return 0;
>
> INIT_LIST_HEAD(&resource_list);
> count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
> if (count <= 0)
> - return NULL;
> + return 0;
>
> resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
> if (!resources) {
> dev_err(&adev->dev, "No memory for resources\n");
> acpi_dev_free_resource_list(&resource_list);
> - return NULL;
> + return -ENOMEM;
> }
> count = 0;
> list_for_each_entry(rentry, &resource_list, node)
> @@ -123,5 +148,15 @@ struct platform_device *acpi_create_plat
> }
>
> kfree(resources);
> - return pdev;
> + return 1;
> +}
> +
> +static struct acpi_scan_handler platform_handler = {
> + .ids = acpi_platform_device_ids,
> + .attach = acpi_create_platform_device,
> +};
> +
> +void __init acpi_platform_init(void)
> +{
> + acpi_scan_add_handler(&platform_handler);
> }
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
> int acpi_scan_init(void);
> void acpi_pci_root_init(void);
> void acpi_pci_link_init(void);
> +void acpi_platform_init(void);
> int acpi_sysfs_init(void);
> void acpi_csrt_init(void);
>
> @@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
> -------------------------------------------------------------------------- */
> struct platform_device;
>
> -/* Flags for acpi_create_platform_device */
> -#define ACPI_PLATFORM_CLK BIT(0)
> -
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> - unsigned long flags);
> -
> #endif /* _ACPI_INTERNAL_H_ */
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
>
> static const char *dummy_hid = "device";
>
> -/*
> - * The following ACPI IDs are known to be suitable for representing as
> - * platform devices.
> - */
> -static const struct acpi_device_id acpi_platform_device_ids[] = {
> -
> - { "PNP0D40" },
> -
> - /* Haswell LPSS devices */
> - { "INT33C0", ACPI_PLATFORM_CLK },
> - { "INT33C1", ACPI_PLATFORM_CLK },
> - { "INT33C2", ACPI_PLATFORM_CLK },
> - { "INT33C3", ACPI_PLATFORM_CLK },
> - { "INT33C4", ACPI_PLATFORM_CLK },
> - { "INT33C5", ACPI_PLATFORM_CLK },
> - { "INT33C6", ACPI_PLATFORM_CLK },
> - { "INT33C7", ACPI_PLATFORM_CLK },
> -
> - { }
> -};
> -
> static LIST_HEAD(acpi_device_list);
> static LIST_HEAD(acpi_bus_id_list);
> static DEFINE_MUTEX(acpi_scan_lock);
> @@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
> static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
> void *not_used, void **ret_not_used)
> {
> - const struct acpi_device_id *id;
> struct acpi_device *device;
> unsigned long long sta_not_used;
> int ret;
> @@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
> if (acpi_bus_get_device(handle, &device))
> return AE_CTRL_DEPTH;
>
> - id = __acpi_match_device(device, acpi_platform_device_ids);
> - if (id) {
> - /* This is a known good platform device. */
> - acpi_create_platform_device(device, id->driver_data);
> - return AE_OK;
> - }
> -
> ret = acpi_scan_attach_handler(device);
> if (ret)
> return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
> @@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
>
> acpi_pci_root_init();
> acpi_pci_link_init();
> + acpi_platform_init();
> acpi_csrt_init();
>
> /*
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-29 2:20 ` Yasuaki Ishimatsu
@ 2013-01-29 11:36 ` Rafael J. Wysocki
2013-01-29 12:30 ` [Update][PATCH " Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 11:36 UTC (permalink / raw)
To: Yasuaki Ishimatsu
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
On Tuesday, January 29, 2013 11:20:44 AM Yasuaki Ishimatsu wrote:
> Hi Rafael,
>
> 2013/01/28 22:01, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Currently, the ACPI namespace scanning code creates platform device
> > objects for ACPI device nodes whose IDs match the contents of the
> > acpi_platform_device_ids[] table. However, this adds a superfluous
> > special case into acpi_bus_device_attach() and makes it more
> > difficult to follow than it has to be. It also will make it more
> > difficult to implement removal code for those platform device objects
> > in the future.
> >
> > For the above reasons, introduce a struct acpi_scan_handler object
> > for creating platform devices and move the code related to that from
> > acpi_bus_device_attach() to the .attach() callback of that object.
> > Also move the acpi_platform_device_ids[] table to acpi_platform.c.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> > drivers/acpi/acpi_platform.c | 55 +++++++++++++++++++++++++++++++++++--------
> > drivers/acpi/internal.h | 7 -----
> > drivers/acpi/scan.c | 30 -----------------------
> > 3 files changed, 47 insertions(+), 45 deletions(-)
> >
> > Index: test/drivers/acpi/acpi_platform.c
> > ===================================================================
> > --- test.orig/drivers/acpi/acpi_platform.c
> > +++ test/drivers/acpi/acpi_platform.c
> > @@ -22,6 +22,30 @@
> >
> > ACPI_MODULE_NAME("platform");
> >
> > +/* Flags for acpi_create_platform_device */
> > +#define ACPI_PLATFORM_CLK BIT(0)
> > +
> > +/*
> > + * The following ACPI IDs are known to be suitable for representing as
> > + * platform devices.
> > + */
> > +static const struct acpi_device_id acpi_platform_device_ids[] = {
> > +
> > + { "PNP0D40" },
> > +
> > + /* Haswell LPSS devices */
> > + { "INT33C0", ACPI_PLATFORM_CLK },
> > + { "INT33C1", ACPI_PLATFORM_CLK },
> > + { "INT33C2", ACPI_PLATFORM_CLK },
> > + { "INT33C3", ACPI_PLATFORM_CLK },
> > + { "INT33C4", ACPI_PLATFORM_CLK },
> > + { "INT33C5", ACPI_PLATFORM_CLK },
> > + { "INT33C6", ACPI_PLATFORM_CLK },
> > + { "INT33C7", ACPI_PLATFORM_CLK },
> > +
> > + { }
> > +};
> > +
> > static int acpi_create_platform_clks(struct acpi_device *adev)
> > {
> > static struct platform_device *pdev;
> > @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
> > /**
> > * acpi_create_platform_device - Create platform device for ACPI device node
> > * @adev: ACPI device node to create a platform device for.
> > - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> > - * devices.
> > + * @id: ACPI device ID used to match @adev.
> > *
> > * Check if the given @adev can be represented as a platform device and, if
> > * that's the case, create and register a platform device, populate its common
> > @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
> > *
> > * Name of the platform device will be the same as @adev's.
> > */
> > -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> > - unsigned long flags)
> > +static int acpi_create_platform_device(struct acpi_device *adev,
> > + const struct acpi_device_id *id)
> > {
> > + unsigned long flags = id->driver_data;
> > struct platform_device *pdev = NULL;
> > struct acpi_device *acpi_parent;
> > struct platform_device_info pdevinfo;
> > @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
> > struct resource *resources;
> > int count;
> >
>
> > - if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> > + if (flags & ACPI_PLATFORM_CLK) {
> > + int ret = acpi_create_platform_clks(adev);
> > dev_err(&adev->dev, "failed to create clocks\n");
> > - return NULL;
> > + return ret;
> > }
>
> If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
> always retruns with dev_err() messages. Why?
Ah. By mistake. :-)
Thanks for poiting this out!
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [Update][PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-29 11:36 ` Rafael J. Wysocki
@ 2013-01-29 12:30 ` Rafael J. Wysocki
2013-01-29 23:51 ` Yasuaki Ishimatsu
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 12:30 UTC (permalink / raw)
To: Yasuaki Ishimatsu
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
On Tuesday, January 29, 2013 12:36:35 PM Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 11:20:44 AM Yasuaki Ishimatsu wrote:
> > Hi Rafael,
> >
> > 2013/01/28 22:01, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > Currently, the ACPI namespace scanning code creates platform device
> > > objects for ACPI device nodes whose IDs match the contents of the
> > > acpi_platform_device_ids[] table. However, this adds a superfluous
> > > special case into acpi_bus_device_attach() and makes it more
> > > difficult to follow than it has to be. It also will make it more
> > > difficult to implement removal code for those platform device objects
> > > in the future.
> > >
> > > For the above reasons, introduce a struct acpi_scan_handler object
> > > for creating platform devices and move the code related to that from
> > > acpi_bus_device_attach() to the .attach() callback of that object.
> > > Also move the acpi_platform_device_ids[] table to acpi_platform.c.
> > >
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > ---
> > > drivers/acpi/acpi_platform.c | 55 +++++++++++++++++++++++++++++++++++--------
> > > drivers/acpi/internal.h | 7 -----
> > > drivers/acpi/scan.c | 30 -----------------------
> > > 3 files changed, 47 insertions(+), 45 deletions(-)
> > >
> > > Index: test/drivers/acpi/acpi_platform.c
> > > ===================================================================
> > > --- test.orig/drivers/acpi/acpi_platform.c
> > > +++ test/drivers/acpi/acpi_platform.c
> > > @@ -22,6 +22,30 @@
> > >
> > > ACPI_MODULE_NAME("platform");
> > >
> > > +/* Flags for acpi_create_platform_device */
> > > +#define ACPI_PLATFORM_CLK BIT(0)
> > > +
> > > +/*
> > > + * The following ACPI IDs are known to be suitable for representing as
> > > + * platform devices.
> > > + */
> > > +static const struct acpi_device_id acpi_platform_device_ids[] = {
> > > +
> > > + { "PNP0D40" },
> > > +
> > > + /* Haswell LPSS devices */
> > > + { "INT33C0", ACPI_PLATFORM_CLK },
> > > + { "INT33C1", ACPI_PLATFORM_CLK },
> > > + { "INT33C2", ACPI_PLATFORM_CLK },
> > > + { "INT33C3", ACPI_PLATFORM_CLK },
> > > + { "INT33C4", ACPI_PLATFORM_CLK },
> > > + { "INT33C5", ACPI_PLATFORM_CLK },
> > > + { "INT33C6", ACPI_PLATFORM_CLK },
> > > + { "INT33C7", ACPI_PLATFORM_CLK },
> > > +
> > > + { }
> > > +};
> > > +
> > > static int acpi_create_platform_clks(struct acpi_device *adev)
> > > {
> > > static struct platform_device *pdev;
> > > @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
> > > /**
> > > * acpi_create_platform_device - Create platform device for ACPI device node
> > > * @adev: ACPI device node to create a platform device for.
> > > - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> > > - * devices.
> > > + * @id: ACPI device ID used to match @adev.
> > > *
> > > * Check if the given @adev can be represented as a platform device and, if
> > > * that's the case, create and register a platform device, populate its common
> > > @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
> > > *
> > > * Name of the platform device will be the same as @adev's.
> > > */
> > > -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> > > - unsigned long flags)
> > > +static int acpi_create_platform_device(struct acpi_device *adev,
> > > + const struct acpi_device_id *id)
> > > {
> > > + unsigned long flags = id->driver_data;
> > > struct platform_device *pdev = NULL;
> > > struct acpi_device *acpi_parent;
> > > struct platform_device_info pdevinfo;
> > > @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
> > > struct resource *resources;
> > > int count;
> > >
> >
> > > - if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> > > + if (flags & ACPI_PLATFORM_CLK) {
> > > + int ret = acpi_create_platform_clks(adev);
> > > dev_err(&adev->dev, "failed to create clocks\n");
> > > - return NULL;
> > > + return ret;
> > > }
> >
> > If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
> > always retruns with dev_err() messages. Why?
>
> Ah. By mistake. :-)
>
> Thanks for poiting this out!
Updated patch is appended.
Thanks,
Rafael
---
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Subject: ACPI / platform: Use struct acpi_scan_handler for creating devices
Currently, the ACPI namespace scanning code creates platform device
objects for ACPI device nodes whose IDs match the contents of the
acpi_platform_device_ids[] table. However, this adds a superfluous
special case into acpi_bus_device_attach() and makes it more
difficult to follow than it has to be. It also will make it more
difficult to implement removal code for those platform device objects
in the future.
For the above reasons, introduce a struct acpi_scan_handler object
for creating platform devices and move the code related to that from
acpi_bus_device_attach() to the .attach() callback of that object.
Also move the acpi_platform_device_ids[] table to acpi_platform.c.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/acpi_platform.c | 59 ++++++++++++++++++++++++++++++++++---------
drivers/acpi/internal.h | 7 -----
drivers/acpi/scan.c | 30 ---------------------
3 files changed, 50 insertions(+), 46 deletions(-)
Index: test/drivers/acpi/acpi_platform.c
===================================================================
--- test.orig/drivers/acpi/acpi_platform.c
+++ test/drivers/acpi/acpi_platform.c
@@ -22,6 +22,30 @@
ACPI_MODULE_NAME("platform");
+/* Flags for acpi_create_platform_device */
+#define ACPI_PLATFORM_CLK BIT(0)
+
+/*
+ * The following ACPI IDs are known to be suitable for representing as
+ * platform devices.
+ */
+static const struct acpi_device_id acpi_platform_device_ids[] = {
+
+ { "PNP0D40" },
+
+ /* Haswell LPSS devices */
+ { "INT33C0", ACPI_PLATFORM_CLK },
+ { "INT33C1", ACPI_PLATFORM_CLK },
+ { "INT33C2", ACPI_PLATFORM_CLK },
+ { "INT33C3", ACPI_PLATFORM_CLK },
+ { "INT33C4", ACPI_PLATFORM_CLK },
+ { "INT33C5", ACPI_PLATFORM_CLK },
+ { "INT33C6", ACPI_PLATFORM_CLK },
+ { "INT33C7", ACPI_PLATFORM_CLK },
+
+ { }
+};
+
static int acpi_create_platform_clks(struct acpi_device *adev)
{
static struct platform_device *pdev;
@@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
/**
* acpi_create_platform_device - Create platform device for ACPI device node
* @adev: ACPI device node to create a platform device for.
- * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
- * devices.
+ * @id: ACPI device ID used to match @adev.
*
* Check if the given @adev can be represented as a platform device and, if
* that's the case, create and register a platform device, populate its common
@@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
*
* Name of the platform device will be the same as @adev's.
*/
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
- unsigned long flags)
+static int acpi_create_platform_device(struct acpi_device *adev,
+ const struct acpi_device_id *id)
{
+ unsigned long flags = id->driver_data;
struct platform_device *pdev = NULL;
struct acpi_device *acpi_parent;
struct platform_device_info pdevinfo;
@@ -59,25 +83,28 @@ struct platform_device *acpi_create_plat
struct resource *resources;
int count;
- if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
- dev_err(&adev->dev, "failed to create clocks\n");
- return NULL;
+ if (flags & ACPI_PLATFORM_CLK) {
+ int ret = acpi_create_platform_clks(adev);
+ if (ret) {
+ dev_err(&adev->dev, "failed to create clocks\n");
+ return ret;
+ }
}
/* If the ACPI node already has a physical device attached, skip it. */
if (adev->physical_node_count)
- return NULL;
+ return 0;
INIT_LIST_HEAD(&resource_list);
count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
if (count <= 0)
- return NULL;
+ return 0;
resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
if (!resources) {
dev_err(&adev->dev, "No memory for resources\n");
acpi_dev_free_resource_list(&resource_list);
- return NULL;
+ return -ENOMEM;
}
count = 0;
list_for_each_entry(rentry, &resource_list, node)
@@ -123,5 +150,15 @@ struct platform_device *acpi_create_plat
}
kfree(resources);
- return pdev;
+ return 1;
+}
+
+static struct acpi_scan_handler platform_handler = {
+ .ids = acpi_platform_device_ids,
+ .attach = acpi_create_platform_device,
+};
+
+void __init acpi_platform_init(void)
+{
+ acpi_scan_add_handler(&platform_handler);
}
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
int acpi_scan_init(void);
void acpi_pci_root_init(void);
void acpi_pci_link_init(void);
+void acpi_platform_init(void);
int acpi_sysfs_init(void);
void acpi_csrt_init(void);
@@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
-------------------------------------------------------------------------- */
struct platform_device;
-/* Flags for acpi_create_platform_device */
-#define ACPI_PLATFORM_CLK BIT(0)
-
-struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
- unsigned long flags);
-
#endif /* _ACPI_INTERNAL_H_ */
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
static const char *dummy_hid = "device";
-/*
- * The following ACPI IDs are known to be suitable for representing as
- * platform devices.
- */
-static const struct acpi_device_id acpi_platform_device_ids[] = {
-
- { "PNP0D40" },
-
- /* Haswell LPSS devices */
- { "INT33C0", ACPI_PLATFORM_CLK },
- { "INT33C1", ACPI_PLATFORM_CLK },
- { "INT33C2", ACPI_PLATFORM_CLK },
- { "INT33C3", ACPI_PLATFORM_CLK },
- { "INT33C4", ACPI_PLATFORM_CLK },
- { "INT33C5", ACPI_PLATFORM_CLK },
- { "INT33C6", ACPI_PLATFORM_CLK },
- { "INT33C7", ACPI_PLATFORM_CLK },
-
- { }
-};
-
static LIST_HEAD(acpi_device_list);
static LIST_HEAD(acpi_bus_id_list);
static DEFINE_MUTEX(acpi_scan_lock);
@@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
void *not_used, void **ret_not_used)
{
- const struct acpi_device_id *id;
struct acpi_device *device;
unsigned long long sta_not_used;
int ret;
@@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
if (acpi_bus_get_device(handle, &device))
return AE_CTRL_DEPTH;
- id = __acpi_match_device(device, acpi_platform_device_ids);
- if (id) {
- /* This is a known good platform device. */
- acpi_create_platform_device(device, id->driver_data);
- return AE_OK;
- }
-
ret = acpi_scan_attach_handler(device);
if (ret)
return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
@@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
acpi_pci_root_init();
acpi_pci_link_init();
+ acpi_platform_init();
acpi_csrt_init();
/*
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [Update][PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-29 12:30 ` [Update][PATCH " Rafael J. Wysocki
@ 2013-01-29 23:51 ` Yasuaki Ishimatsu
0 siblings, 0 replies; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-01-29 23:51 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
2013/01/29 21:30, Rafael J. Wysocki wrote:
> On Tuesday, January 29, 2013 12:36:35 PM Rafael J. Wysocki wrote:
>> On Tuesday, January 29, 2013 11:20:44 AM Yasuaki Ishimatsu wrote:
>>> Hi Rafael,
>>>
>>> 2013/01/28 22:01, Rafael J. Wysocki wrote:
>>>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>>>
>>>> Currently, the ACPI namespace scanning code creates platform device
>>>> objects for ACPI device nodes whose IDs match the contents of the
>>>> acpi_platform_device_ids[] table. However, this adds a superfluous
>>>> special case into acpi_bus_device_attach() and makes it more
>>>> difficult to follow than it has to be. It also will make it more
>>>> difficult to implement removal code for those platform device objects
>>>> in the future.
>>>>
>>>> For the above reasons, introduce a struct acpi_scan_handler object
>>>> for creating platform devices and move the code related to that from
>>>> acpi_bus_device_attach() to the .attach() callback of that object.
>>>> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
>>>>
>>>> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>>> ---
>>>> drivers/acpi/acpi_platform.c | 55 +++++++++++++++++++++++++++++++++++--------
>>>> drivers/acpi/internal.h | 7 -----
>>>> drivers/acpi/scan.c | 30 -----------------------
>>>> 3 files changed, 47 insertions(+), 45 deletions(-)
>>>>
>>>> Index: test/drivers/acpi/acpi_platform.c
>>>> ===================================================================
>>>> --- test.orig/drivers/acpi/acpi_platform.c
>>>> +++ test/drivers/acpi/acpi_platform.c
>>>> @@ -22,6 +22,30 @@
>>>>
>>>> ACPI_MODULE_NAME("platform");
>>>>
>>>> +/* Flags for acpi_create_platform_device */
>>>> +#define ACPI_PLATFORM_CLK BIT(0)
>>>> +
>>>> +/*
>>>> + * The following ACPI IDs are known to be suitable for representing as
>>>> + * platform devices.
>>>> + */
>>>> +static const struct acpi_device_id acpi_platform_device_ids[] = {
>>>> +
>>>> + { "PNP0D40" },
>>>> +
>>>> + /* Haswell LPSS devices */
>>>> + { "INT33C0", ACPI_PLATFORM_CLK },
>>>> + { "INT33C1", ACPI_PLATFORM_CLK },
>>>> + { "INT33C2", ACPI_PLATFORM_CLK },
>>>> + { "INT33C3", ACPI_PLATFORM_CLK },
>>>> + { "INT33C4", ACPI_PLATFORM_CLK },
>>>> + { "INT33C5", ACPI_PLATFORM_CLK },
>>>> + { "INT33C6", ACPI_PLATFORM_CLK },
>>>> + { "INT33C7", ACPI_PLATFORM_CLK },
>>>> +
>>>> + { }
>>>> +};
>>>> +
>>>> static int acpi_create_platform_clks(struct acpi_device *adev)
>>>> {
>>>> static struct platform_device *pdev;
>>>> @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
>>>> /**
>>>> * acpi_create_platform_device - Create platform device for ACPI device node
>>>> * @adev: ACPI device node to create a platform device for.
>>>> - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
>>>> - * devices.
>>>> + * @id: ACPI device ID used to match @adev.
>>>> *
>>>> * Check if the given @adev can be represented as a platform device and, if
>>>> * that's the case, create and register a platform device, populate its common
>>>> @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
>>>> *
>>>> * Name of the platform device will be the same as @adev's.
>>>> */
>>>> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
>>>> - unsigned long flags)
>>>> +static int acpi_create_platform_device(struct acpi_device *adev,
>>>> + const struct acpi_device_id *id)
>>>> {
>>>> + unsigned long flags = id->driver_data;
>>>> struct platform_device *pdev = NULL;
>>>> struct acpi_device *acpi_parent;
>>>> struct platform_device_info pdevinfo;
>>>> @@ -59,25 +83,26 @@ struct platform_device *acpi_create_plat
>>>> struct resource *resources;
>>>> int count;
>>>>
>>>
>>>> - if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
>>>> + if (flags & ACPI_PLATFORM_CLK) {
>>>> + int ret = acpi_create_platform_clks(adev);
>>>> dev_err(&adev->dev, "failed to create clocks\n");
>>>> - return NULL;
>>>> + return ret;
>>>> }
>>>
>>> If (flag & ACPI_PLATFORM_CLK) is true, the acpi_create_platform_device()
>>> always retruns with dev_err() messages. Why?
>>
>> Ah. By mistake. :-)
>>
>> Thanks for poiting this out!
>
> Updated patch is appended.
>
> Thanks,
> Rafael
>
> ---
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Subject: ACPI / platform: Use struct acpi_scan_handler for creating devices
>
> Currently, the ACPI namespace scanning code creates platform device
> objects for ACPI device nodes whose IDs match the contents of the
> acpi_platform_device_ids[] table. However, this adds a superfluous
> special case into acpi_bus_device_attach() and makes it more
> difficult to follow than it has to be. It also will make it more
> difficult to implement removal code for those platform device objects
> in the future.
>
> For the above reasons, introduce a struct acpi_scan_handler object
> for creating platform devices and move the code related to that from
> acpi_bus_device_attach() to the .attach() callback of that object.
> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
> drivers/acpi/acpi_platform.c | 59 ++++++++++++++++++++++++++++++++++---------
> drivers/acpi/internal.h | 7 -----
> drivers/acpi/scan.c | 30 ---------------------
> 3 files changed, 50 insertions(+), 46 deletions(-)
>
> Index: test/drivers/acpi/acpi_platform.c
> ===================================================================
> --- test.orig/drivers/acpi/acpi_platform.c
> +++ test/drivers/acpi/acpi_platform.c
> @@ -22,6 +22,30 @@
>
> ACPI_MODULE_NAME("platform");
>
> +/* Flags for acpi_create_platform_device */
> +#define ACPI_PLATFORM_CLK BIT(0)
> +
> +/*
> + * The following ACPI IDs are known to be suitable for representing as
> + * platform devices.
> + */
> +static const struct acpi_device_id acpi_platform_device_ids[] = {
> +
> + { "PNP0D40" },
> +
> + /* Haswell LPSS devices */
> + { "INT33C0", ACPI_PLATFORM_CLK },
> + { "INT33C1", ACPI_PLATFORM_CLK },
> + { "INT33C2", ACPI_PLATFORM_CLK },
> + { "INT33C3", ACPI_PLATFORM_CLK },
> + { "INT33C4", ACPI_PLATFORM_CLK },
> + { "INT33C5", ACPI_PLATFORM_CLK },
> + { "INT33C6", ACPI_PLATFORM_CLK },
> + { "INT33C7", ACPI_PLATFORM_CLK },
> +
> + { }
> +};
> +
> static int acpi_create_platform_clks(struct acpi_device *adev)
> {
> static struct platform_device *pdev;
> @@ -39,8 +63,7 @@ static int acpi_create_platform_clks(str
> /**
> * acpi_create_platform_device - Create platform device for ACPI device node
> * @adev: ACPI device node to create a platform device for.
> - * @flags: ACPI_PLATFORM_* flags that affect the creation of the platform
> - * devices.
> + * @id: ACPI device ID used to match @adev.
> *
> * Check if the given @adev can be represented as a platform device and, if
> * that's the case, create and register a platform device, populate its common
> @@ -48,9 +71,10 @@ static int acpi_create_platform_clks(str
> *
> * Name of the platform device will be the same as @adev's.
> */
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> - unsigned long flags)
> +static int acpi_create_platform_device(struct acpi_device *adev,
> + const struct acpi_device_id *id)
> {
> + unsigned long flags = id->driver_data;
> struct platform_device *pdev = NULL;
> struct acpi_device *acpi_parent;
> struct platform_device_info pdevinfo;
> @@ -59,25 +83,28 @@ struct platform_device *acpi_create_plat
> struct resource *resources;
> int count;
>
> - if ((flags & ACPI_PLATFORM_CLK) && acpi_create_platform_clks(adev)) {
> - dev_err(&adev->dev, "failed to create clocks\n");
> - return NULL;
> + if (flags & ACPI_PLATFORM_CLK) {
> + int ret = acpi_create_platform_clks(adev);
> + if (ret) {
> + dev_err(&adev->dev, "failed to create clocks\n");
> + return ret;
> + }
> }
>
> /* If the ACPI node already has a physical device attached, skip it. */
> if (adev->physical_node_count)
> - return NULL;
> + return 0;
>
> INIT_LIST_HEAD(&resource_list);
> count = acpi_dev_get_resources(adev, &resource_list, NULL, NULL);
> if (count <= 0)
> - return NULL;
> + return 0;
>
> resources = kmalloc(count * sizeof(struct resource), GFP_KERNEL);
> if (!resources) {
> dev_err(&adev->dev, "No memory for resources\n");
> acpi_dev_free_resource_list(&resource_list);
> - return NULL;
> + return -ENOMEM;
> }
> count = 0;
> list_for_each_entry(rentry, &resource_list, node)
> @@ -123,5 +150,15 @@ struct platform_device *acpi_create_plat
> }
>
> kfree(resources);
> - return pdev;
> + return 1;
> +}
> +
> +static struct acpi_scan_handler platform_handler = {
> + .ids = acpi_platform_device_ids,
> + .attach = acpi_create_platform_device,
> +};
> +
> +void __init acpi_platform_init(void)
> +{
> + acpi_scan_add_handler(&platform_handler);
> }
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -27,6 +27,7 @@ int init_acpi_device_notify(void);
> int acpi_scan_init(void);
> void acpi_pci_root_init(void);
> void acpi_pci_link_init(void);
> +void acpi_platform_init(void);
> int acpi_sysfs_init(void);
> void acpi_csrt_init(void);
>
> @@ -119,10 +120,4 @@ static inline void suspend_nvs_restore(v
> -------------------------------------------------------------------------- */
> struct platform_device;
>
> -/* Flags for acpi_create_platform_device */
> -#define ACPI_PLATFORM_CLK BIT(0)
> -
> -struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
> - unsigned long flags);
> -
> #endif /* _ACPI_INTERNAL_H_ */
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -29,27 +29,6 @@ extern struct acpi_device *acpi_root;
>
> static const char *dummy_hid = "device";
>
> -/*
> - * The following ACPI IDs are known to be suitable for representing as
> - * platform devices.
> - */
> -static const struct acpi_device_id acpi_platform_device_ids[] = {
> -
> - { "PNP0D40" },
> -
> - /* Haswell LPSS devices */
> - { "INT33C0", ACPI_PLATFORM_CLK },
> - { "INT33C1", ACPI_PLATFORM_CLK },
> - { "INT33C2", ACPI_PLATFORM_CLK },
> - { "INT33C3", ACPI_PLATFORM_CLK },
> - { "INT33C4", ACPI_PLATFORM_CLK },
> - { "INT33C5", ACPI_PLATFORM_CLK },
> - { "INT33C6", ACPI_PLATFORM_CLK },
> - { "INT33C7", ACPI_PLATFORM_CLK },
> -
> - { }
> -};
> -
> static LIST_HEAD(acpi_device_list);
> static LIST_HEAD(acpi_bus_id_list);
> static DEFINE_MUTEX(acpi_scan_lock);
> @@ -1606,7 +1585,6 @@ static int acpi_scan_attach_handler(stru
> static acpi_status acpi_bus_device_attach(acpi_handle handle, u32 lvl_not_used,
> void *not_used, void **ret_not_used)
> {
> - const struct acpi_device_id *id;
> struct acpi_device *device;
> unsigned long long sta_not_used;
> int ret;
> @@ -1621,13 +1599,6 @@ static acpi_status acpi_bus_device_attac
> if (acpi_bus_get_device(handle, &device))
> return AE_CTRL_DEPTH;
>
> - id = __acpi_match_device(device, acpi_platform_device_ids);
> - if (id) {
> - /* This is a known good platform device. */
> - acpi_create_platform_device(device, id->driver_data);
> - return AE_OK;
> - }
> -
> ret = acpi_scan_attach_handler(device);
> if (ret)
> return ret > 0 ? AE_OK : AE_CTRL_DEPTH;
> @@ -1775,6 +1746,7 @@ int __init acpi_scan_init(void)
>
> acpi_pci_root_init();
> acpi_pci_link_init();
> + acpi_platform_init();
> acpi_csrt_init();
>
> /*
>
>
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-28 13:01 ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
2013-01-29 2:20 ` Yasuaki Ishimatsu
@ 2013-01-29 7:35 ` Mika Westerberg
2013-01-29 12:01 ` Rafael J. Wysocki
2013-01-29 8:05 ` Mika Westerberg
2 siblings, 1 reply; 71+ messages in thread
From: Mika Westerberg @ 2013-01-29 7:35 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Currently, the ACPI namespace scanning code creates platform device
> objects for ACPI device nodes whose IDs match the contents of the
> acpi_platform_device_ids[] table. However, this adds a superfluous
> special case into acpi_bus_device_attach() and makes it more
> difficult to follow than it has to be. It also will make it more
> difficult to implement removal code for those platform device objects
> in the future.
>
> For the above reasons, introduce a struct acpi_scan_handler object
> for creating platform devices and move the code related to that from
> acpi_bus_device_attach() to the .attach() callback of that object.
> Also move the acpi_platform_device_ids[] table to acpi_platform.c.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
I've tested this with Haswell machine and once you fix the problem pointed
out by Yasuaki Ishimat (returning always when ACPI_PLATFORM_CLK is set) the
platform device creation works well. This is a nice cleanup and localizes
the hard coded platform device table in one file making maintenance bit
easier.
Feel free to add:
Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-29 7:35 ` [PATCH " Mika Westerberg
@ 2013-01-29 12:01 ` Rafael J. Wysocki
0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 12:01 UTC (permalink / raw)
To: Mika Westerberg
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
On Tuesday, January 29, 2013 09:35:32 AM Mika Westerberg wrote:
> On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Currently, the ACPI namespace scanning code creates platform device
> > objects for ACPI device nodes whose IDs match the contents of the
> > acpi_platform_device_ids[] table. However, this adds a superfluous
> > special case into acpi_bus_device_attach() and makes it more
> > difficult to follow than it has to be. It also will make it more
> > difficult to implement removal code for those platform device objects
> > in the future.
> >
> > For the above reasons, introduce a struct acpi_scan_handler object
> > for creating platform devices and move the code related to that from
> > acpi_bus_device_attach() to the .attach() callback of that object.
> > Also move the acpi_platform_device_ids[] table to acpi_platform.c.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> I've tested this with Haswell machine and once you fix the problem pointed
> out by Yasuaki Ishimat (returning always when ACPI_PLATFORM_CLK is set)
Well, yeah. Fixed now.
> the platform device creation works well. This is a nice cleanup and localizes
> the hard coded platform device table in one file making maintenance bit
> easier.
>
> Feel free to add:
>
> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Thanks!
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-28 13:01 ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
2013-01-29 2:20 ` Yasuaki Ishimatsu
2013-01-29 7:35 ` [PATCH " Mika Westerberg
@ 2013-01-29 8:05 ` Mika Westerberg
2013-01-29 12:02 ` Rafael J. Wysocki
2 siblings, 1 reply; 71+ messages in thread
From: Mika Westerberg @ 2013-01-29 8:05 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> +/* Flags for acpi_create_platform_device */
> +#define ACPI_PLATFORM_CLK BIT(0)
> +
> +/*
> + * The following ACPI IDs are known to be suitable for representing as
> + * platform devices.
> + */
> +static const struct acpi_device_id acpi_platform_device_ids[] = {
> +
> + { "PNP0D40" },
> +
> + /* Haswell LPSS devices */
> + { "INT33C0", ACPI_PLATFORM_CLK },
> + { "INT33C1", ACPI_PLATFORM_CLK },
> + { "INT33C2", ACPI_PLATFORM_CLK },
> + { "INT33C3", ACPI_PLATFORM_CLK },
> + { "INT33C4", ACPI_PLATFORM_CLK },
> + { "INT33C5", ACPI_PLATFORM_CLK },
> + { "INT33C6", ACPI_PLATFORM_CLK },
> + { "INT33C7", ACPI_PLATFORM_CLK },
> +
> + { }
> +};
Now that we have everything the platform support code needs in a single
file, should we instead of setting flags and comparing strings like
"INT33C" to find out are we running on Lynxpoint, pass function pointer
that gets called when corresponding device gets created? Something like:
{ "INT33C0", lpt_clks_init },
...
Or do you think we need to keep the flags still?
I can prepare a patch if this turns out to be sensible thing to do.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices
2013-01-29 8:05 ` Mika Westerberg
@ 2013-01-29 12:02 ` Rafael J. Wysocki
0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 12:02 UTC (permalink / raw)
To: Mika Westerberg
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
On Tuesday, January 29, 2013 10:05:09 AM Mika Westerberg wrote:
> On Mon, Jan 28, 2013 at 02:01:14PM +0100, Rafael J. Wysocki wrote:
> > +/* Flags for acpi_create_platform_device */
> > +#define ACPI_PLATFORM_CLK BIT(0)
> > +
> > +/*
> > + * The following ACPI IDs are known to be suitable for representing as
> > + * platform devices.
> > + */
> > +static const struct acpi_device_id acpi_platform_device_ids[] = {
> > +
> > + { "PNP0D40" },
> > +
> > + /* Haswell LPSS devices */
> > + { "INT33C0", ACPI_PLATFORM_CLK },
> > + { "INT33C1", ACPI_PLATFORM_CLK },
> > + { "INT33C2", ACPI_PLATFORM_CLK },
> > + { "INT33C3", ACPI_PLATFORM_CLK },
> > + { "INT33C4", ACPI_PLATFORM_CLK },
> > + { "INT33C5", ACPI_PLATFORM_CLK },
> > + { "INT33C6", ACPI_PLATFORM_CLK },
> > + { "INT33C7", ACPI_PLATFORM_CLK },
> > +
> > + { }
> > +};
>
> Now that we have everything the platform support code needs in a single
> file, should we instead of setting flags and comparing strings like
> "INT33C" to find out are we running on Lynxpoint, pass function pointer
> that gets called when corresponding device gets created? Something like:
>
> { "INT33C0", lpt_clks_init },
> ...
>
> Or do you think we need to keep the flags still?
>
> I can prepare a patch if this turns out to be sensible thing to do.
Well, if we can reduce the code size this way, please send a patch.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/4] ACPI scan handlers
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
` (3 preceding siblings ...)
2013-01-28 13:01 ` [PATCH 4/4] ACPI / platform: Use struct acpi_scan_handler for creating devices Rafael J. Wysocki
@ 2013-01-28 21:54 ` Yinghai Lu
2013-01-29 0:38 ` Rafael J. Wysocki
2013-01-29 2:33 ` Toshi Kani
` (2 subsequent siblings)
7 siblings, 1 reply; 71+ messages in thread
From: Yinghai Lu @ 2013-01-28 21:54 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML
On Mon, Jan 28, 2013 at 4:58 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
>> Hi All,
>>
>> There is a considerable amount of confusion in the ACPI subsystem about what
>> ACPI drivers are used for. Namely, some of them are used as "normal" device
>> drivers that bind to devices and handle them using ACPI control methods (like
>> the fan or battery drivers), but some of them are just used for handling
>> namespace events, such as the creation or removal of device nodes (I guess it
>> would be fair to call that an abuse of the driver core). These two roles are
>> quite distinct, which is particularly visible from the confusion about the role
>> of the .remove() callback.
>>
>> For the "normal" drivers this callback is simply used to handle situations in
>> which the driver needs to be unbound from the device, because one of them
>> (either the device or the driver) is going away. That operation can't really
>> fail, it just needs to do the necessary cleanup.
>>
>> However, for the namespace events handling "drivers" .remove() means that not
>> only the device node in question, but generally also the whole subtree below it
>> needs to be prepared for removal, which may involve deleting multiple device
>> objects belonging to different bus types and so on and which very well may fail
>> (for example, those devices may be used for such things like swap or they may be
>> memory banks used by the kernel and it may not be safe to remove them at the
>> moment etc.). Moreover, for these things the removal of the "driver" doesn't
>> really make sense, because it has to be there to handle the namespace events it
>> is designed to handle or else things will go remarkably awry in some places.
>>
>> To resolve all that mess I'd like to do the following, which in part is inspired
>> by the recent Toshi Kani's hotplug framework proposal and in part is based on
>> some discussions I had with Bjorn and others (the code references made below are
>> based on the current contens of linux-pm.git/linux-next).
>>
>> 1) Introduce a special data type for "ACPI namespace event handlers" like:
>>
>> struct acpi_scan_handler {
>> const struct acpi_device_id *ids;
>> struct list_head list_node;
>> int (*attach)(struct acpi_device *adev);
>> int (*untie)(struct acpi_device *adev);
>> int (*reclaim)(struct acpi_device *adev);
>> void (*detach)(struct acpi_device *adev);
>> };
>
> After some reconsideration I think that the "untie" and "reclaim" things won't
> be really useful at this level. This means that I only need ACPI scan handlers
> to do .attach() and .detach() and all of that becomes really simple, so I don't
> see reason to wait with that change.
>
> The following patches introduce ACPI scan handlers and make some use of them.
>
> [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
> device IDs.
>
> [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
>
> [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
>
> [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
Good, esp you move away hard code in scan.c for platform devices.
Test with pci root bus hotplug, and it works well.
So for all 4,
Acked-by: Yinghai Lu <yinghai@kernel.org>
It will have some merging conflicts change in drivers/acpi/internel.h
in pci/next for pci root bus hotplug support.
But it should be very simple to solve it.
Thanks
Yinghai
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/4] ACPI scan handlers
2013-01-28 21:54 ` [PATCH 0/4] ACPI scan handlers Yinghai Lu
@ 2013-01-29 0:38 ` Rafael J. Wysocki
0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-29 0:38 UTC (permalink / raw)
To: Yinghai Lu
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML
On Monday, January 28, 2013 01:54:30 PM Yinghai Lu wrote:
> On Mon, Jan 28, 2013 at 4:58 AM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> >> Hi All,
> >>
> >> There is a considerable amount of confusion in the ACPI subsystem about what
> >> ACPI drivers are used for. Namely, some of them are used as "normal" device
> >> drivers that bind to devices and handle them using ACPI control methods (like
> >> the fan or battery drivers), but some of them are just used for handling
> >> namespace events, such as the creation or removal of device nodes (I guess it
> >> would be fair to call that an abuse of the driver core). These two roles are
> >> quite distinct, which is particularly visible from the confusion about the role
> >> of the .remove() callback.
> >>
> >> For the "normal" drivers this callback is simply used to handle situations in
> >> which the driver needs to be unbound from the device, because one of them
> >> (either the device or the driver) is going away. That operation can't really
> >> fail, it just needs to do the necessary cleanup.
> >>
> >> However, for the namespace events handling "drivers" .remove() means that not
> >> only the device node in question, but generally also the whole subtree below it
> >> needs to be prepared for removal, which may involve deleting multiple device
> >> objects belonging to different bus types and so on and which very well may fail
> >> (for example, those devices may be used for such things like swap or they may be
> >> memory banks used by the kernel and it may not be safe to remove them at the
> >> moment etc.). Moreover, for these things the removal of the "driver" doesn't
> >> really make sense, because it has to be there to handle the namespace events it
> >> is designed to handle or else things will go remarkably awry in some places.
> >>
> >> To resolve all that mess I'd like to do the following, which in part is inspired
> >> by the recent Toshi Kani's hotplug framework proposal and in part is based on
> >> some discussions I had with Bjorn and others (the code references made below are
> >> based on the current contens of linux-pm.git/linux-next).
> >>
> >> 1) Introduce a special data type for "ACPI namespace event handlers" like:
> >>
> >> struct acpi_scan_handler {
> >> const struct acpi_device_id *ids;
> >> struct list_head list_node;
> >> int (*attach)(struct acpi_device *adev);
> >> int (*untie)(struct acpi_device *adev);
> >> int (*reclaim)(struct acpi_device *adev);
> >> void (*detach)(struct acpi_device *adev);
> >> };
> >
> > After some reconsideration I think that the "untie" and "reclaim" things won't
> > be really useful at this level. This means that I only need ACPI scan handlers
> > to do .attach() and .detach() and all of that becomes really simple, so I don't
> > see reason to wait with that change.
> >
> > The following patches introduce ACPI scan handlers and make some use of them.
> >
> > [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
> > device IDs.
> >
> > [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
> >
> > [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
> >
> > [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
>
> Good, esp you move away hard code in scan.c for platform devices.
>
> Test with pci root bus hotplug, and it works well.
>
> So for all 4,
>
> Acked-by: Yinghai Lu <yinghai@kernel.org>
Thanks for the review!
> It will have some merging conflicts change in drivers/acpi/internel.h
> in pci/next for pci root bus hotplug support.
> But it should be very simple to solve it.
Yes, it shouldn't be too difficult to resolve them.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/4] ACPI scan handlers
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
` (4 preceding siblings ...)
2013-01-28 21:54 ` [PATCH 0/4] ACPI scan handlers Yinghai Lu
@ 2013-01-29 2:33 ` Toshi Kani
2013-01-30 1:58 ` Toshi Kani
2013-02-03 23:45 ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
7 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-01-29 2:33 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Mon, 2013-01-28 at 13:58 +0100, Rafael J. Wysocki wrote:
> On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> > Hi All,
> >
> > There is a considerable amount of confusion in the ACPI subsystem about what
> > ACPI drivers are used for. Namely, some of them are used as "normal" device
> > drivers that bind to devices and handle them using ACPI control methods (like
> > the fan or battery drivers), but some of them are just used for handling
> > namespace events, such as the creation or removal of device nodes (I guess it
> > would be fair to call that an abuse of the driver core). These two roles are
> > quite distinct, which is particularly visible from the confusion about the role
> > of the .remove() callback.
> >
> > For the "normal" drivers this callback is simply used to handle situations in
> > which the driver needs to be unbound from the device, because one of them
> > (either the device or the driver) is going away. That operation can't really
> > fail, it just needs to do the necessary cleanup.
> >
> > However, for the namespace events handling "drivers" .remove() means that not
> > only the device node in question, but generally also the whole subtree below it
> > needs to be prepared for removal, which may involve deleting multiple device
> > objects belonging to different bus types and so on and which very well may fail
> > (for example, those devices may be used for such things like swap or they may be
> > memory banks used by the kernel and it may not be safe to remove them at the
> > moment etc.). Moreover, for these things the removal of the "driver" doesn't
> > really make sense, because it has to be there to handle the namespace events it
> > is designed to handle or else things will go remarkably awry in some places.
> >
> > To resolve all that mess I'd like to do the following, which in part is inspired
> > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > some discussions I had with Bjorn and others (the code references made below are
> > based on the current contens of linux-pm.git/linux-next).
> >
> > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> >
> > struct acpi_scan_handler {
> > const struct acpi_device_id *ids;
> > struct list_head list_node;
> > int (*attach)(struct acpi_device *adev);
> > int (*untie)(struct acpi_device *adev);
> > int (*reclaim)(struct acpi_device *adev);
> > void (*detach)(struct acpi_device *adev);
> > };
>
> After some reconsideration I think that the "untie" and "reclaim" things won't
> be really useful at this level. This means that I only need ACPI scan handlers
> to do .attach() and .detach() and all of that becomes really simple, so I don't
> see reason to wait with that change.
That's great. I agree with you. The name of attach/detach() also
clarifies the purpose of the interfaces well.
Thanks,
-Toshi
ps.
I am tied up this week and will be somewhat slow to respond...
>
> The following patches introduce ACPI scan handlers and make some use of them.
>
> [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
> device IDs.
>
> [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
>
> [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
>
> [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
>
> Thanks,
> Rafael
>
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/4] ACPI scan handlers
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
` (5 preceding siblings ...)
2013-01-29 2:33 ` Toshi Kani
@ 2013-01-30 1:58 ` Toshi Kani
2013-01-30 13:36 ` Rafael J. Wysocki
2013-02-03 23:45 ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
7 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-01-30 1:58 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Mon, 2013-01-28 at 13:58 +0100, Rafael J. Wysocki wrote:
> On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> > Hi All,
> >
> > There is a considerable amount of confusion in the ACPI subsystem about what
> > ACPI drivers are used for. Namely, some of them are used as "normal" device
> > drivers that bind to devices and handle them using ACPI control methods (like
> > the fan or battery drivers), but some of them are just used for handling
> > namespace events, such as the creation or removal of device nodes (I guess it
> > would be fair to call that an abuse of the driver core). These two roles are
> > quite distinct, which is particularly visible from the confusion about the role
> > of the .remove() callback.
> >
> > For the "normal" drivers this callback is simply used to handle situations in
> > which the driver needs to be unbound from the device, because one of them
> > (either the device or the driver) is going away. That operation can't really
> > fail, it just needs to do the necessary cleanup.
> >
> > However, for the namespace events handling "drivers" .remove() means that not
> > only the device node in question, but generally also the whole subtree below it
> > needs to be prepared for removal, which may involve deleting multiple device
> > objects belonging to different bus types and so on and which very well may fail
> > (for example, those devices may be used for such things like swap or they may be
> > memory banks used by the kernel and it may not be safe to remove them at the
> > moment etc.). Moreover, for these things the removal of the "driver" doesn't
> > really make sense, because it has to be there to handle the namespace events it
> > is designed to handle or else things will go remarkably awry in some places.
> >
> > To resolve all that mess I'd like to do the following, which in part is inspired
> > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > some discussions I had with Bjorn and others (the code references made below are
> > based on the current contens of linux-pm.git/linux-next).
> >
> > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> >
> > struct acpi_scan_handler {
> > const struct acpi_device_id *ids;
> > struct list_head list_node;
> > int (*attach)(struct acpi_device *adev);
> > int (*untie)(struct acpi_device *adev);
> > int (*reclaim)(struct acpi_device *adev);
> > void (*detach)(struct acpi_device *adev);
> > };
>
> After some reconsideration I think that the "untie" and "reclaim" things won't
> be really useful at this level. This means that I only need ACPI scan handlers
> to do .attach() and .detach() and all of that becomes really simple, so I don't
> see reason to wait with that change.
>
> The following patches introduce ACPI scan handlers and make some use of them.
>
> [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
> device IDs.
>
> [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
>
> [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
>
> [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
For the series:
Acked-by: Toshi Kani <toshi.kani@hp.com>
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/4] ACPI scan handlers
2013-01-30 1:58 ` Toshi Kani
@ 2013-01-30 13:36 ` Rafael J. Wysocki
0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-01-30 13:36 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Tuesday, January 29, 2013 06:58:30 PM Toshi Kani wrote:
> On Mon, 2013-01-28 at 13:58 +0100, Rafael J. Wysocki wrote:
> > On Thursday, January 24, 2013 01:26:56 AM Rafael J. Wysocki wrote:
> > > Hi All,
> > >
> > > There is a considerable amount of confusion in the ACPI subsystem about what
> > > ACPI drivers are used for. Namely, some of them are used as "normal" device
> > > drivers that bind to devices and handle them using ACPI control methods (like
> > > the fan or battery drivers), but some of them are just used for handling
> > > namespace events, such as the creation or removal of device nodes (I guess it
> > > would be fair to call that an abuse of the driver core). These two roles are
> > > quite distinct, which is particularly visible from the confusion about the role
> > > of the .remove() callback.
> > >
> > > For the "normal" drivers this callback is simply used to handle situations in
> > > which the driver needs to be unbound from the device, because one of them
> > > (either the device or the driver) is going away. That operation can't really
> > > fail, it just needs to do the necessary cleanup.
> > >
> > > However, for the namespace events handling "drivers" .remove() means that not
> > > only the device node in question, but generally also the whole subtree below it
> > > needs to be prepared for removal, which may involve deleting multiple device
> > > objects belonging to different bus types and so on and which very well may fail
> > > (for example, those devices may be used for such things like swap or they may be
> > > memory banks used by the kernel and it may not be safe to remove them at the
> > > moment etc.). Moreover, for these things the removal of the "driver" doesn't
> > > really make sense, because it has to be there to handle the namespace events it
> > > is designed to handle or else things will go remarkably awry in some places.
> > >
> > > To resolve all that mess I'd like to do the following, which in part is inspired
> > > by the recent Toshi Kani's hotplug framework proposal and in part is based on
> > > some discussions I had with Bjorn and others (the code references made below are
> > > based on the current contens of linux-pm.git/linux-next).
> > >
> > > 1) Introduce a special data type for "ACPI namespace event handlers" like:
> > >
> > > struct acpi_scan_handler {
> > > const struct acpi_device_id *ids;
> > > struct list_head list_node;
> > > int (*attach)(struct acpi_device *adev);
> > > int (*untie)(struct acpi_device *adev);
> > > int (*reclaim)(struct acpi_device *adev);
> > > void (*detach)(struct acpi_device *adev);
> > > };
> >
> > After some reconsideration I think that the "untie" and "reclaim" things won't
> > be really useful at this level. This means that I only need ACPI scan handlers
> > to do .attach() and .detach() and all of that becomes really simple, so I don't
> > see reason to wait with that change.
> >
> > The following patches introduce ACPI scan handlers and make some use of them.
> >
> > [1/4] Introduce struct acpi_scan_handler for configuration tasks depending on
> > device IDs.
> >
> > [2/4] Make ACPI PCI root driver use struct acpi_scan_handler.
> >
> > [3/4] Make ACPI PCI IRQ link driver use struct acpi_scan_handler.
> >
> > [4/4] Use struct acpi_scan_handler for creating platform devices enumerated via ACPI.
>
> For the series:
>
> Acked-by: Toshi Kani <toshi.kani@hp.com>
Thanks!
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification
2013-01-28 12:58 ` [PATCH 0/4] " Rafael J. Wysocki
` (6 preceding siblings ...)
2013-01-30 1:58 ` Toshi Kani
@ 2013-02-03 23:45 ` Rafael J. Wysocki
2013-02-03 23:46 ` [PATCH 1/2] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
2013-02-03 23:47 ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
7 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 23:45 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
Hi All,
Patch [1/2] in this series makes the ACPI memory hotplug driver use struct
acpi_scan_handler instead of struct acpi_driver and changes the driver to
non-modular (as a consequence).
Patch [2/2] is a bit funny, though. I though I'd make the container driver
use struct acpi_scan_handler instead of struct acpi_driver too, but then I
noticed that its struct acpi_driver and everything it does is just plain
garbage without any use whatsoever, so the patch simply drops that stuff.
Both on top of linux-pm.git/bleeding-edge. Unfortunately, I don't have the
hardware to test those things, so if anyone can test them, I'll appreciate it
a lot.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 1/2] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler
2013-02-03 23:45 ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
@ 2013-02-03 23:46 ` Rafael J. Wysocki
2013-02-03 23:47 ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
1 sibling, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 23:46 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Make the ACPI memory hotplug driver use struct acpi_scan_handler
for representing the object used to set up ACPI memory hotplug
functionality and to remove hotplug memory ranges and data
structures used by the driver before unregistering ACPI device
nodes representing memory.
This simplifies the code and reduces the kernel's memory footprint by
avoiding the registration of a struct device_driver object with the
driver core and creation of its sysfs directory which is unnecessary.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/Kconfig | 3
drivers/acpi/acpi_memhotplug.c | 180 ++++++++++-------------------------------
drivers/acpi/internal.h | 5 +
drivers/acpi/scan.c | 1
4 files changed, 54 insertions(+), 135 deletions(-)
Index: test/drivers/acpi/Kconfig
===================================================================
--- test.orig/drivers/acpi/Kconfig
+++ test/drivers/acpi/Kconfig
@@ -347,9 +347,8 @@ config ACPI_CONTAINER
the module will be called container.
config ACPI_HOTPLUG_MEMORY
- tristate "Memory Hotplug"
+ bool "Memory Hotplug"
depends on MEMORY_HOTPLUG
- default n
help
This driver supports ACPI memory hotplug. The driver
fields notifications on ACPI memory devices (PNP0C80),
Index: test/drivers/acpi/acpi_memhotplug.c
===================================================================
--- test.orig/drivers/acpi/acpi_memhotplug.c
+++ test/drivers/acpi/acpi_memhotplug.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2004 Intel Corporation <naveen.b.s@intel.com>
+ * Copyright (C) 2004 Intel Corporation
+ * Author: Naveen B S <naveen.b.s@intel.com>
*
* All rights reserved.
*
@@ -44,17 +45,15 @@
#define PREFIX "ACPI:memory_hp:"
ACPI_MODULE_NAME("acpi_memhotplug");
-MODULE_AUTHOR("Naveen B S <naveen.b.s@intel.com>");
-MODULE_DESCRIPTION("Hotplug Mem Driver");
-MODULE_LICENSE("GPL");
/* Memory Device States */
#define MEMORY_INVALID_STATE 0
#define MEMORY_POWER_ON_STATE 1
#define MEMORY_POWER_OFF_STATE 2
-static int acpi_memory_device_add(struct acpi_device *device);
-static int acpi_memory_device_remove(struct acpi_device *device);
+static int acpi_memory_device_add(struct acpi_device *device,
+ const struct acpi_device_id *not_used);
+static void acpi_memory_device_remove(struct acpi_device *device);
static const struct acpi_device_id memory_device_ids[] = {
{ACPI_MEMORY_DEVICE_HID, 0},
@@ -62,14 +61,10 @@ static const struct acpi_device_id memor
};
MODULE_DEVICE_TABLE(acpi, memory_device_ids);
-static struct acpi_driver acpi_memory_device_driver = {
- .name = "acpi_memhotplug",
- .class = ACPI_MEMORY_DEVICE_CLASS,
+static struct acpi_scan_handler memory_device_handler = {
.ids = memory_device_ids,
- .ops = {
- .add = acpi_memory_device_add,
- .remove = acpi_memory_device_remove,
- },
+ .attach = acpi_memory_device_add,
+ .detach = acpi_memory_device_remove,
};
struct acpi_memory_info {
@@ -369,14 +364,15 @@ static void acpi_memory_device_free(stru
return;
acpi_memory_free_device_resources(mem_device);
+ mem_device->device->driver_data = NULL;
kfree(mem_device);
}
-static int acpi_memory_device_add(struct acpi_device *device)
+static int acpi_memory_device_add(struct acpi_device *device,
+ const struct acpi_device_id *not_used)
{
+ struct acpi_memory_device *mem_device;
int result;
- struct acpi_memory_device *mem_device = NULL;
-
if (!device)
return -EINVAL;
@@ -401,147 +397,65 @@ static int acpi_memory_device_add(struct
/* Set the device state */
mem_device->state = MEMORY_POWER_ON_STATE;
- pr_debug("%s\n", acpi_device_name(device));
+ result = acpi_memory_check_device(mem_device);
+ if (result) {
+ acpi_memory_device_free(mem_device);
+ return 0;
+ }
- if (!acpi_memory_check_device(mem_device)) {
- /* call add_memory func */
- result = acpi_memory_enable_device(mem_device);
- if (result) {
- dev_err(&device->dev,
- "Error in acpi_memory_enable_device\n");
- acpi_memory_device_free(mem_device);
- }
+ result = acpi_memory_enable_device(mem_device);
+ if (result) {
+ dev_err(&device->dev, "acpi_memory_enable_device() error\n");
+ acpi_memory_device_free(mem_device);
+ return -ENODEV;
}
- return result;
+
+ dev_dbg(&device->dev, "Memory device configured by ACPI\n");
+ return 1;
}
-static int acpi_memory_device_remove(struct acpi_device *device)
+static void acpi_memory_device_remove(struct acpi_device *device)
{
- struct acpi_memory_device *mem_device = NULL;
- int result;
+ struct acpi_memory_device *mem_device;
if (!device || !acpi_driver_data(device))
- return -EINVAL;
+ return;
mem_device = acpi_driver_data(device);
-
- result = acpi_memory_remove_memory(mem_device);
- if (result)
- return result;
-
+ acpi_memory_remove_memory(mem_device);
acpi_memory_device_free(mem_device);
-
- return 0;
}
-/*
- * Helper function to check for memory device
- */
-static acpi_status is_memory_device(acpi_handle handle)
+static bool is_memory_device(acpi_handle handle)
{
- char *hardware_id;
- acpi_status status;
struct acpi_device_info *info;
+ bool ret = false;
- status = acpi_get_object_info(handle, &info);
- if (ACPI_FAILURE(status))
- return status;
-
- if (!(info->valid & ACPI_VALID_HID)) {
- kfree(info);
- return AE_ERROR;
- }
+ if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+ return false;
- hardware_id = info->hardware_id.string;
- if ((hardware_id == NULL) ||
- (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID)))
- status = AE_ERROR;
+ if (info->valid & ACPI_VALID_HID)
+ ret = !strcmp(info->hardware_id.string, ACPI_MEMORY_DEVICE_HID);
kfree(info);
- return status;
+ return ret;
}
-static acpi_status
-acpi_memory_register_notify_handler(acpi_handle handle,
- u32 level, void *ctxt, void **retv)
+static acpi_status acpi_memory_register_notify_handler(acpi_handle handle,
+ u32 lvl, void *ctxt,
+ void **retv)
{
- acpi_status status;
+ if (is_memory_device(handle))
+ acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ acpi_memory_device_notify, NULL);
-
- status = is_memory_device(handle);
- if (ACPI_FAILURE(status))
- return AE_OK; /* continue */
-
- status = acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
- acpi_memory_device_notify, NULL);
- /* continue */
return AE_OK;
}
-static acpi_status
-acpi_memory_deregister_notify_handler(acpi_handle handle,
- u32 level, void *ctxt, void **retv)
-{
- acpi_status status;
-
-
- status = is_memory_device(handle);
- if (ACPI_FAILURE(status))
- return AE_OK; /* continue */
-
- status = acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- acpi_memory_device_notify);
-
- return AE_OK; /* continue */
-}
-
-static int __init acpi_memory_device_init(void)
-{
- int result;
- acpi_status status;
-
-
- result = acpi_bus_register_driver(&acpi_memory_device_driver);
-
- if (result < 0)
- return -ENODEV;
-
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- acpi_memory_register_notify_handler, NULL,
- NULL, NULL);
-
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
- acpi_bus_unregister_driver(&acpi_memory_device_driver);
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __exit acpi_memory_device_exit(void)
+void __init acpi_memory_hotplug_init(void)
{
- acpi_status status;
-
-
- /*
- * Adding this to un-install notification handlers for all the device
- * handles.
- */
- status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- acpi_memory_deregister_notify_handler, NULL,
- NULL, NULL);
-
- if (ACPI_FAILURE(status))
- ACPI_EXCEPTION((AE_INFO, status, "walk_namespace failed"));
-
- acpi_bus_unregister_driver(&acpi_memory_device_driver);
-
- return;
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ acpi_memory_register_notify_handler, NULL,
+ NULL, NULL);
+ acpi_scan_add_handler(&memory_device_handler);
}
-
-module_init(acpi_memory_device_init);
-module_exit(acpi_memory_device_exit);
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -35,6 +35,11 @@ void acpi_pci_slot_init(void);
#else
static inline void acpi_pci_slot_init(void) { }
#endif
+#ifdef CONFIG_ACPI_HOTPLUG_MEMORY
+void acpi_memory_hotplug_init(void);
+#else
+static inline void acpi_memory_hotplug_init(void) {}
+#endif
#ifdef CONFIG_DEBUG_FS
extern struct dentry *acpi_debugfs_dir;
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1762,6 +1762,7 @@ int __init acpi_scan_init(void)
acpi_pci_slot_init();
acpi_platform_init();
acpi_csrt_init();
+ acpi_memory_hotplug_init();
/*
* Enumerate devices in the ACPI namespace.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-03 23:45 ` [PATCH 0/2] ACPI scan handler for memory hotplug and container simplification Rafael J. Wysocki
2013-02-03 23:46 ` [PATCH 1/2] ACPI / scan: Make memory hotplug driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-02-03 23:47 ` Rafael J. Wysocki
2013-02-06 22:32 ` Toshi Kani
` (2 more replies)
1 sibling, 3 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-03 23:47 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
The only useful thing that the ACPI container driver does is to
install system notify handlers for all container and module device
objects it finds in the namespace. The driver structure,
acpi_container_driver, and the data structures created by its
.add() callback are in fact not used by the driver, so remove
them entirely.
It also makes a little sense to build that driver as a module,
so make it non-modular and add its initialization to the
namespace scanning code.
In addition to that, make the namespace walk callback used for
installing the notify handlers more straightforward.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/Kconfig | 2
drivers/acpi/container.c | 158 ++++++-----------------------------------------
drivers/acpi/internal.h | 5 +
drivers/acpi/scan.c | 1
4 files changed, 30 insertions(+), 136 deletions(-)
Index: test/drivers/acpi/container.c
===================================================================
--- test.orig/drivers/acpi/container.c
+++ test/drivers/acpi/container.c
@@ -38,41 +38,15 @@
#define PREFIX "ACPI: "
-#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
-#define ACPI_CONTAINER_CLASS "container"
-
-#define INSTALL_NOTIFY_HANDLER 1
-#define UNINSTALL_NOTIFY_HANDLER 2
-
#define _COMPONENT ACPI_CONTAINER_COMPONENT
ACPI_MODULE_NAME("container");
-MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION("ACPI container driver");
-MODULE_LICENSE("GPL");
-
-static int acpi_container_add(struct acpi_device *device);
-static int acpi_container_remove(struct acpi_device *device);
-
static const struct acpi_device_id container_device_ids[] = {
{"ACPI0004", 0},
{"PNP0A05", 0},
{"PNP0A06", 0},
{"", 0},
};
-MODULE_DEVICE_TABLE(acpi, container_device_ids);
-
-static struct acpi_driver acpi_container_driver = {
- .name = "container",
- .class = ACPI_CONTAINER_CLASS,
- .ids = container_device_ids,
- .ops = {
- .add = acpi_container_add,
- .remove = acpi_container_remove,
- },
-};
-
-/*******************************************************************/
static int is_device_present(acpi_handle handle)
{
@@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
}
-static bool is_container_device(const char *hid)
-{
- const struct acpi_device_id *container_id;
-
- for (container_id = container_device_ids;
- container_id->id[0]; container_id++) {
- if (!strcmp((char *)container_id->id, hid))
- return true;
- }
-
- return false;
-}
-
-/*******************************************************************/
-static int acpi_container_add(struct acpi_device *device)
-{
- struct acpi_container *container;
-
- container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
- if (!container)
- return -ENOMEM;
-
- container->handle = device->handle;
- strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
- device->driver_data = container;
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
- acpi_device_name(device), acpi_device_bid(device)));
-
- return 0;
-}
-
-static int acpi_container_remove(struct acpi_device *device)
-{
- acpi_status status = AE_OK;
- struct acpi_container *pc = NULL;
-
- pc = acpi_driver_data(device);
- kfree(pc);
- return status;
-}
-
static void container_notify_cb(acpi_handle handle, u32 type, void *context)
{
struct acpi_device *device = NULL;
@@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
return;
}
-static acpi_status
-container_walk_namespace_cb(acpi_handle handle,
- u32 lvl, void *context, void **rv)
+static bool is_container(acpi_handle handle)
{
- char *hid = NULL;
struct acpi_device_info *info;
- acpi_status status;
- int *action = context;
+ bool ret = false;
- status = acpi_get_object_info(handle, &info);
- if (ACPI_FAILURE(status)) {
- return AE_OK;
- }
-
- if (info->valid & ACPI_VALID_HID)
- hid = info->hardware_id.string;
-
- if (hid == NULL) {
- goto end;
- }
+ if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+ return false;
- if (!is_container_device(hid))
- goto end;
+ if (info->valid & ACPI_VALID_HID) {
+ const struct acpi_device_id *id;
- switch (*action) {
- case INSTALL_NOTIFY_HANDLER:
- acpi_install_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb, NULL);
- break;
- case UNINSTALL_NOTIFY_HANDLER:
- acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb);
- break;
- default:
- break;
+ for (id = container_device_ids; id->id[0]; id++) {
+ ret = !strcmp((char *)id->id, info->hardware_id.string);
+ if (ret)
+ break;
+ }
}
-
- end:
kfree(info);
-
- return AE_OK;
+ return ret;
}
-static int __init acpi_container_init(void)
+static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
+ u32 lvl, void *ctxt,
+ void **retv)
{
- int result = 0;
- int action = INSTALL_NOTIFY_HANDLER;
-
- result = acpi_bus_register_driver(&acpi_container_driver);
- if (result < 0) {
- return (result);
- }
-
- /* register notify handler to every container device */
- acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb, NULL, &action, NULL);
+ if (is_container(handle))
+ acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ container_notify_cb, NULL);
- return (0);
+ return AE_OK;
}
-static void __exit acpi_container_exit(void)
+void __init acpi_container_init(void)
{
- int action = UNINSTALL_NOTIFY_HANDLER;
-
-
- acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb, NULL, &action, NULL);
-
- acpi_bus_unregister_driver(&acpi_container_driver);
-
- return;
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ acpi_container_register_notify_handler, NULL,
+ NULL, NULL);
}
-
-module_init(acpi_container_init);
-module_exit(acpi_container_exit);
Index: test/drivers/acpi/Kconfig
===================================================================
--- test.orig/drivers/acpi/Kconfig
+++ test/drivers/acpi/Kconfig
@@ -334,7 +334,7 @@ config X86_PM_TIMER
systems require this timer.
config ACPI_CONTAINER
- tristate "Container and Module Devices (EXPERIMENTAL)"
+ bool "Container and Module Devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
help
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
#else
static inline void acpi_memory_hotplug_init(void) {}
#endif
+#ifdef ACPI_CONTAINER
+void acpi_container_init(void);
+#else
+static inline void acpi_container_init(void) {}
+#endif
#ifdef CONFIG_DEBUG_FS
extern struct dentry *acpi_debugfs_dir;
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1763,6 +1763,7 @@ int __init acpi_scan_init(void)
acpi_platform_init();
acpi_csrt_init();
acpi_memory_hotplug_init();
+ acpi_container_init();
/*
* Enumerate devices in the ACPI namespace.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-03 23:47 ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
@ 2013-02-06 22:32 ` Toshi Kani
2013-02-07 0:55 ` Rafael J. Wysocki
2013-02-07 8:32 ` Yasuaki Ishimatsu
2013-02-08 0:24 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
2 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-06 22:32 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The only useful thing that the ACPI container driver does is to
> install system notify handlers for all container and module device
> objects it finds in the namespace. The driver structure,
> acpi_container_driver, and the data structures created by its
> .add() callback are in fact not used by the driver, so remove
> them entirely.
>
> It also makes a little sense to build that driver as a module,
> so make it non-modular and add its initialization to the
> namespace scanning code.
>
> In addition to that, make the namespace walk callback used for
> installing the notify handlers more straightforward.
I think the container driver needs to be registered as an ACPI scan
driver so that sysfs eject will continue to work for container devices,
such as ACPI0004:XX/eject. Since the container driver does not support
ACPI eject notification (and we have been discussing how system device
hot-plug should work), this sysfs eject is the only way to eject a
container device at this point. I will send an update patchset that
applies on top of this patch.
With the update in my patchset:
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Thanks,
-Toshi
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
> drivers/acpi/Kconfig | 2
> drivers/acpi/container.c | 158 ++++++-----------------------------------------
> drivers/acpi/internal.h | 5 +
> drivers/acpi/scan.c | 1
> 4 files changed, 30 insertions(+), 136 deletions(-)
>
> Index: test/drivers/acpi/container.c
> ===================================================================
> --- test.orig/drivers/acpi/container.c
> +++ test/drivers/acpi/container.c
> @@ -38,41 +38,15 @@
>
> #define PREFIX "ACPI: "
>
> -#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
> -#define ACPI_CONTAINER_CLASS "container"
> -
> -#define INSTALL_NOTIFY_HANDLER 1
> -#define UNINSTALL_NOTIFY_HANDLER 2
> -
> #define _COMPONENT ACPI_CONTAINER_COMPONENT
> ACPI_MODULE_NAME("container");
>
> -MODULE_AUTHOR("Anil S Keshavamurthy");
> -MODULE_DESCRIPTION("ACPI container driver");
> -MODULE_LICENSE("GPL");
> -
> -static int acpi_container_add(struct acpi_device *device);
> -static int acpi_container_remove(struct acpi_device *device);
> -
> static const struct acpi_device_id container_device_ids[] = {
> {"ACPI0004", 0},
> {"PNP0A05", 0},
> {"PNP0A06", 0},
> {"", 0},
> };
> -MODULE_DEVICE_TABLE(acpi, container_device_ids);
> -
> -static struct acpi_driver acpi_container_driver = {
> - .name = "container",
> - .class = ACPI_CONTAINER_CLASS,
> - .ids = container_device_ids,
> - .ops = {
> - .add = acpi_container_add,
> - .remove = acpi_container_remove,
> - },
> -};
> -
> -/*******************************************************************/
>
> static int is_device_present(acpi_handle handle)
> {
> @@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
> return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
> }
>
> -static bool is_container_device(const char *hid)
> -{
> - const struct acpi_device_id *container_id;
> -
> - for (container_id = container_device_ids;
> - container_id->id[0]; container_id++) {
> - if (!strcmp((char *)container_id->id, hid))
> - return true;
> - }
> -
> - return false;
> -}
> -
> -/*******************************************************************/
> -static int acpi_container_add(struct acpi_device *device)
> -{
> - struct acpi_container *container;
> -
> - container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
> - if (!container)
> - return -ENOMEM;
> -
> - container->handle = device->handle;
> - strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
> - strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
> - device->driver_data = container;
> -
> - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
> - acpi_device_name(device), acpi_device_bid(device)));
> -
> - return 0;
> -}
> -
> -static int acpi_container_remove(struct acpi_device *device)
> -{
> - acpi_status status = AE_OK;
> - struct acpi_container *pc = NULL;
> -
> - pc = acpi_driver_data(device);
> - kfree(pc);
> - return status;
> -}
> -
> static void container_notify_cb(acpi_handle handle, u32 type, void *context)
> {
> struct acpi_device *device = NULL;
> @@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
> return;
> }
>
> -static acpi_status
> -container_walk_namespace_cb(acpi_handle handle,
> - u32 lvl, void *context, void **rv)
> +static bool is_container(acpi_handle handle)
> {
> - char *hid = NULL;
> struct acpi_device_info *info;
> - acpi_status status;
> - int *action = context;
> + bool ret = false;
>
> - status = acpi_get_object_info(handle, &info);
> - if (ACPI_FAILURE(status)) {
> - return AE_OK;
> - }
> -
> - if (info->valid & ACPI_VALID_HID)
> - hid = info->hardware_id.string;
> -
> - if (hid == NULL) {
> - goto end;
> - }
> + if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
> + return false;
>
> - if (!is_container_device(hid))
> - goto end;
> + if (info->valid & ACPI_VALID_HID) {
> + const struct acpi_device_id *id;
>
> - switch (*action) {
> - case INSTALL_NOTIFY_HANDLER:
> - acpi_install_notify_handler(handle,
> - ACPI_SYSTEM_NOTIFY,
> - container_notify_cb, NULL);
> - break;
> - case UNINSTALL_NOTIFY_HANDLER:
> - acpi_remove_notify_handler(handle,
> - ACPI_SYSTEM_NOTIFY,
> - container_notify_cb);
> - break;
> - default:
> - break;
> + for (id = container_device_ids; id->id[0]; id++) {
> + ret = !strcmp((char *)id->id, info->hardware_id.string);
> + if (ret)
> + break;
> + }
> }
> -
> - end:
> kfree(info);
> -
> - return AE_OK;
> + return ret;
> }
>
> -static int __init acpi_container_init(void)
> +static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
> + u32 lvl, void *ctxt,
> + void **retv)
> {
> - int result = 0;
> - int action = INSTALL_NOTIFY_HANDLER;
> -
> - result = acpi_bus_register_driver(&acpi_container_driver);
> - if (result < 0) {
> - return (result);
> - }
> -
> - /* register notify handler to every container device */
> - acpi_walk_namespace(ACPI_TYPE_DEVICE,
> - ACPI_ROOT_OBJECT,
> - ACPI_UINT32_MAX,
> - container_walk_namespace_cb, NULL, &action, NULL);
> + if (is_container(handle))
> + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> + container_notify_cb, NULL);
>
> - return (0);
> + return AE_OK;
> }
>
> -static void __exit acpi_container_exit(void)
> +void __init acpi_container_init(void)
> {
> - int action = UNINSTALL_NOTIFY_HANDLER;
> -
> -
> - acpi_walk_namespace(ACPI_TYPE_DEVICE,
> - ACPI_ROOT_OBJECT,
> - ACPI_UINT32_MAX,
> - container_walk_namespace_cb, NULL, &action, NULL);
> -
> - acpi_bus_unregister_driver(&acpi_container_driver);
> -
> - return;
> + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
> + acpi_container_register_notify_handler, NULL,
> + NULL, NULL);
> }
> -
> -module_init(acpi_container_init);
> -module_exit(acpi_container_exit);
> Index: test/drivers/acpi/Kconfig
> ===================================================================
> --- test.orig/drivers/acpi/Kconfig
> +++ test/drivers/acpi/Kconfig
> @@ -334,7 +334,7 @@ config X86_PM_TIMER
> systems require this timer.
>
> config ACPI_CONTAINER
> - tristate "Container and Module Devices (EXPERIMENTAL)"
> + bool "Container and Module Devices (EXPERIMENTAL)"
> depends on EXPERIMENTAL
> default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
> help
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
> #else
> static inline void acpi_memory_hotplug_init(void) {}
> #endif
> +#ifdef ACPI_CONTAINER
> +void acpi_container_init(void);
> +#else
> +static inline void acpi_container_init(void) {}
> +#endif
>
> #ifdef CONFIG_DEBUG_FS
> extern struct dentry *acpi_debugfs_dir;
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1763,6 +1763,7 @@ int __init acpi_scan_init(void)
> acpi_platform_init();
> acpi_csrt_init();
> acpi_memory_hotplug_init();
> + acpi_container_init();
>
> /*
> * Enumerate devices in the ACPI namespace.
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-06 22:32 ` Toshi Kani
@ 2013-02-07 0:55 ` Rafael J. Wysocki
2013-02-07 0:51 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07 0:55 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > The only useful thing that the ACPI container driver does is to
> > install system notify handlers for all container and module device
> > objects it finds in the namespace. The driver structure,
> > acpi_container_driver, and the data structures created by its
> > .add() callback are in fact not used by the driver, so remove
> > them entirely.
> >
> > It also makes a little sense to build that driver as a module,
> > so make it non-modular and add its initialization to the
> > namespace scanning code.
> >
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers more straightforward.
>
> I think the container driver needs to be registered as an ACPI scan
> driver so that sysfs eject will continue to work for container devices,
> such as ACPI0004:XX/eject. Since the container driver does not support
> ACPI eject notification (and we have been discussing how system device
> hot-plug should work), this sysfs eject is the only way to eject a
> container device at this point. I will send an update patchset that
> applies on top of this patch.
>
> With the update in my patchset:
> Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Thanks, but I'd like to (1) apply your patch from
https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
into my [2/2], if you don't mind, and apply that next.
Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
actually makes sense after the recent changes to acpi_bus_trim(), because that
can't fail now, so the eject will always be carried out. So perhaps we can
simply remove the acpi_device->driver check from there entirely in the first
place?
If we really want to be able to prevent ejects from happening in some cases,
we need to implement something along the lines discussed with Greg.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-07 0:55 ` Rafael J. Wysocki
@ 2013-02-07 0:51 ` Toshi Kani
2013-02-07 1:32 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-07 0:51 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > The only useful thing that the ACPI container driver does is to
> > > install system notify handlers for all container and module device
> > > objects it finds in the namespace. The driver structure,
> > > acpi_container_driver, and the data structures created by its
> > > .add() callback are in fact not used by the driver, so remove
> > > them entirely.
> > >
> > > It also makes a little sense to build that driver as a module,
> > > so make it non-modular and add its initialization to the
> > > namespace scanning code.
> > >
> > > In addition to that, make the namespace walk callback used for
> > > installing the notify handlers more straightforward.
> >
> > I think the container driver needs to be registered as an ACPI scan
> > driver so that sysfs eject will continue to work for container devices,
> > such as ACPI0004:XX/eject. Since the container driver does not support
> > ACPI eject notification (and we have been discussing how system device
> > hot-plug should work), this sysfs eject is the only way to eject a
> > container device at this point. I will send an update patchset that
> > applies on top of this patch.
> >
> > With the update in my patchset:
> > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
>
> Thanks, but I'd like to (1) apply your patch from
> https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> into my [2/2], if you don't mind, and apply that next.
That's fine by me.
> Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> actually makes sense after the recent changes to acpi_bus_trim(), because that
> can't fail now, so the eject will always be carried out. So perhaps we can
> simply remove the acpi_device->driver check from there entirely in the first
> place?
>
> If we really want to be able to prevent ejects from happening in some cases,
> we need to implement something along the lines discussed with Greg.
acpi_bus_trim() cannot fail, but sysfs eject can fail. So, I think it
makes sense to do some validation before calling acpi_bus_trim(). If we
are to implement the no_eject flag thing, that check needs to be made
before calling acpi_bus_trim().
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-07 0:51 ` Toshi Kani
@ 2013-02-07 1:32 ` Rafael J. Wysocki
2013-02-07 14:32 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07 1:32 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > >
> > > > The only useful thing that the ACPI container driver does is to
> > > > install system notify handlers for all container and module device
> > > > objects it finds in the namespace. The driver structure,
> > > > acpi_container_driver, and the data structures created by its
> > > > .add() callback are in fact not used by the driver, so remove
> > > > them entirely.
> > > >
> > > > It also makes a little sense to build that driver as a module,
> > > > so make it non-modular and add its initialization to the
> > > > namespace scanning code.
> > > >
> > > > In addition to that, make the namespace walk callback used for
> > > > installing the notify handlers more straightforward.
> > >
> > > I think the container driver needs to be registered as an ACPI scan
> > > driver so that sysfs eject will continue to work for container devices,
> > > such as ACPI0004:XX/eject. Since the container driver does not support
> > > ACPI eject notification (and we have been discussing how system device
> > > hot-plug should work), this sysfs eject is the only way to eject a
> > > container device at this point. I will send an update patchset that
> > > applies on top of this patch.
> > >
> > > With the update in my patchset:
> > > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> >
> > Thanks, but I'd like to (1) apply your patch from
> > https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> > into my [2/2], if you don't mind, and apply that next.
>
> That's fine by me.
>
> > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > can't fail now, so the eject will always be carried out. So perhaps we can
> > simply remove the acpi_device->driver check from there entirely in the first
> > place?
> >
> > If we really want to be able to prevent ejects from happening in some cases,
> > we need to implement something along the lines discussed with Greg.
>
> acpi_bus_trim() cannot fail, but sysfs eject can fail. So, I think it
> makes sense to do some validation before calling acpi_bus_trim(). If we
> are to implement the no_eject flag thing, that check needs to be made
> before calling acpi_bus_trim().
Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
devices that have no ACPI drivers", so I'm wondering what the purpose of this
is. It definitely isn't too obvious. :-)
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-07 1:32 ` Rafael J. Wysocki
@ 2013-02-07 14:32 ` Toshi Kani
2013-02-07 22:42 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-07 14:32 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > >
> > > > > The only useful thing that the ACPI container driver does is to
> > > > > install system notify handlers for all container and module device
> > > > > objects it finds in the namespace. The driver structure,
> > > > > acpi_container_driver, and the data structures created by its
> > > > > .add() callback are in fact not used by the driver, so remove
> > > > > them entirely.
> > > > >
> > > > > It also makes a little sense to build that driver as a module,
> > > > > so make it non-modular and add its initialization to the
> > > > > namespace scanning code.
> > > > >
> > > > > In addition to that, make the namespace walk callback used for
> > > > > installing the notify handlers more straightforward.
> > > >
> > > > I think the container driver needs to be registered as an ACPI scan
> > > > driver so that sysfs eject will continue to work for container devices,
> > > > such as ACPI0004:XX/eject. Since the container driver does not support
> > > > ACPI eject notification (and we have been discussing how system device
> > > > hot-plug should work), this sysfs eject is the only way to eject a
> > > > container device at this point. I will send an update patchset that
> > > > applies on top of this patch.
> > > >
> > > > With the update in my patchset:
> > > > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> > >
> > > Thanks, but I'd like to (1) apply your patch from
> > > https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> > > into my [2/2], if you don't mind, and apply that next.
> >
> > That's fine by me.
> >
> > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > can't fail now, so the eject will always be carried out. So perhaps we can
> > > simply remove the acpi_device->driver check from there entirely in the first
> > > place?
> > >
> > > If we really want to be able to prevent ejects from happening in some cases,
> > > we need to implement something along the lines discussed with Greg.
> >
> > acpi_bus_trim() cannot fail, but sysfs eject can fail. So, I think it
> > makes sense to do some validation before calling acpi_bus_trim(). If we
> > are to implement the no_eject flag thing, that check needs to be made
> > before calling acpi_bus_trim().
>
> Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> devices that have no ACPI drivers", so I'm wondering what the purpose of this
> is. It definitely isn't too obvious. :-)
The check sounds odd for container, but is necessary for CPU and memory
for now. CPU and memory go online without their ACPI drivers at boot.
So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
without attempting to offline when the ACPI drivers are not bound. Of
course, we have the issue of a failure in offline be ignored, so this
offlining part needs to be moved out from acpi_bus_trim() in one way or
the other.
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-07 14:32 ` Toshi Kani
@ 2013-02-07 22:42 ` Rafael J. Wysocki
2013-02-08 1:05 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07 22:42 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > > > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > > > >
> > > > > > The only useful thing that the ACPI container driver does is to
> > > > > > install system notify handlers for all container and module device
> > > > > > objects it finds in the namespace. The driver structure,
> > > > > > acpi_container_driver, and the data structures created by its
> > > > > > .add() callback are in fact not used by the driver, so remove
> > > > > > them entirely.
> > > > > >
> > > > > > It also makes a little sense to build that driver as a module,
> > > > > > so make it non-modular and add its initialization to the
> > > > > > namespace scanning code.
> > > > > >
> > > > > > In addition to that, make the namespace walk callback used for
> > > > > > installing the notify handlers more straightforward.
> > > > >
> > > > > I think the container driver needs to be registered as an ACPI scan
> > > > > driver so that sysfs eject will continue to work for container devices,
> > > > > such as ACPI0004:XX/eject. Since the container driver does not support
> > > > > ACPI eject notification (and we have been discussing how system device
> > > > > hot-plug should work), this sysfs eject is the only way to eject a
> > > > > container device at this point. I will send an update patchset that
> > > > > applies on top of this patch.
> > > > >
> > > > > With the update in my patchset:
> > > > > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> > > >
> > > > Thanks, but I'd like to (1) apply your patch from
> > > > https://patchwork.kernel.org/patch/2108851/ first and then (2) fold your [2/2]
> > > > into my [2/2], if you don't mind, and apply that next.
> > >
> > > That's fine by me.
> > >
> > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > can't fail now, so the eject will always be carried out. So perhaps we can
> > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > place?
> > > >
> > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > we need to implement something along the lines discussed with Greg.
> > >
> > > acpi_bus_trim() cannot fail, but sysfs eject can fail. So, I think it
> > > makes sense to do some validation before calling acpi_bus_trim(). If we
> > > are to implement the no_eject flag thing, that check needs to be made
> > > before calling acpi_bus_trim().
> >
> > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > is. It definitely isn't too obvious. :-)
>
> The check sounds odd for container, but is necessary for CPU and memory
> for now. CPU and memory go online without their ACPI drivers at boot.
> So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> without attempting to offline when the ACPI drivers are not bound. Of
> course, we have the issue of a failure in offline be ignored, so this
> offlining part needs to be moved out from acpi_bus_trim() in one way or
> the other.
That was my point.
I'm going to add that change for now, but I think we need to take a step back
and talk about how we want the whole eject machinery to work, regardless of
the offline/online problem.
I think that it should work in the same way for all things that may be ejected
or inserted. Namely, they all should use the same notify handler, for example,
and if we generate a uevent for one, we should do that for all of them.
Question is how that notify handler should work and here there are two chices
in my view: Either we'll always emit a uevent and wait for user space to start
the eject procedure via sysfs, or we won't emit uevents at all and rely on the
"no_eject" flag to trigger if something is not ready. I'm basically fine with
any of them (the "no_eject" flag may be useful even if we rely on user space
to offline stuff before triggering the eject in my opinion), but if we're going
to rely on user space, then there needs to be a timeout for letting the BIOS
know that the eject has failed.
[There may be a flag for the common code telling it whether to emit a uevent
and wait for user space to trigger eject or to trigger eject by itself.]
Next, I think there needs to be a global list of IDs for which we'll install
hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
So, if a device ID is on that list, we'll install the (common) hot-plug notify
handler for its ACPI handle and we'll set an "eject_possible" flag in its
struct acpi_device (when created). That will need to be done for every scan
of the ACPI namespace and not just once, BTW. And we'll check the
"eject_possible" flag in acpi_eject_store() instead of the "does it have a
driver or scan handler" check.
Then, the scan handlers for hot-plug devices will be able to add their IDs to
that global list instead of walking the namespace and installing notify handlers
by themselves (which as I said has a problem that it's done once, while it
should be done every time acpi_bus_scan() runs).
I wonder what you think.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-07 22:42 ` Rafael J. Wysocki
@ 2013-02-08 1:05 ` Toshi Kani
2013-02-08 12:52 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-08 1:05 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Thu, 2013-02-07 at 23:42 +0100, Rafael J. Wysocki wrote:
> On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> > On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
:
> > > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > > can't fail now, so the eject will always be carried out. So perhaps we can
> > > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > > place?
> > > > >
> > > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > > we need to implement something along the lines discussed with Greg.
> > > >
> > > > acpi_bus_trim() cannot fail, but sysfs eject can fail. So, I think it
> > > > makes sense to do some validation before calling acpi_bus_trim(). If we
> > > > are to implement the no_eject flag thing, that check needs to be made
> > > > before calling acpi_bus_trim().
> > >
> > > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > > is. It definitely isn't too obvious. :-)
> >
> > The check sounds odd for container, but is necessary for CPU and memory
> > for now. CPU and memory go online without their ACPI drivers at boot.
> > So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> > without attempting to offline when the ACPI drivers are not bound. Of
> > course, we have the issue of a failure in offline be ignored, so this
> > offlining part needs to be moved out from acpi_bus_trim() in one way or
> > the other.
>
> That was my point.
>
> I'm going to add that change for now, but I think we need to take a step back
> and talk about how we want the whole eject machinery to work, regardless of
> the offline/online problem.
Right.
> I think that it should work in the same way for all things that may be ejected
> or inserted. Namely, they all should use the same notify handler, for example,
> and if we generate a uevent for one, we should do that for all of them.
Agreed.
> Question is how that notify handler should work and here there are two chices
> in my view: Either we'll always emit a uevent and wait for user space to start
> the eject procedure via sysfs, or we won't emit uevents at all and rely on the
> "no_eject" flag to trigger if something is not ready. I'm basically fine with
> any of them (the "no_eject" flag may be useful even if we rely on user space
> to offline stuff before triggering the eject in my opinion), but if we're going
> to rely on user space, then there needs to be a timeout for letting the BIOS
> know that the eject has failed.
>
> [There may be a flag for the common code telling it whether to emit a uevent
> and wait for user space to trigger eject or to trigger eject by itself.]
IMHO, the kernel waiting for a user program to complete is a recipe for
future problems. So, I think two possible implementation choices are:
1. Upon an eject request, off-line all devices and eject
=> Implement a kernel sequencer (my RFC patchset)
2. Upon an eject request, eject if all devices are off-lined beforehand
=> Implement the "no_eject" approach
Since we are heading to the user space approach, we need to go with #2.
There are some challenges with #2, ex. if sysfs memory online/offline
interfaces can correspond with ACPI memory objects, which we will also
need to look into.
> Next, I think there needs to be a global list of IDs for which we'll install
> hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
> So, if a device ID is on that list, we'll install the (common) hot-plug notify
> handler for its ACPI handle and we'll set an "eject_possible" flag in its
> struct acpi_device (when created). That will need to be done for every scan
> of the ACPI namespace and not just once, BTW. And we'll check the
> "eject_possible" flag in acpi_eject_store() instead of the "does it have a
> driver or scan handler" check.
>
> Then, the scan handlers for hot-plug devices will be able to add their IDs to
> that global list instead of walking the namespace and installing notify handlers
> by themselves (which as I said has a problem that it's done once, while it
> should be done every time acpi_bus_scan() runs).
I agree. I think we can use the global notify handler (as the common
notify handler) to look up the eject_possible ID list, instead of
installing a notify handler to each device.
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-08 1:05 ` Toshi Kani
@ 2013-02-08 12:52 ` Rafael J. Wysocki
2013-02-08 16:24 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 12:52 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Thursday, February 07, 2013 06:05:19 PM Toshi Kani wrote:
> On Thu, 2013-02-07 at 23:42 +0100, Rafael J. Wysocki wrote:
> > On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> > > On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > > > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> :
> > > > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > > > can't fail now, so the eject will always be carried out. So perhaps we can
> > > > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > > > place?
> > > > > >
> > > > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > > > we need to implement something along the lines discussed with Greg.
> > > > >
> > > > > acpi_bus_trim() cannot fail, but sysfs eject can fail. So, I think it
> > > > > makes sense to do some validation before calling acpi_bus_trim(). If we
> > > > > are to implement the no_eject flag thing, that check needs to be made
> > > > > before calling acpi_bus_trim().
> > > >
> > > > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > > > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > > > is. It definitely isn't too obvious. :-)
> > >
> > > The check sounds odd for container, but is necessary for CPU and memory
> > > for now. CPU and memory go online without their ACPI drivers at boot.
> > > So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> > > without attempting to offline when the ACPI drivers are not bound. Of
> > > course, we have the issue of a failure in offline be ignored, so this
> > > offlining part needs to be moved out from acpi_bus_trim() in one way or
> > > the other.
> >
> > That was my point.
> >
> > I'm going to add that change for now, but I think we need to take a step back
> > and talk about how we want the whole eject machinery to work, regardless of
> > the offline/online problem.
>
> Right.
>
> > I think that it should work in the same way for all things that may be ejected
> > or inserted. Namely, they all should use the same notify handler, for example,
> > and if we generate a uevent for one, we should do that for all of them.
>
> Agreed.
>
> > Question is how that notify handler should work and here there are two chices
> > in my view: Either we'll always emit a uevent and wait for user space to start
> > the eject procedure via sysfs, or we won't emit uevents at all and rely on the
> > "no_eject" flag to trigger if something is not ready. I'm basically fine with
> > any of them (the "no_eject" flag may be useful even if we rely on user space
> > to offline stuff before triggering the eject in my opinion), but if we're going
> > to rely on user space, then there needs to be a timeout for letting the BIOS
> > know that the eject has failed.
> >
> > [There may be a flag for the common code telling it whether to emit a uevent
> > and wait for user space to trigger eject or to trigger eject by itself.]
>
> IMHO, the kernel waiting for a user program to complete is a recipe for
> future problems. So, I think two possible implementation choices are:
>
> 1. Upon an eject request, off-line all devices and eject
> => Implement a kernel sequencer (my RFC patchset)
>
> 2. Upon an eject request, eject if all devices are off-lined beforehand
> => Implement the "no_eject" approach
>
> Since we are heading to the user space approach, we need to go with #2.
> There are some challenges with #2, ex. if sysfs memory online/offline
> interfaces can correspond with ACPI memory objects, which we will also
> need to look into.
Sure.
> > Next, I think there needs to be a global list of IDs for which we'll install
> > hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
> > So, if a device ID is on that list, we'll install the (common) hot-plug notify
> > handler for its ACPI handle and we'll set an "eject_possible" flag in its
> > struct acpi_device (when created). That will need to be done for every scan
> > of the ACPI namespace and not just once, BTW. And we'll check the
> > "eject_possible" flag in acpi_eject_store() instead of the "does it have a
> > driver or scan handler" check.
> >
> > Then, the scan handlers for hot-plug devices will be able to add their IDs to
> > that global list instead of walking the namespace and installing notify handlers
> > by themselves (which as I said has a problem that it's done once, while it
> > should be done every time acpi_bus_scan() runs).
>
> I agree. I think we can use the global notify handler (as the common
> notify handler) to look up the eject_possible ID list, instead of
> installing a notify handler to each device.
Actually installing notify handlers for individual devices may be more
efficient, because then we'll know what device the notification is for without
looking it up.
OK, so it looks like I need to sit down and cut some more patches. :-)
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-08 12:52 ` Rafael J. Wysocki
@ 2013-02-08 16:24 ` Toshi Kani
0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-08 16:24 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML
On Fri, 2013-02-08 at 13:52 +0100, Rafael J. Wysocki wrote:
> On Thursday, February 07, 2013 06:05:19 PM Toshi Kani wrote:
> > On Thu, 2013-02-07 at 23:42 +0100, Rafael J. Wysocki wrote:
> > > On Thursday, February 07, 2013 07:32:07 AM Toshi Kani wrote:
> > > > On Thu, 2013-02-07 at 02:32 +0100, Rafael J. Wysocki wrote:
> > > > > On Wednesday, February 06, 2013 05:51:42 PM Toshi Kani wrote:
> > > > > > On Thu, 2013-02-07 at 01:55 +0100, Rafael J. Wysocki wrote:
> > > > > > > On Wednesday, February 06, 2013 03:32:18 PM Toshi Kani wrote:
> > > > > > > > On Mon, 2013-02-04 at 00:47 +0100, Rafael J. Wysocki wrote:
> > :
> > > > > > > Moreover, I'm wondering if the #ifndef FORCE_EJECT thing in acpi_eject_store()
> > > > > > > actually makes sense after the recent changes to acpi_bus_trim(), because that
> > > > > > > can't fail now, so the eject will always be carried out. So perhaps we can
> > > > > > > simply remove the acpi_device->driver check from there entirely in the first
> > > > > > > place?
> > > > > > >
> > > > > > > If we really want to be able to prevent ejects from happening in some cases,
> > > > > > > we need to implement something along the lines discussed with Greg.
> > > > > >
> > > > > > acpi_bus_trim() cannot fail, but sysfs eject can fail. So, I think it
> > > > > > makes sense to do some validation before calling acpi_bus_trim(). If we
> > > > > > are to implement the no_eject flag thing, that check needs to be made
> > > > > > before calling acpi_bus_trim().
> > > > >
> > > > > Sure, but now the logic seems to be "if FORCE_EJECT is not set, don't eject
> > > > > devices that have no ACPI drivers", so I'm wondering what the purpose of this
> > > > > is. It definitely isn't too obvious. :-)
> > > >
> > > > The check sounds odd for container, but is necessary for CPU and memory
> > > > for now. CPU and memory go online without their ACPI drivers at boot.
> > > > So, without this check (i.e. FORCE_EJECT is set), it simply ejects them
> > > > without attempting to offline when the ACPI drivers are not bound. Of
> > > > course, we have the issue of a failure in offline be ignored, so this
> > > > offlining part needs to be moved out from acpi_bus_trim() in one way or
> > > > the other.
> > >
> > > That was my point.
> > >
> > > I'm going to add that change for now, but I think we need to take a step back
> > > and talk about how we want the whole eject machinery to work, regardless of
> > > the offline/online problem.
> >
> > Right.
> >
> > > I think that it should work in the same way for all things that may be ejected
> > > or inserted. Namely, they all should use the same notify handler, for example,
> > > and if we generate a uevent for one, we should do that for all of them.
> >
> > Agreed.
> >
> > > Question is how that notify handler should work and here there are two chices
> > > in my view: Either we'll always emit a uevent and wait for user space to start
> > > the eject procedure via sysfs, or we won't emit uevents at all and rely on the
> > > "no_eject" flag to trigger if something is not ready. I'm basically fine with
> > > any of them (the "no_eject" flag may be useful even if we rely on user space
> > > to offline stuff before triggering the eject in my opinion), but if we're going
> > > to rely on user space, then there needs to be a timeout for letting the BIOS
> > > know that the eject has failed.
> > >
> > > [There may be a flag for the common code telling it whether to emit a uevent
> > > and wait for user space to trigger eject or to trigger eject by itself.]
> >
> > IMHO, the kernel waiting for a user program to complete is a recipe for
> > future problems. So, I think two possible implementation choices are:
> >
> > 1. Upon an eject request, off-line all devices and eject
> > => Implement a kernel sequencer (my RFC patchset)
> >
> > 2. Upon an eject request, eject if all devices are off-lined beforehand
> > => Implement the "no_eject" approach
> >
> > Since we are heading to the user space approach, we need to go with #2.
> > There are some challenges with #2, ex. if sysfs memory online/offline
> > interfaces can correspond with ACPI memory objects, which we will also
> > need to look into.
>
> Sure.
>
> > > Next, I think there needs to be a global list of IDs for which we'll install
> > > hot-plug notify handlers and which we'll allow to be ejected via /sys/.../eject.
> > > So, if a device ID is on that list, we'll install the (common) hot-plug notify
> > > handler for its ACPI handle and we'll set an "eject_possible" flag in its
> > > struct acpi_device (when created). That will need to be done for every scan
> > > of the ACPI namespace and not just once, BTW. And we'll check the
> > > "eject_possible" flag in acpi_eject_store() instead of the "does it have a
> > > driver or scan handler" check.
> > >
> > > Then, the scan handlers for hot-plug devices will be able to add their IDs to
> > > that global list instead of walking the namespace and installing notify handlers
> > > by themselves (which as I said has a problem that it's done once, while it
> > > should be done every time acpi_bus_scan() runs).
> >
> > I agree. I think we can use the global notify handler (as the common
> > notify handler) to look up the eject_possible ID list, instead of
> > installing a notify handler to each device.
>
> Actually installing notify handlers for individual devices may be more
> efficient, because then we'll know what device the notification is for without
> looking it up.
Right. I am fine with either way as long as we can get rid of the
scanning from each driver and support dynamic ACPI namespace.
> OK, so it looks like I need to sit down and cut some more patches. :-)
Cool!
Thanks,
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-03 23:47 ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
2013-02-06 22:32 ` Toshi Kani
@ 2013-02-07 8:32 ` Yasuaki Ishimatsu
2013-02-07 11:43 ` Rafael J. Wysocki
2013-02-08 0:24 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
2 siblings, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-02-07 8:32 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
Hi Rafael,
Sorry for late reply.
2013/02/04 8:47, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The only useful thing that the ACPI container driver does is to
> install system notify handlers for all container and module device
> objects it finds in the namespace. The driver structure,
> acpi_container_driver, and the data structures created by its
> .add() callback are in fact not used by the driver, so remove
> them entirely.
>
> It also makes a little sense to build that driver as a module,
> so make it non-modular and add its initialization to the
> namespace scanning code.
>
> In addition to that, make the namespace walk callback used for
> installing the notify handlers more straightforward.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
> drivers/acpi/Kconfig | 2
> drivers/acpi/container.c | 158 ++++++-----------------------------------------
> drivers/acpi/internal.h | 5 +
> drivers/acpi/scan.c | 1
> 4 files changed, 30 insertions(+), 136 deletions(-)
>
> Index: test/drivers/acpi/container.c
> ===================================================================
> --- test.orig/drivers/acpi/container.c
> +++ test/drivers/acpi/container.c
> @@ -38,41 +38,15 @@
>
> #define PREFIX "ACPI: "
>
> -#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
> -#define ACPI_CONTAINER_CLASS "container"
> -
> -#define INSTALL_NOTIFY_HANDLER 1
> -#define UNINSTALL_NOTIFY_HANDLER 2
> -
> #define _COMPONENT ACPI_CONTAINER_COMPONENT
> ACPI_MODULE_NAME("container");
>
> -MODULE_AUTHOR("Anil S Keshavamurthy");
> -MODULE_DESCRIPTION("ACPI container driver");
> -MODULE_LICENSE("GPL");
> -
> -static int acpi_container_add(struct acpi_device *device);
> -static int acpi_container_remove(struct acpi_device *device);
> -
> static const struct acpi_device_id container_device_ids[] = {
> {"ACPI0004", 0},
> {"PNP0A05", 0},
> {"PNP0A06", 0},
> {"", 0},
> };
> -MODULE_DEVICE_TABLE(acpi, container_device_ids);
> -
> -static struct acpi_driver acpi_container_driver = {
> - .name = "container",
> - .class = ACPI_CONTAINER_CLASS,
> - .ids = container_device_ids,
> - .ops = {
> - .add = acpi_container_add,
> - .remove = acpi_container_remove,
> - },
> -};
> -
> -/*******************************************************************/
>
> static int is_device_present(acpi_handle handle)
> {
> @@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
> return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
> }
>
> -static bool is_container_device(const char *hid)
> -{
> - const struct acpi_device_id *container_id;
> -
> - for (container_id = container_device_ids;
> - container_id->id[0]; container_id++) {
> - if (!strcmp((char *)container_id->id, hid))
> - return true;
> - }
> -
> - return false;
> -}
> -
> -/*******************************************************************/
> -static int acpi_container_add(struct acpi_device *device)
> -{
> - struct acpi_container *container;
> -
> - container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
> - if (!container)
> - return -ENOMEM;
> -
> - container->handle = device->handle;
> - strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
> - strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
> - device->driver_data = container;
> -
> - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
> - acpi_device_name(device), acpi_device_bid(device)));
> -
> - return 0;
> -}
> -
> -static int acpi_container_remove(struct acpi_device *device)
> -{
> - acpi_status status = AE_OK;
> - struct acpi_container *pc = NULL;
> -
> - pc = acpi_driver_data(device);
> - kfree(pc);
> - return status;
> -}
> -
> static void container_notify_cb(acpi_handle handle, u32 type, void *context)
> {
> struct acpi_device *device = NULL;
> @@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
> return;
> }
>
> -static acpi_status
> -container_walk_namespace_cb(acpi_handle handle,
> - u32 lvl, void *context, void **rv)
> +static bool is_container(acpi_handle handle)
> {
> - char *hid = NULL;
> struct acpi_device_info *info;
> - acpi_status status;
> - int *action = context;
> + bool ret = false;
>
> - status = acpi_get_object_info(handle, &info);
> - if (ACPI_FAILURE(status)) {
> - return AE_OK;
> - }
> -
> - if (info->valid & ACPI_VALID_HID)
> - hid = info->hardware_id.string;
> -
> - if (hid == NULL) {
> - goto end;
> - }
> + if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
> + return false;
>
> - if (!is_container_device(hid))
> - goto end;
> + if (info->valid & ACPI_VALID_HID) {
> + const struct acpi_device_id *id;
>
> - switch (*action) {
> - case INSTALL_NOTIFY_HANDLER:
> - acpi_install_notify_handler(handle,
> - ACPI_SYSTEM_NOTIFY,
> - container_notify_cb, NULL);
> - break;
> - case UNINSTALL_NOTIFY_HANDLER:
> - acpi_remove_notify_handler(handle,
> - ACPI_SYSTEM_NOTIFY,
> - container_notify_cb);
> - break;
> - default:
> - break;
> + for (id = container_device_ids; id->id[0]; id++) {
> + ret = !strcmp((char *)id->id, info->hardware_id.string);
> + if (ret)
> + break;
> + }
> }
> -
> - end:
> kfree(info);
> -
> - return AE_OK;
> + return ret;
> }
>
> -static int __init acpi_container_init(void)
> +static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
> + u32 lvl, void *ctxt,
> + void **retv)
> {
> - int result = 0;
> - int action = INSTALL_NOTIFY_HANDLER;
> -
> - result = acpi_bus_register_driver(&acpi_container_driver);
> - if (result < 0) {
> - return (result);
> - }
> -
> - /* register notify handler to every container device */
> - acpi_walk_namespace(ACPI_TYPE_DEVICE,
> - ACPI_ROOT_OBJECT,
> - ACPI_UINT32_MAX,
> - container_walk_namespace_cb, NULL, &action, NULL);
> + if (is_container(handle))
> + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> + container_notify_cb, NULL);
>
> - return (0);
> + return AE_OK;
> }
>
> -static void __exit acpi_container_exit(void)
> +void __init acpi_container_init(void)
> {
> - int action = UNINSTALL_NOTIFY_HANDLER;
> -
> -
> - acpi_walk_namespace(ACPI_TYPE_DEVICE,
> - ACPI_ROOT_OBJECT,
> - ACPI_UINT32_MAX,
> - container_walk_namespace_cb, NULL, &action, NULL);
> -
> - acpi_bus_unregister_driver(&acpi_container_driver);
> -
> - return;
> + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
> + acpi_container_register_notify_handler, NULL,
> + NULL, NULL);
> }
> -
> -module_init(acpi_container_init);
> -module_exit(acpi_container_exit);
> Index: test/drivers/acpi/Kconfig
> ===================================================================
> --- test.orig/drivers/acpi/Kconfig
> +++ test/drivers/acpi/Kconfig
> @@ -334,7 +334,7 @@ config X86_PM_TIMER
> systems require this timer.
>
> config ACPI_CONTAINER
> - tristate "Container and Module Devices (EXPERIMENTAL)"
> + bool "Container and Module Devices (EXPERIMENTAL)"
> depends on EXPERIMENTAL
> default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
> help
> Index: test/drivers/acpi/internal.h
> ===================================================================
> --- test.orig/drivers/acpi/internal.h
> +++ test/drivers/acpi/internal.h
> @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
> #else
> static inline void acpi_memory_hotplug_init(void) {}
> #endif
> +#ifdef ACPI_CONTAINER
It should be CONFIG_ACPI_CONTAINER. By this, acpi_container_init()
do nothing. When I fix it and test the patch, the patch goes well.
If you update the patch, I'll test again.
Thanks,
Yasuaki Ishimatsu
> +void acpi_container_init(void);
> +#else
> +static inline void acpi_container_init(void) {}
> +#endif
>
> #ifdef CONFIG_DEBUG_FS
> extern struct dentry *acpi_debugfs_dir;
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -1763,6 +1763,7 @@ int __init acpi_scan_init(void)
> acpi_platform_init();
> acpi_csrt_init();
> acpi_memory_hotplug_init();
> + acpi_container_init();
>
> /*
> * Enumerate devices in the ACPI namespace.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-07 8:32 ` Yasuaki Ishimatsu
@ 2013-02-07 11:43 ` Rafael J. Wysocki
2013-02-07 14:38 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-07 11:43 UTC (permalink / raw)
To: Yasuaki Ishimatsu
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
On Thursday, February 07, 2013 05:32:15 PM Yasuaki Ishimatsu wrote:
> Hi Rafael,
>
> Sorry for late reply.
No problem, thank you for the review.
> 2013/02/04 8:47, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > The only useful thing that the ACPI container driver does is to
> > install system notify handlers for all container and module device
> > objects it finds in the namespace. The driver structure,
> > acpi_container_driver, and the data structures created by its
> > .add() callback are in fact not used by the driver, so remove
> > them entirely.
> >
> > It also makes a little sense to build that driver as a module,
> > so make it non-modular and add its initialization to the
> > namespace scanning code.
> >
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers more straightforward.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> > drivers/acpi/Kconfig | 2
> > drivers/acpi/container.c | 158 ++++++-----------------------------------------
> > drivers/acpi/internal.h | 5 +
> > drivers/acpi/scan.c | 1
> > 4 files changed, 30 insertions(+), 136 deletions(-)
> >
> > Index: test/drivers/acpi/container.c
> > ===================================================================
> > --- test.orig/drivers/acpi/container.c
> > +++ test/drivers/acpi/container.c
> > @@ -38,41 +38,15 @@
> >
> > #define PREFIX "ACPI: "
> >
> > -#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
> > -#define ACPI_CONTAINER_CLASS "container"
> > -
> > -#define INSTALL_NOTIFY_HANDLER 1
> > -#define UNINSTALL_NOTIFY_HANDLER 2
> > -
> > #define _COMPONENT ACPI_CONTAINER_COMPONENT
> > ACPI_MODULE_NAME("container");
> >
> > -MODULE_AUTHOR("Anil S Keshavamurthy");
> > -MODULE_DESCRIPTION("ACPI container driver");
> > -MODULE_LICENSE("GPL");
> > -
> > -static int acpi_container_add(struct acpi_device *device);
> > -static int acpi_container_remove(struct acpi_device *device);
> > -
> > static const struct acpi_device_id container_device_ids[] = {
> > {"ACPI0004", 0},
> > {"PNP0A05", 0},
> > {"PNP0A06", 0},
> > {"", 0},
> > };
> > -MODULE_DEVICE_TABLE(acpi, container_device_ids);
> > -
> > -static struct acpi_driver acpi_container_driver = {
> > - .name = "container",
> > - .class = ACPI_CONTAINER_CLASS,
> > - .ids = container_device_ids,
> > - .ops = {
> > - .add = acpi_container_add,
> > - .remove = acpi_container_remove,
> > - },
> > -};
> > -
> > -/*******************************************************************/
> >
> > static int is_device_present(acpi_handle handle)
> > {
> > @@ -92,49 +66,6 @@ static int is_device_present(acpi_handle
> > return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
> > }
> >
> > -static bool is_container_device(const char *hid)
> > -{
> > - const struct acpi_device_id *container_id;
> > -
> > - for (container_id = container_device_ids;
> > - container_id->id[0]; container_id++) {
> > - if (!strcmp((char *)container_id->id, hid))
> > - return true;
> > - }
> > -
> > - return false;
> > -}
> > -
> > -/*******************************************************************/
> > -static int acpi_container_add(struct acpi_device *device)
> > -{
> > - struct acpi_container *container;
> > -
> > - container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
> > - if (!container)
> > - return -ENOMEM;
> > -
> > - container->handle = device->handle;
> > - strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
> > - strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
> > - device->driver_data = container;
> > -
> > - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
> > - acpi_device_name(device), acpi_device_bid(device)));
> > -
> > - return 0;
> > -}
> > -
> > -static int acpi_container_remove(struct acpi_device *device)
> > -{
> > - acpi_status status = AE_OK;
> > - struct acpi_container *pc = NULL;
> > -
> > - pc = acpi_driver_data(device);
> > - kfree(pc);
> > - return status;
> > -}
> > -
> > static void container_notify_cb(acpi_handle handle, u32 type, void *context)
> > {
> > struct acpi_device *device = NULL;
> > @@ -199,84 +130,41 @@ static void container_notify_cb(acpi_han
> > return;
> > }
> >
> > -static acpi_status
> > -container_walk_namespace_cb(acpi_handle handle,
> > - u32 lvl, void *context, void **rv)
> > +static bool is_container(acpi_handle handle)
> > {
> > - char *hid = NULL;
> > struct acpi_device_info *info;
> > - acpi_status status;
> > - int *action = context;
> > + bool ret = false;
> >
> > - status = acpi_get_object_info(handle, &info);
> > - if (ACPI_FAILURE(status)) {
> > - return AE_OK;
> > - }
> > -
> > - if (info->valid & ACPI_VALID_HID)
> > - hid = info->hardware_id.string;
> > -
> > - if (hid == NULL) {
> > - goto end;
> > - }
> > + if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
> > + return false;
> >
> > - if (!is_container_device(hid))
> > - goto end;
> > + if (info->valid & ACPI_VALID_HID) {
> > + const struct acpi_device_id *id;
> >
> > - switch (*action) {
> > - case INSTALL_NOTIFY_HANDLER:
> > - acpi_install_notify_handler(handle,
> > - ACPI_SYSTEM_NOTIFY,
> > - container_notify_cb, NULL);
> > - break;
> > - case UNINSTALL_NOTIFY_HANDLER:
> > - acpi_remove_notify_handler(handle,
> > - ACPI_SYSTEM_NOTIFY,
> > - container_notify_cb);
> > - break;
> > - default:
> > - break;
> > + for (id = container_device_ids; id->id[0]; id++) {
> > + ret = !strcmp((char *)id->id, info->hardware_id.string);
> > + if (ret)
> > + break;
> > + }
> > }
> > -
> > - end:
> > kfree(info);
> > -
> > - return AE_OK;
> > + return ret;
> > }
> >
> > -static int __init acpi_container_init(void)
> > +static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
> > + u32 lvl, void *ctxt,
> > + void **retv)
> > {
> > - int result = 0;
> > - int action = INSTALL_NOTIFY_HANDLER;
> > -
> > - result = acpi_bus_register_driver(&acpi_container_driver);
> > - if (result < 0) {
> > - return (result);
> > - }
> > -
> > - /* register notify handler to every container device */
> > - acpi_walk_namespace(ACPI_TYPE_DEVICE,
> > - ACPI_ROOT_OBJECT,
> > - ACPI_UINT32_MAX,
> > - container_walk_namespace_cb, NULL, &action, NULL);
> > + if (is_container(handle))
> > + acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
> > + container_notify_cb, NULL);
> >
> > - return (0);
> > + return AE_OK;
> > }
> >
> > -static void __exit acpi_container_exit(void)
> > +void __init acpi_container_init(void)
> > {
> > - int action = UNINSTALL_NOTIFY_HANDLER;
> > -
> > -
> > - acpi_walk_namespace(ACPI_TYPE_DEVICE,
> > - ACPI_ROOT_OBJECT,
> > - ACPI_UINT32_MAX,
> > - container_walk_namespace_cb, NULL, &action, NULL);
> > -
> > - acpi_bus_unregister_driver(&acpi_container_driver);
> > -
> > - return;
> > + acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
> > + acpi_container_register_notify_handler, NULL,
> > + NULL, NULL);
> > }
> > -
> > -module_init(acpi_container_init);
> > -module_exit(acpi_container_exit);
> > Index: test/drivers/acpi/Kconfig
> > ===================================================================
> > --- test.orig/drivers/acpi/Kconfig
> > +++ test/drivers/acpi/Kconfig
> > @@ -334,7 +334,7 @@ config X86_PM_TIMER
> > systems require this timer.
> >
> > config ACPI_CONTAINER
> > - tristate "Container and Module Devices (EXPERIMENTAL)"
> > + bool "Container and Module Devices (EXPERIMENTAL)"
> > depends on EXPERIMENTAL
> > default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
> > help
> > Index: test/drivers/acpi/internal.h
> > ===================================================================
> > --- test.orig/drivers/acpi/internal.h
> > +++ test/drivers/acpi/internal.h
> > @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
> > #else
> > static inline void acpi_memory_hotplug_init(void) {}
> > #endif
>
> > +#ifdef ACPI_CONTAINER
>
> It should be CONFIG_ACPI_CONTAINER.
Totally correct.
> By this, acpi_container_init() do nothing. When I fix it and test the patch,
> the patch goes well.
>
> If you update the patch, I'll test again.
This fix from Toshi Kani is necessary in addition to it, though
https://patchwork.kernel.org/patch/2108851/
because FORCE_EJECT is never set as far as I can say.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Simplify container driver
2013-02-07 11:43 ` Rafael J. Wysocki
@ 2013-02-07 14:38 ` Toshi Kani
0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-07 14:38 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Yasuaki Ishimatsu, ACPI Devel Maling List, Greg Kroah-Hartman,
Bjorn Helgaas, Mika Westerberg, Matthew Garrett, Yinghai Lu,
Jiang Liu, LKML
On Thu, 2013-02-07 at 12:43 +0100, Rafael J. Wysocki wrote:
> On Thursday, February 07, 2013 05:32:15 PM Yasuaki Ishimatsu wrote:
:
> > > Index: test/drivers/acpi/internal.h
> > > ===================================================================
> > > --- test.orig/drivers/acpi/internal.h
> > > +++ test/drivers/acpi/internal.h
> > > @@ -40,6 +40,11 @@ void acpi_memory_hotplug_init(void);
> > > #else
> > > static inline void acpi_memory_hotplug_init(void) {}
> > > #endif
> >
> > > +#ifdef ACPI_CONTAINER
> >
> > It should be CONFIG_ACPI_CONTAINER.
>
> Totally correct.
Just FYI, this change is included in my patch 2/2 as well.
https://patchwork.kernel.org/patch/2108881/
Thanks,
-Toshi
> > By this, acpi_container_init() do nothing. When I fix it and test the patch,
> > the patch goes well.
> >
> > If you update the patch, I'll test again.
>
> This fix from Toshi Kani is necessary in addition to it, though
>
> https://patchwork.kernel.org/patch/2108851/
>
> because FORCE_EJECT is never set as far as I can say.
>
> Thanks,
> Rafael
>
>
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
2013-02-03 23:47 ` [PATCH 2/2] ACPI / scan: Simplify container driver Rafael J. Wysocki
2013-02-06 22:32 ` Toshi Kani
2013-02-07 8:32 ` Yasuaki Ishimatsu
@ 2013-02-08 0:24 ` Rafael J. Wysocki
2013-02-08 0:25 ` [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store() Rafael J. Wysocki
` (4 more replies)
2 siblings, 5 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 0:24 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML,
Yasuaki Ishimatsu
On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The only useful thing that the ACPI container driver does is to
> install system notify handlers for all container and module device
> objects it finds in the namespace. The driver structure,
> acpi_container_driver, and the data structures created by its
> .add() callback are in fact not used by the driver, so remove
> them entirely.
>
> It also makes a little sense to build that driver as a module,
> so make it non-modular and add its initialization to the
> namespace scanning code.
>
> In addition to that, make the namespace walk callback used for
> installing the notify handlers more straightforward.
As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
fail for containers and it is the only way to eject them currently, so patch
[2/2] is an improved version of this (with Toshi's changes folded in).
Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store()
2013-02-08 0:24 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
@ 2013-02-08 0:25 ` Rafael J. Wysocki
2013-02-08 0:27 ` [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler Rafael J. Wysocki
` (3 subsequent siblings)
4 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 0:25 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML,
Yasuaki Ishimatsu
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Since the FORCE_EJECT symbol is never defined, the
#ifndef FORCE_EJECT in acpi_eject_store() is always true, so drop it.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/scan.c | 2 --
1 file changed, 2 deletions(-)
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -202,12 +202,10 @@ acpi_eject_store(struct device *d, struc
if ((!count) || (buf[0] != '1')) {
return -EINVAL;
}
-#ifndef FORCE_EJECT
if (!acpi_device->driver && !acpi_device->handler) {
ret = -ENODEV;
goto err;
}
-#endif
status = acpi_get_type(acpi_device->handle, &type);
if (ACPI_FAILURE(status) || (!acpi_device->flags.ejectable)) {
ret = -ENODEV;
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler
2013-02-08 0:24 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
2013-02-08 0:25 ` [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store() Rafael J. Wysocki
@ 2013-02-08 0:27 ` Rafael J. Wysocki
2013-02-08 3:32 ` Yinghai Lu
2013-02-08 3:19 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver Yasuaki Ishimatsu
` (2 subsequent siblings)
4 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 0:27 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, Toshi Kani, LKML,
Yasuaki Ishimatsu
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Make the ACPI container driver use struct acpi_scan_handler for
representing the object used to initialize ACPI containers and remove
the ACPI driver structure used previously and the data structures
created by it, since in fact they were not used for any purpose.
This simplifies the code and reduces the kernel's memory footprint by
avoiding the registration of a struct device_driver object with the
driver core and creation of its sysfs directory which is unnecessary.
In addition to that, make the namespace walk callback used for
installing the notify handlers for ACPI containers more
straightforward.
This change includes fixes from Toshi Kani.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/Kconfig | 2
drivers/acpi/container.c | 167 ++++++++++-------------------------------------
drivers/acpi/internal.h | 5 +
drivers/acpi/scan.c | 1
4 files changed, 43 insertions(+), 132 deletions(-)
Index: test/drivers/acpi/container.c
===================================================================
--- test.orig/drivers/acpi/container.c
+++ test/drivers/acpi/container.c
@@ -38,42 +38,31 @@
#define PREFIX "ACPI: "
-#define ACPI_CONTAINER_DEVICE_NAME "ACPI container device"
-#define ACPI_CONTAINER_CLASS "container"
-
-#define INSTALL_NOTIFY_HANDLER 1
-#define UNINSTALL_NOTIFY_HANDLER 2
-
#define _COMPONENT ACPI_CONTAINER_COMPONENT
ACPI_MODULE_NAME("container");
-MODULE_AUTHOR("Anil S Keshavamurthy");
-MODULE_DESCRIPTION("ACPI container driver");
-MODULE_LICENSE("GPL");
-
-static int acpi_container_add(struct acpi_device *device);
-static int acpi_container_remove(struct acpi_device *device);
-
static const struct acpi_device_id container_device_ids[] = {
{"ACPI0004", 0},
{"PNP0A05", 0},
{"PNP0A06", 0},
{"", 0},
};
-MODULE_DEVICE_TABLE(acpi, container_device_ids);
-static struct acpi_driver acpi_container_driver = {
- .name = "container",
- .class = ACPI_CONTAINER_CLASS,
+static int container_device_attach(struct acpi_device *device,
+ const struct acpi_device_id *not_used)
+{
+ /*
+ * FIXME: This is necessary, so that acpi_eject_store() doesn't return
+ * -ENODEV for containers.
+ */
+ return 1;
+}
+
+static struct acpi_scan_handler container_device_handler = {
.ids = container_device_ids,
- .ops = {
- .add = acpi_container_add,
- .remove = acpi_container_remove,
- },
+ .attach = container_device_attach,
};
-/*******************************************************************/
-
static int is_device_present(acpi_handle handle)
{
acpi_handle temp;
@@ -92,49 +81,6 @@ static int is_device_present(acpi_handle
return ((sta & ACPI_STA_DEVICE_PRESENT) == ACPI_STA_DEVICE_PRESENT);
}
-static bool is_container_device(const char *hid)
-{
- const struct acpi_device_id *container_id;
-
- for (container_id = container_device_ids;
- container_id->id[0]; container_id++) {
- if (!strcmp((char *)container_id->id, hid))
- return true;
- }
-
- return false;
-}
-
-/*******************************************************************/
-static int acpi_container_add(struct acpi_device *device)
-{
- struct acpi_container *container;
-
- container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
- if (!container)
- return -ENOMEM;
-
- container->handle = device->handle;
- strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
- strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
- device->driver_data = container;
-
- ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device <%s> bid <%s>\n",
- acpi_device_name(device), acpi_device_bid(device)));
-
- return 0;
-}
-
-static int acpi_container_remove(struct acpi_device *device)
-{
- acpi_status status = AE_OK;
- struct acpi_container *pc = NULL;
-
- pc = acpi_driver_data(device);
- kfree(pc);
- return status;
-}
-
static void container_notify_cb(acpi_handle handle, u32 type, void *context)
{
struct acpi_device *device = NULL;
@@ -199,84 +145,43 @@ static void container_notify_cb(acpi_han
return;
}
-static acpi_status
-container_walk_namespace_cb(acpi_handle handle,
- u32 lvl, void *context, void **rv)
+static bool is_container(acpi_handle handle)
{
- char *hid = NULL;
struct acpi_device_info *info;
- acpi_status status;
- int *action = context;
-
- status = acpi_get_object_info(handle, &info);
- if (ACPI_FAILURE(status)) {
- return AE_OK;
- }
+ bool ret = false;
- if (info->valid & ACPI_VALID_HID)
- hid = info->hardware_id.string;
+ if (ACPI_FAILURE(acpi_get_object_info(handle, &info)))
+ return false;
- if (hid == NULL) {
- goto end;
- }
-
- if (!is_container_device(hid))
- goto end;
+ if (info->valid & ACPI_VALID_HID) {
+ const struct acpi_device_id *id;
- switch (*action) {
- case INSTALL_NOTIFY_HANDLER:
- acpi_install_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb, NULL);
- break;
- case UNINSTALL_NOTIFY_HANDLER:
- acpi_remove_notify_handler(handle,
- ACPI_SYSTEM_NOTIFY,
- container_notify_cb);
- break;
- default:
- break;
+ for (id = container_device_ids; id->id[0]; id++) {
+ ret = !strcmp((char *)id->id, info->hardware_id.string);
+ if (ret)
+ break;
+ }
}
-
- end:
kfree(info);
-
- return AE_OK;
+ return ret;
}
-static int __init acpi_container_init(void)
+static acpi_status acpi_container_register_notify_handler(acpi_handle handle,
+ u32 lvl, void *ctxt,
+ void **retv)
{
- int result = 0;
- int action = INSTALL_NOTIFY_HANDLER;
-
- result = acpi_bus_register_driver(&acpi_container_driver);
- if (result < 0) {
- return (result);
- }
-
- /* register notify handler to every container device */
- acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb, NULL, &action, NULL);
+ if (is_container(handle))
+ acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+ container_notify_cb, NULL);
- return (0);
+ return AE_OK;
}
-static void __exit acpi_container_exit(void)
+void __init acpi_container_init(void)
{
- int action = UNINSTALL_NOTIFY_HANDLER;
-
-
- acpi_walk_namespace(ACPI_TYPE_DEVICE,
- ACPI_ROOT_OBJECT,
- ACPI_UINT32_MAX,
- container_walk_namespace_cb, NULL, &action, NULL);
+ acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+ acpi_container_register_notify_handler, NULL,
+ NULL, NULL);
- acpi_bus_unregister_driver(&acpi_container_driver);
-
- return;
+ acpi_scan_add_handler(&container_device_handler);
}
-
-module_init(acpi_container_init);
-module_exit(acpi_container_exit);
Index: test/drivers/acpi/Kconfig
===================================================================
--- test.orig/drivers/acpi/Kconfig
+++ test/drivers/acpi/Kconfig
@@ -334,7 +334,7 @@ config X86_PM_TIMER
systems require this timer.
config ACPI_CONTAINER
- tristate "Container and Module Devices (EXPERIMENTAL)"
+ bool "Container and Module Devices (EXPERIMENTAL)"
depends on EXPERIMENTAL
default (ACPI_HOTPLUG_MEMORY || ACPI_HOTPLUG_CPU || ACPI_HOTPLUG_IO)
help
Index: test/drivers/acpi/internal.h
===================================================================
--- test.orig/drivers/acpi/internal.h
+++ test/drivers/acpi/internal.h
@@ -35,6 +35,11 @@ void acpi_pci_slot_init(void);
#else
static inline void acpi_pci_slot_init(void) { }
#endif
+#ifdef CONFIG_ACPI_CONTAINER
+void acpi_container_init(void);
+#else
+static inline void acpi_container_init(void) {}
+#endif
#ifdef CONFIG_DEBUG_FS
extern struct dentry *acpi_debugfs_dir;
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -1762,6 +1762,7 @@ int __init acpi_scan_init(void)
acpi_pci_slot_init();
acpi_platform_init();
acpi_csrt_init();
+ acpi_container_init();
/*
* Enumerate devices in the ACPI namespace.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler
2013-02-08 0:27 ` [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-02-08 3:32 ` Yinghai Lu
2013-02-08 12:45 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Yinghai Lu @ 2013-02-08 3:32 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML,
Yasuaki Ishimatsu
On Thu, Feb 7, 2013 at 4:27 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Make the ACPI container driver use struct acpi_scan_handler for
> representing the object used to initialize ACPI containers and remove
> the ACPI driver structure used previously and the data structures
> created by it, since in fact they were not used for any purpose.
>
> This simplifies the code and reduces the kernel's memory footprint by
> avoiding the registration of a struct device_driver object with the
> driver core and creation of its sysfs directory which is unnecessary.
>
> In addition to that, make the namespace walk callback used for
> installing the notify handlers for ACPI containers more
> straightforward.
>
> This change includes fixes from Toshi Kani.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Yes, container support should be built-in by nature.
Acked-by: Yinghai Lu <yinghai@kernel.org>
What is the next?
dock?
Hope someone with access of dock that have pcie devices could help
sorting it out...
Thanks
Yinghai
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler
2013-02-08 3:32 ` Yinghai Lu
@ 2013-02-08 12:45 ` Rafael J. Wysocki
0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 12:45 UTC (permalink / raw)
To: Yinghai Lu
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Jiang Liu, Toshi Kani, LKML,
Yasuaki Ishimatsu
On Thursday, February 07, 2013 07:32:22 PM Yinghai Lu wrote:
> On Thu, Feb 7, 2013 at 4:27 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Make the ACPI container driver use struct acpi_scan_handler for
> > representing the object used to initialize ACPI containers and remove
> > the ACPI driver structure used previously and the data structures
> > created by it, since in fact they were not used for any purpose.
> >
> > This simplifies the code and reduces the kernel's memory footprint by
> > avoiding the registration of a struct device_driver object with the
> > driver core and creation of its sysfs directory which is unnecessary.
> >
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers for ACPI containers more
> > straightforward.
> >
> > This change includes fixes from Toshi Kani.
> >
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Yes, container support should be built-in by nature.
>
> Acked-by: Yinghai Lu <yinghai@kernel.org>
Thanks!
> What is the next?
I've sent a patch for memory hotplug already, but I'm a little concerned about
it, because after my patch users wouldn't have an option to turn memory eject
off (now they can remove the module, which is suboptimal, but at least it kind
kind of works). So I think there needs to be some sysfs-based switch for that
or something.
> dock?
It is on the radar, but it also is kind of a can of worms. :-)
> Hope someone with access of dock that have pcie devices could help
> sorting it out...
Someone having a system like that told me he was willing to test patches,
but I got distracted by something.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
2013-02-08 0:24 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
2013-02-08 0:25 ` [PATCH 1/2] ACPI / scan: Remove useless #ifndef from acpi_eject_store() Rafael J. Wysocki
2013-02-08 0:27 ` [PATCH 2/2] ACPI / scan: Make container driver use struct acpi_scan_handler Rafael J. Wysocki
@ 2013-02-08 3:19 ` Yasuaki Ishimatsu
2013-02-08 12:46 ` Rafael J. Wysocki
2013-02-08 16:57 ` Toshi Kani
2013-02-09 14:26 ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
4 siblings, 1 reply; 71+ messages in thread
From: Yasuaki Ishimatsu @ 2013-02-08 3:19 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
Hi Rafael,
2013/02/08 9:24, Rafael J. Wysocki wrote:
> On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>
>> The only useful thing that the ACPI container driver does is to
>> install system notify handlers for all container and module device
>> objects it finds in the namespace. The driver structure,
>> acpi_container_driver, and the data structures created by its
>> .add() callback are in fact not used by the driver, so remove
>> them entirely.
>>
>> It also makes a little sense to build that driver as a module,
>> so make it non-modular and add its initialization to the
>> namespace scanning code.
>>
>> In addition to that, make the namespace walk callback used for
>> installing the notify handlers more straightforward.
>
> As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> fail for containers and it is the only way to eject them currently, so patch
> [2/2] is an improved version of this (with Toshi's changes folded in).
>
> Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
I confimed the patch series works well.
Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Tested-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Thanks,
Yasuaki Ishimatsu
>
> Thanks,
> Rafael
>
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
2013-02-08 3:19 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver Yasuaki Ishimatsu
@ 2013-02-08 12:46 ` Rafael J. Wysocki
0 siblings, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 12:46 UTC (permalink / raw)
To: Yasuaki Ishimatsu
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML
On Friday, February 08, 2013 12:19:35 PM Yasuaki Ishimatsu wrote:
> Hi Rafael,
>
> 2013/02/08 9:24, Rafael J. Wysocki wrote:
> > On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> >> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >>
> >> The only useful thing that the ACPI container driver does is to
> >> install system notify handlers for all container and module device
> >> objects it finds in the namespace. The driver structure,
> >> acpi_container_driver, and the data structures created by its
> >> .add() callback are in fact not used by the driver, so remove
> >> them entirely.
> >>
> >> It also makes a little sense to build that driver as a module,
> >> so make it non-modular and add its initialization to the
> >> namespace scanning code.
> >>
> >> In addition to that, make the namespace walk callback used for
> >> installing the notify handlers more straightforward.
> >
> > As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> > fail for containers and it is the only way to eject them currently, so patch
> > [2/2] is an improved version of this (with Toshi's changes folded in).
> >
> > Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
>
> I confimed the patch series works well.
>
> Acked-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
> Tested-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Thanks a lot!
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
2013-02-08 0:24 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
` (2 preceding siblings ...)
2013-02-08 3:19 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver Yasuaki Ishimatsu
@ 2013-02-08 16:57 ` Toshi Kani
2013-02-08 19:59 ` Rafael J. Wysocki
2013-02-09 14:26 ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
4 siblings, 1 reply; 71+ messages in thread
From: Toshi Kani @ 2013-02-08 16:57 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
Yasuaki Ishimatsu
On Fri, 2013-02-08 at 01:24 +0100, Rafael J. Wysocki wrote:
> On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > The only useful thing that the ACPI container driver does is to
> > install system notify handlers for all container and module device
> > objects it finds in the namespace. The driver structure,
> > acpi_container_driver, and the data structures created by its
> > .add() callback are in fact not used by the driver, so remove
> > them entirely.
> >
> > It also makes a little sense to build that driver as a module,
> > so make it non-modular and add its initialization to the
> > namespace scanning code.
> >
> > In addition to that, make the namespace walk callback used for
> > installing the notify handlers more straightforward.
>
> As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> fail for containers and it is the only way to eject them currently, so patch
> [2/2] is an improved version of this (with Toshi's changes folded in).
>
> Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
Thanks for the update! They look good. For the series:
Reviewed-by: Toshi Kani <toshi.kani@hp.com>
Tested-by: Toshi Kani <toshi.kani@hp.com>
BTW, did you intentionally keep the struct acpi_container definition in
<acpi/container.h>? I deleted that one in my patch.
-Toshi
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
2013-02-08 16:57 ` Toshi Kani
@ 2013-02-08 19:59 ` Rafael J. Wysocki
2013-02-08 22:41 ` Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 19:59 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
Yasuaki Ishimatsu
On Friday, February 08, 2013 09:57:18 AM Toshi Kani wrote:
> On Fri, 2013-02-08 at 01:24 +0100, Rafael J. Wysocki wrote:
> > On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > >
> > > The only useful thing that the ACPI container driver does is to
> > > install system notify handlers for all container and module device
> > > objects it finds in the namespace. The driver structure,
> > > acpi_container_driver, and the data structures created by its
> > > .add() callback are in fact not used by the driver, so remove
> > > them entirely.
> > >
> > > It also makes a little sense to build that driver as a module,
> > > so make it non-modular and add its initialization to the
> > > namespace scanning code.
> > >
> > > In addition to that, make the namespace walk callback used for
> > > installing the notify handlers more straightforward.
> >
> > As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> > fail for containers and it is the only way to eject them currently, so patch
> > [2/2] is an improved version of this (with Toshi's changes folded in).
> >
> > Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
>
> Thanks for the update! They look good. For the series:
>
> Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> Tested-by: Toshi Kani <toshi.kani@hp.com>
>
> BTW, did you intentionally keep the struct acpi_container definition in
> <acpi/container.h>? I deleted that one in my patch.
No, I overlooked that part. I'll apply that part of your patch as a separate
patch on top of this one.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify container driver
2013-02-08 19:59 ` Rafael J. Wysocki
@ 2013-02-08 22:41 ` Rafael J. Wysocki
2013-02-08 23:18 ` [PATCH] ACPI: Drop the container.h header file Rafael J. Wysocki
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 22:41 UTC (permalink / raw)
To: Toshi Kani
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
Yasuaki Ishimatsu
On Friday, February 08, 2013 08:59:44 PM Rafael J. Wysocki wrote:
> On Friday, February 08, 2013 09:57:18 AM Toshi Kani wrote:
> > On Fri, 2013-02-08 at 01:24 +0100, Rafael J. Wysocki wrote:
> > > On Monday, February 04, 2013 12:47:31 AM Rafael J. Wysocki wrote:
> > > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > >
> > > > The only useful thing that the ACPI container driver does is to
> > > > install system notify handlers for all container and module device
> > > > objects it finds in the namespace. The driver structure,
> > > > acpi_container_driver, and the data structures created by its
> > > > .add() callback are in fact not used by the driver, so remove
> > > > them entirely.
> > > >
> > > > It also makes a little sense to build that driver as a module,
> > > > so make it non-modular and add its initialization to the
> > > > namespace scanning code.
> > > >
> > > > In addition to that, make the namespace walk callback used for
> > > > installing the notify handlers more straightforward.
> > >
> > > As pointed out by Toshi Kani, the above changes would make acpi_eject_store()
> > > fail for containers and it is the only way to eject them currently, so patch
> > > [2/2] is an improved version of this (with Toshi's changes folded in).
> > >
> > > Patch [1/2] is just a cleanup removing a useless #ifndef from acpi_eject_store().
> >
> > Thanks for the update! They look good. For the series:
> >
> > Reviewed-by: Toshi Kani <toshi.kani@hp.com>
> > Tested-by: Toshi Kani <toshi.kani@hp.com>
> >
> > BTW, did you intentionally keep the struct acpi_container definition in
> > <acpi/container.h>? I deleted that one in my patch.
>
> No, I overlooked that part. I'll apply that part of your patch as a separate
> patch on top of this one.
Actually, I prefer to remove container.h entirely. I'll post a patch for that
shortly.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH] ACPI: Drop the container.h header file
2013-02-08 22:41 ` Rafael J. Wysocki
@ 2013-02-08 23:18 ` Rafael J. Wysocki
2013-02-08 23:27 ` Toshi Kani
0 siblings, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-08 23:18 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Toshi Kani, Greg Kroah-Hartman, Bjorn Helgaas, Mika Westerberg,
Matthew Garrett, Yinghai Lu, Jiang Liu, LKML, Yasuaki Ishimatsu
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
The include/acpi/container.h only contains a definition of a
structure that is not used any more, so drop it entirely.
Similar change was proposed earlier by Toshi Kani.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
On top of current linux-pm.git/bleeding-edge.
Thanks,
Rafael
---
drivers/acpi/container.c | 1 -
include/acpi/container.h | 12 ------------
2 files changed, 13 deletions(-)
Index: test/include/acpi/container.h
===================================================================
--- test.orig/include/acpi/container.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __ACPI_CONTAINER_H
-#define __ACPI_CONTAINER_H
-
-#include <linux/kernel.h>
-
-struct acpi_container {
- acpi_handle handle;
- unsigned long sun;
- int state;
-};
-
-#endif /* __ACPI_CONTAINER_H */
Index: test/drivers/acpi/container.c
===================================================================
--- test.orig/drivers/acpi/container.c
+++ test/drivers/acpi/container.c
@@ -34,7 +34,6 @@
#include <linux/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
-#include <acpi/container.h>
#define PREFIX "ACPI: "
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH] ACPI: Drop the container.h header file
2013-02-08 23:18 ` [PATCH] ACPI: Drop the container.h header file Rafael J. Wysocki
@ 2013-02-08 23:27 ` Toshi Kani
0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-08 23:27 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Greg Kroah-Hartman, Bjorn Helgaas,
Mika Westerberg, Matthew Garrett, Yinghai Lu, Jiang Liu, LKML,
Yasuaki Ishimatsu
On Sat, 2013-02-09 at 00:18 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The include/acpi/container.h only contains a definition of a
> structure that is not used any more, so drop it entirely.
>
> Similar change was proposed earlier by Toshi Kani.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Toshi Kani <toshi.kani@hp.com>
Thanks,
-Toshi
> ---
>
> On top of current linux-pm.git/bleeding-edge.
>
> Thanks,
> Rafael
>
> ---
> drivers/acpi/container.c | 1 -
> include/acpi/container.h | 12 ------------
> 2 files changed, 13 deletions(-)
>
> Index: test/include/acpi/container.h
> ===================================================================
> --- test.orig/include/acpi/container.h
> +++ /dev/null
> @@ -1,12 +0,0 @@
> -#ifndef __ACPI_CONTAINER_H
> -#define __ACPI_CONTAINER_H
> -
> -#include <linux/kernel.h>
> -
> -struct acpi_container {
> - acpi_handle handle;
> - unsigned long sun;
> - int state;
> -};
> -
> -#endif /* __ACPI_CONTAINER_H */
> Index: test/drivers/acpi/container.c
> ===================================================================
> --- test.orig/drivers/acpi/container.c
> +++ test/drivers/acpi/container.c
> @@ -34,7 +34,6 @@
> #include <linux/acpi.h>
> #include <acpi/acpi_bus.h>
> #include <acpi/acpi_drivers.h>
> -#include <acpi/container.h>
>
> #define PREFIX "ACPI: "
>
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal
2013-02-08 0:24 ` [PATCH 0/2] ACPI / scan: Remove useless #ifndef and simplify " Rafael J. Wysocki
` (3 preceding siblings ...)
2013-02-08 16:57 ` Toshi Kani
@ 2013-02-09 14:26 ` Rafael J. Wysocki
2013-02-09 14:29 ` [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock Rafael J. Wysocki
2013-02-09 14:31 ` [PATCH 2/2] ACPI / scan: Full transition to D3cold in acpi_device_unregister() Rafael J. Wysocki
4 siblings, 2 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-09 14:26 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Bjorn Helgaas, Mika Westerberg, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML, Yasuaki Ishimatsu
Hi,
The following two patches fix issues I've found revently in the ACPI device
hot-removal code.
Patch [1/2] makes acpi_bus_hot_remove_device() hold acpi_scan_lock around the
whole removal procedure to prevent potential race condition between
acpi_bus_scan() and a conflicting evaluation of _EJ0 from happening.
Patch [2/2] makes acpi_device_unregister() put devices (supporting that) into
D3cold to prevent potential problems with removing power from them without
preparation from happening and removes the totally wrong evaluation of _PS3
from acpi_bus_hot_remove_device().
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock
2013-02-09 14:26 ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
@ 2013-02-09 14:29 ` Rafael J. Wysocki
2013-02-11 23:42 ` Toshi Kani
2013-02-09 14:31 ` [PATCH 2/2] ACPI / scan: Full transition to D3cold in acpi_device_unregister() Rafael J. Wysocki
1 sibling, 1 reply; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-09 14:29 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Bjorn Helgaas, Mika Westerberg, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML, Yasuaki Ishimatsu
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
The ACPI scan lock has been introduced to prevent acpi_bus_scan()
and acpi_bus_trim() from running in parallel with each other for
overlapping ACPI namespace scopes. However, it is not sufficient
to do that, because if acpi_bus_scan() is run (for an overlapping
namespace scope) right after the acpi_bus_trim() in
acpi_bus_hot_remove_device(), the subsequent eject will remove
devices without removing the corresponding struct acpi_device
objects (and possibly companion "physical" device objects).
Therefore acpi_bus_hot_remove_device() has to acquire the scan
lock before carrying out the bus trimming and hold it through
the evaluation of _EJ0, so make that happen.
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/scan.c | 31 +++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -95,6 +95,8 @@ acpi_device_modalias_show(struct device
}
static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
+static void __acpi_bus_trim(struct acpi_device *start);
+
/**
* acpi_bus_hot_remove_device: hot-remove a device and its children
* @context: struct acpi_eject_event pointer (freed in this func)
@@ -114,10 +116,12 @@ void acpi_bus_hot_remove_device(void *co
acpi_status status = AE_OK;
u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
+ mutex_lock(&acpi_scan_lock);
+
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Hot-removing device %s...\n", dev_name(&device->dev)));
- acpi_bus_trim(device);
+ __acpi_bus_trim(device);
/* Device node has been released. */
device = NULL;
@@ -146,18 +150,14 @@ void acpi_bus_hot_remove_device(void *co
status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
if (ACPI_FAILURE(status)) {
if (status != AE_NOT_FOUND)
- printk(KERN_WARNING PREFIX
- "Eject device failed\n");
- goto err_out;
- }
+ acpi_handle_warn(handle, "Eject failed\n");
- kfree(context);
- return;
+ /* Tell the firmware the hot-remove operation has failed. */
+ acpi_evaluate_hotplug_ost(handle, ej_event->event,
+ ost_code, NULL);
+ }
-err_out:
- /* Inform firmware the hot-remove operation has completed w/ error */
- (void) acpi_evaluate_hotplug_ost(handle,
- ej_event->event, ost_code, NULL);
+ mutex_unlock(&acpi_scan_lock);
kfree(context);
return;
}
@@ -1686,10 +1686,8 @@ static acpi_status acpi_bus_remove(acpi_
return AE_OK;
}
-void acpi_bus_trim(struct acpi_device *start)
+static void __acpi_bus_trim(struct acpi_device *start)
{
- mutex_lock(&acpi_scan_lock);
-
/*
* Execute acpi_bus_device_detach() as a post-order callback to detach
* all ACPI drivers from the device nodes being removed.
@@ -1704,7 +1702,12 @@ void acpi_bus_trim(struct acpi_device *s
acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
acpi_bus_remove, NULL, NULL);
acpi_bus_remove(start->handle, 0, NULL, NULL);
+}
+void acpi_bus_trim(struct acpi_device *start)
+{
+ mutex_lock(&acpi_scan_lock);
+ __acpi_bus_trim(start);
mutex_unlock(&acpi_scan_lock);
}
EXPORT_SYMBOL_GPL(acpi_bus_trim);
^ permalink raw reply [flat|nested] 71+ messages in thread
* Re: [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock
2013-02-09 14:29 ` [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock Rafael J. Wysocki
@ 2013-02-11 23:42 ` Toshi Kani
0 siblings, 0 replies; 71+ messages in thread
From: Toshi Kani @ 2013-02-11 23:42 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: ACPI Devel Maling List, Bjorn Helgaas, Mika Westerberg,
Yinghai Lu, Jiang Liu, LKML, Yasuaki Ishimatsu
On Sat, 2013-02-09 at 15:29 +0100, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> The ACPI scan lock has been introduced to prevent acpi_bus_scan()
> and acpi_bus_trim() from running in parallel with each other for
> overlapping ACPI namespace scopes. However, it is not sufficient
> to do that, because if acpi_bus_scan() is run (for an overlapping
> namespace scope) right after the acpi_bus_trim() in
> acpi_bus_hot_remove_device(), the subsequent eject will remove
> devices without removing the corresponding struct acpi_device
> objects (and possibly companion "physical" device objects).
> Therefore acpi_bus_hot_remove_device() has to acquire the scan
> lock before carrying out the bus trimming and hold it through
> the evaluation of _EJ0, so make that happen.
>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Looks good.
Acked-by: Toshi Kani <toshi.kani@hp.com>
Thanks,
-Toshi
> ---
> drivers/acpi/scan.c | 31 +++++++++++++++++--------------
> 1 file changed, 17 insertions(+), 14 deletions(-)
>
> Index: test/drivers/acpi/scan.c
> ===================================================================
> --- test.orig/drivers/acpi/scan.c
> +++ test/drivers/acpi/scan.c
> @@ -95,6 +95,8 @@ acpi_device_modalias_show(struct device
> }
> static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
>
> +static void __acpi_bus_trim(struct acpi_device *start);
> +
> /**
> * acpi_bus_hot_remove_device: hot-remove a device and its children
> * @context: struct acpi_eject_event pointer (freed in this func)
> @@ -114,10 +116,12 @@ void acpi_bus_hot_remove_device(void *co
> acpi_status status = AE_OK;
> u32 ost_code = ACPI_OST_SC_NON_SPECIFIC_FAILURE; /* default */
>
> + mutex_lock(&acpi_scan_lock);
> +
> ACPI_DEBUG_PRINT((ACPI_DB_INFO,
> "Hot-removing device %s...\n", dev_name(&device->dev)));
>
> - acpi_bus_trim(device);
> + __acpi_bus_trim(device);
> /* Device node has been released. */
> device = NULL;
>
> @@ -146,18 +150,14 @@ void acpi_bus_hot_remove_device(void *co
> status = acpi_evaluate_object(handle, "_EJ0", &arg_list, NULL);
> if (ACPI_FAILURE(status)) {
> if (status != AE_NOT_FOUND)
> - printk(KERN_WARNING PREFIX
> - "Eject device failed\n");
> - goto err_out;
> - }
> + acpi_handle_warn(handle, "Eject failed\n");
>
> - kfree(context);
> - return;
> + /* Tell the firmware the hot-remove operation has failed. */
> + acpi_evaluate_hotplug_ost(handle, ej_event->event,
> + ost_code, NULL);
> + }
>
> -err_out:
> - /* Inform firmware the hot-remove operation has completed w/ error */
> - (void) acpi_evaluate_hotplug_ost(handle,
> - ej_event->event, ost_code, NULL);
> + mutex_unlock(&acpi_scan_lock);
> kfree(context);
> return;
> }
> @@ -1686,10 +1686,8 @@ static acpi_status acpi_bus_remove(acpi_
> return AE_OK;
> }
>
> -void acpi_bus_trim(struct acpi_device *start)
> +static void __acpi_bus_trim(struct acpi_device *start)
> {
> - mutex_lock(&acpi_scan_lock);
> -
> /*
> * Execute acpi_bus_device_detach() as a post-order callback to detach
> * all ACPI drivers from the device nodes being removed.
> @@ -1704,7 +1702,12 @@ void acpi_bus_trim(struct acpi_device *s
> acpi_walk_namespace(ACPI_TYPE_ANY, start->handle, ACPI_UINT32_MAX, NULL,
> acpi_bus_remove, NULL, NULL);
> acpi_bus_remove(start->handle, 0, NULL, NULL);
> +}
>
> +void acpi_bus_trim(struct acpi_device *start)
> +{
> + mutex_lock(&acpi_scan_lock);
> + __acpi_bus_trim(start);
> mutex_unlock(&acpi_scan_lock);
> }
> EXPORT_SYMBOL_GPL(acpi_bus_trim);
>
^ permalink raw reply [flat|nested] 71+ messages in thread
* [PATCH 2/2] ACPI / scan: Full transition to D3cold in acpi_device_unregister()
2013-02-09 14:26 ` [PATCH 0/2] ACPI / scan: Two fixes for device hot-removal Rafael J. Wysocki
2013-02-09 14:29 ` [PATCH 1/2] ACPI / scan: Make acpi_bus_hot_remove_device() acquire the scan lock Rafael J. Wysocki
@ 2013-02-09 14:31 ` Rafael J. Wysocki
1 sibling, 0 replies; 71+ messages in thread
From: Rafael J. Wysocki @ 2013-02-09 14:31 UTC (permalink / raw)
To: ACPI Devel Maling List
Cc: Bjorn Helgaas, Mika Westerberg, Yinghai Lu, Jiang Liu,
Toshi Kani, LKML, Yasuaki Ishimatsu
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
In order to drop reference counts of all power resources used by an
ACPI device node being removed, acpi_device_unregister() calls
acpi_power_transition(device, ACPI_STATE_D3_COLD), which effectively
transitions the device node into D3cold if it uses any power
resources. However, for some device nodes it may not be appropriate
to remove power from them entirely before putting them into D3hot
before. On the other hand, executing _PS3 for devices that don't
use power resources before removing them shouldn't really hurt.
In fact, that is done by acpi_bus_hot_remove_device(), but this is
not the right place to do it, because the bus trimming may have
caused power to be removed from the device node in question already
before.
For these reasons, make acpi_device_unregister() carry out full
power-off transition for all device nodes supporting that and remove
the direct evaluation of _PS3 from acpi_bus_hot_remove_device().
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
drivers/acpi/scan.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
Index: test/drivers/acpi/scan.c
===================================================================
--- test.orig/drivers/acpi/scan.c
+++ test/drivers/acpi/scan.c
@@ -125,12 +125,6 @@ void acpi_bus_hot_remove_device(void *co
/* Device node has been released. */
device = NULL;
- /* power off device */
- status = acpi_evaluate_object(handle, "_PS3", NULL, NULL);
- if (ACPI_FAILURE(status) && status != AE_NOT_FOUND)
- printk(KERN_WARNING PREFIX
- "Power-off device failed\n");
-
if (ACPI_SUCCESS(acpi_get_handle(handle, "_LCK", &temp))) {
arg_list.count = 1;
arg_list.pointer = &arg;
@@ -780,10 +774,11 @@ static void acpi_device_unregister(struc
device_del(&device->dev);
/*
- * Drop the reference counts of all power resources the device depends
- * on and turn off the ones that have no more references.
+ * Transition the device to D3cold to drop the reference counts of all
+ * power resources the device depends on and turn off the ones that have
+ * no more references.
*/
- acpi_power_transition(device, ACPI_STATE_D3_COLD);
+ acpi_device_set_power(device, ACPI_STATE_D3_COLD);
put_device(&device->dev);
}
^ permalink raw reply [flat|nested] 71+ messages in thread