From: Zhang Rui <rui.zhang@intel.com>
To: lenb@kernel.org
Cc: "linux-acpi@vger" <linux-acpi@vger.kernel.org>, davej@redhat.com
Subject: Re: [PATCH 13/14] ACPI: use PNPID:instance_no as bus_id of ACPI device
Date: Fri, 08 Dec 2006 17:23:43 +0800 [thread overview]
Message-ID: <1165569823.5480.6.camel@localhost.localdomain> (raw)
In-Reply-To: <1165496265.11485.87.camel@localhost.localdomain>
From: Zhang Rui <rui.zhang@intel.com>
Previously we used the device name in the DSDT, but would
crash upon encountering a duplicate. Also, exposing the
DSDT device name to the user in a patch isn't a good idea,
because it is arbitrary.
After some discussion, we finally decided to use
"PNPID:instance_no" as the bus_id of ACPI devices.
Two attributes for each device are added at the same time,
the full pathname in ACPI namespace and hardware_id if it has.
NOTE: acpi_bus_id_list is used to keep the information of PNPID
and instance number of the given PNPID. Loop the
acpi_bus_id_list to find the instance_no of the same PNPID
when register a device. If failed, i.e. we don't have a
node with this PNPID, allocate one and link it to this list.
NOTE: Now I don't take the memory free work in charge.
If necessary, I can add a reference count in
struct acpi_device_bus_id, and check the reference and
when unregister a device, i.e. memory is freed when
the reference count of a given PNPID is 0.
Signed-off-by: Li Shaohua <shaohua.li@intel.com>
---
drivers/acpi/scan.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 109 insertions(+), 9 deletions(-)
Index: linux-2.6.19/drivers/acpi/scan.c
===================================================================
--- linux-2.6.19.orig/drivers/acpi/scan.c 2006-12-08 16:20:53.000000000 +0800
+++ linux-2.6.19/drivers/acpi/scan.c 2006-12-08 16:57:20.000000000 +0800
@@ -21,9 +21,15 @@ extern struct acpi_device *acpi_root;
#define ACPI_BUS_DEVICE_NAME "System Bus"
static LIST_HEAD(acpi_device_list);
+static LIST_HEAD(acpi_bus_id_list);
DEFINE_SPINLOCK(acpi_device_lock);
LIST_HEAD(acpi_wakeup_device_list);
+struct acpi_device_bus_id{
+ char bus_id[9];
+ unsigned int instance_no;
+ struct list_head node;
+};
static int acpi_eject_operation(acpi_handle handle, int lockable)
{
struct acpi_object_list arg_list;
@@ -103,18 +109,61 @@ acpi_eject_store(struct device *d, struc
static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store);
-static void acpi_device_setup_files(struct acpi_device *dev)
+static ssize_t
+acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+
+ return sprintf(buf, "%s\n", acpi_dev->pnp.hardware_id);
+}
+static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL);
+
+static ssize_t
+acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) {
+ struct acpi_device *acpi_dev = to_acpi_device(dev);
+ struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL};
+ int result;
+
+ result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path);
+ if(result)
+ goto end;
+
+ result = sprintf(buf, "%s\n", (char*)path.pointer);
+ kfree(path.pointer);
+ end:
+ return result;
+}
+static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL);
+
+static int acpi_device_setup_files(struct acpi_device *dev)
{
acpi_status status;
acpi_handle temp;
+ int result = 0;
/*
- * If device has _EJ0, 'eject' file is created that is used to trigger
- * hot-removal function from userland.
+ * Devices gotten from FADT don't have a "path" attribute
*/
+ if(dev->handle) {
+ result = device_create_file(&dev->dev, &dev_attr_path);
+ if(result)
+ goto end;
+ }
+
+ if(dev->flags.hardware_id) {
+ result = device_create_file(&dev->dev, &dev_attr_hid);
+ if(result)
+ goto end;
+ }
+
+ /*
+ * If device has _EJ0, 'eject' file is created that is used to trigger
+ * hot-removal function from userland.
+ */
status = acpi_get_handle(dev->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
- device_create_file(&dev->dev, &dev_attr_eject);
+ result = device_create_file(&dev->dev, &dev_attr_eject);
+ end:
+ return result;
}
static void acpi_device_remove_files(struct acpi_device *dev)
@@ -129,6 +178,11 @@ static void acpi_device_remove_files(str
status = acpi_get_handle(dev->handle, "_EJ0", &temp);
if (ACPI_SUCCESS(status))
device_remove_file(&dev->dev, &dev_attr_eject);
+
+ if(dev->flags.hardware_id)
+ device_remove_file(&dev->dev, &dev_attr_hid);
+ if(dev->handle)
+ device_remove_file(&dev->dev, &dev_attr_path);
}
/* --------------------------------------------------------------------------
ACPI Bus operations
@@ -260,9 +314,12 @@ static struct bus_type acpi_bus_type = {
.uevent = acpi_device_uevent,
};
-static void acpi_device_register(struct acpi_device *device,
+static int acpi_device_register(struct acpi_device *device,
struct acpi_device *parent)
{
+ int result;
+ struct acpi_device_bus_id *acpi_device_bus_id, *new_bus_id;
+ int found = 0;
/*
* Linkage
* -------
@@ -273,7 +330,33 @@ static void acpi_device_register(struct
INIT_LIST_HEAD(&device->g_list);
INIT_LIST_HEAD(&device->wakeup_list);
+ new_bus_id = kzalloc(sizeof(struct acpi_device_bus_id), GFP_KERNEL);
+ if (!new_bus_id) {
+ printk(KERN_ERR PREFIX "Memory allocation error\n");
+ return -ENOMEM;
+ }
+
spin_lock(&acpi_device_lock);
+ /*
+ * Find suitable bus_id and instance number in acpi_bus_id_list
+ * If failed, create one and link it into acpi_bus_id_list
+ */
+ list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) {
+ if(!strcmp(acpi_device_bus_id->bus_id, device->flags.hardware_id? device->pnp.hardware_id : "PNPIDNON")) {
+ acpi_device_bus_id->instance_no ++;
+ found = 1;
+ kfree(new_bus_id);
+ break;
+ }
+ }
+ if(!found) {
+ acpi_device_bus_id = new_bus_id;
+ strcpy(acpi_device_bus_id->bus_id, device->flags.hardware_id ? device->pnp.hardware_id : "PNPIDNON");
+ acpi_device_bus_id->instance_no = 0;
+ list_add_tail(&acpi_device_bus_id->node, &acpi_bus_id_list);
+ }
+ sprintf(device->dev.bus_id, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
+
if (device->parent) {
list_add_tail(&device->node, &device->parent->children);
list_add_tail(&device->g_list, &device->parent->g_list);
@@ -287,12 +370,29 @@ static void acpi_device_register(struct
device->dev.parent = &parent->dev;
device->dev.bus = &acpi_bus_type;
device_initialize(&device->dev);
- sprintf(device->dev.bus_id, "%s", device->pnp.bus_id);
device->dev.release = &acpi_device_release;
- device_add(&device->dev);
+ result = device_add(&device->dev);
+ if(result) {
+ printk("Error adding device %s", device->dev.bus_id);
+ goto end;
+ }
+
+ result = acpi_device_setup_files(device);
+ if(result)
+ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error creating sysfs interface for device %s\n", device->dev.bus_id));
- acpi_device_setup_files(device);
device->removal_type = ACPI_BUS_REMOVAL_NORMAL;
+ return 0;
+ end:
+ spin_lock(&acpi_device_lock);
+ if (device->parent) {
+ list_del(&device->node);
+ list_del(&device->g_list);
+ } else
+ list_del(&device->g_list);
+ list_del(&device->wakeup_list);
+ spin_unlock(&acpi_device_lock);
+ return result;
}
static void acpi_device_unregister(struct acpi_device *device, int type)
@@ -1035,7 +1135,7 @@ acpi_add_single_object(struct acpi_devic
acpi_device_get_debug_info(device, handle, type);
- acpi_device_register(device, parent);
+ result = acpi_device_register(device, parent);
end:
if (!result)
next prev parent reply other threads:[~2006-12-08 9:19 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-07 12:57 [PATCH 13/14] ACPI: use PNPID:instance_no as bus_id of ACPI device Zhang Rui
2006-12-07 13:02 ` Dave Jones
2006-12-08 1:05 ` Zhang Rui
2006-12-08 7:59 ` Len Brown
2006-12-08 9:23 ` Zhang Rui [this message]
2006-12-11 6:29 ` Zhang Rui
2006-12-21 8:10 ` Len Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1165569823.5480.6.camel@localhost.localdomain \
--to=rui.zhang@intel.com \
--cc=davej@redhat.com \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.