From: Alex Williamson <alex.williamson@hp.com>
To: John Belmonte <john@neggie.net>
Cc: acpi-devel@lists.sourceforge.net,
linux-kernel <linux-kernel@vger.kernel.org>
Subject: Re: [ACPI] Re: [PATCH] filling in ACPI method access via sysfs namespace
Date: Fri, 09 Apr 2004 23:32:26 -0600 [thread overview]
Message-ID: <1081575145.2562.18.camel@wilson.home.net> (raw)
In-Reply-To: <1081566768.2562.8.camel@wilson.home.net>
On Fri, 2004-04-09 at 21:12, Alex Williamson wrote:
> We could make the store function save off the method
> parameters, then the show function would call the method with the saved
> parameters and return the results. Obviously there are some userspace
> ordering issues that could make this complicated, but it's easy to code
> on the kernel side.
Here's an implementation of this. It's a little klunky, but
certainly fills in the functionality.
Alex
===== drivers/acpi/scan.c 1.22 vs edited =====
--- 1.22/drivers/acpi/scan.c Tue Feb 3 22:29:19 2004
+++ edited/drivers/acpi/scan.c Fri Apr 9 23:02:48 2004
@@ -25,6 +25,208 @@
static LIST_HEAD(acpi_device_list);
static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
+struct acpi_handle_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct acpi_device *, struct acpi_handle_attribute *, char *);
+ ssize_t (*store)(struct acpi_device *, struct acpi_handle_attribute *, const char *, size_t);
+ union acpi_object *args;
+ size_t length;
+ spinlock_t lock;
+};
+
+static ssize_t
+acpi_device_write_raw(
+ struct acpi_device *device,
+ struct acpi_handle_attribute *attrib,
+ const char *buf,
+ size_t length)
+{
+ spin_lock(&attrib->lock);
+ if (attrib->args) {
+ kfree(attrib->args);
+ attrib->args = NULL;
+ attrib->length = 0;
+ }
+
+ attrib->args = kmalloc(length, GFP_KERNEL);
+ if (!attrib->args) {
+ spin_unlock(&attrib->lock);
+ return -ENODEV;
+ }
+
+ memcpy(attrib->args, buf, length);
+ attrib->length = length;
+ spin_unlock(&attrib->lock);
+
+ return length;
+}
+
+static ssize_t
+acpi_device_read_raw(
+ struct acpi_device *device,
+ struct acpi_handle_attribute *attrib,
+ char *buf)
+{
+ struct acpi_object_list *arg_list = NULL;
+ union acpi_object **cur_arg, *args = NULL;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ acpi_status status;
+ u32 count, i;
+ size_t size;
+
+ spin_lock(&attrib->lock);
+ count = attrib->length / sizeof(union acpi_object);
+
+ if (count) {
+ size = sizeof(struct acpi_object_list) +
+ ((count - 1) * sizeof(union acpi_object *));
+
+ arg_list = kmalloc(size, GFP_KERNEL);
+ if (!arg_list) {
+ spin_unlock(&attrib->lock);
+ return -ENODEV;
+ }
+
+ memset(arg_list, 0, size);
+ arg_list->count = count;
+
+ args = kmalloc(attrib->length, GFP_KERNEL);
+ if (!args) {
+ kfree(arg_list);
+ spin_unlock(&attrib->lock);
+ return -ENODEV;
+ }
+ memcpy(args, attrib->args, attrib->length);
+
+ cur_arg = &arg_list->pointer;
+ for (i = 0 ; i < count ; i++)
+ cur_arg[i] = &args[i];
+
+ kfree(attrib->args);
+ attrib->args = NULL;
+ attrib->length = 0;
+ }
+ spin_unlock(&attrib->lock);
+
+ status = acpi_evaluate_object(device->handle, attrib->attr.name,
+ arg_list, &buffer);
+ if (arg_list)
+ kfree(arg_list);
+ if (args)
+ kfree(args);
+
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ memcpy(buf, buffer.pointer, buffer.length);
+ acpi_os_free(buffer.pointer);
+
+ return buffer.length;
+}
+
+#define to_acpi_device(n) container_of(n, struct acpi_device, kobj)
+#define to_handle_attr(n) container_of(n, struct acpi_handle_attribute, attr);
+
+static void
+create_sysfs_files(struct acpi_device *dev)
+{
+ acpi_handle chandle = 0;
+ char pathname[ACPI_PATHNAME_MAX];
+ acpi_status status;
+ struct acpi_buffer buffer;
+ struct acpi_handle_attribute *attrib;
+ int error;
+
+ buffer.length = sizeof(pathname);
+ buffer.pointer = pathname;
+
+ while (ACPI_SUCCESS(acpi_get_next_object(ACPI_TYPE_METHOD, dev->handle,
+ chandle, &chandle))) {
+
+ memset(pathname, 0 , sizeof(pathname));
+
+ status = acpi_get_name(chandle, ACPI_SINGLE_NAME, &buffer);
+ if (ACPI_FAILURE(status))
+ continue;
+
+ attrib = kmalloc(sizeof(struct acpi_handle_attribute),
+ GFP_KERNEL);
+ if (!attrib)
+ continue;
+
+ memset(attrib, 0, sizeof(struct acpi_handle_attribute));
+
+ attrib->attr.name = kmalloc(strlen(pathname), GFP_KERNEL);
+ if (!attrib->attr.name) {
+ kfree(attrib);
+ continue;
+ }
+
+ strcpy(attrib->attr.name, pathname);
+
+ attrib->attr.mode = S_IFREG | S_IRUSR |
+ S_IWUSR | S_IRGRP | S_IWGRP;
+ attrib->show = acpi_device_read_raw;
+ attrib->store = acpi_device_write_raw;
+ spin_lock_init(&attrib->lock);
+
+ error = sysfs_create_file(&dev->kobj, &attrib->attr);
+ if (error) {
+ kfree(attrib->attr.name);
+ kfree(attrib);
+ continue;
+ }
+ }
+}
+
+extern struct dentry * sysfs_get_dentry(struct dentry *, const char *);
+
+static void
+remove_sysfs_files(struct acpi_device *dev)
+{
+ acpi_handle chandle = 0;
+ char pathname[ACPI_PATHNAME_MAX];
+ acpi_status status;
+ struct acpi_buffer buffer;
+ struct acpi_handle_attribute attrib, *old_attrib;
+ struct attribute *old_attr;
+ struct dentry *dentry;
+
+ buffer.length = sizeof(pathname);
+ buffer.pointer = pathname;
+ attrib.attr.name = pathname;
+
+ while (ACPI_SUCCESS(acpi_get_next_object(ACPI_TYPE_METHOD, dev->handle,
+ chandle, &chandle))) {
+
+ memset(pathname, 0 , sizeof(pathname));
+
+ status = acpi_get_name(chandle, ACPI_SINGLE_NAME, &buffer);
+ if (ACPI_FAILURE(status))
+ continue;
+
+ down(&(dev->kobj.dentry->d_inode->i_sem));
+ dentry = sysfs_get_dentry(dev->kobj.dentry, pathname);
+ if (!IS_ERR(dentry))
+ old_attr = dentry->d_fsdata;
+ else
+ old_attr = NULL;
+ up(&(dev->kobj.dentry->d_inode->i_sem));
+
+ sysfs_remove_file(&dev->kobj, &attrib.attr);
+
+ if (old_attr) {
+ if (strncmp(pathname, old_attr->name,
+ strlen(pathname)) != 0)
+ continue;
+
+ old_attrib = to_handle_attr(old_attr);
+ kfree(old_attr->name);
+ kfree(old_attrib);
+ }
+ }
+}
+
static void acpi_device_release(struct kobject * kobj)
{
struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
@@ -33,7 +235,31 @@
kfree(dev);
}
+static ssize_t acpi_device_attr_show(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ struct acpi_device *device = to_acpi_device(kobj);
+ struct acpi_handle_attribute *attribute = to_handle_attr(attr);
+ return attribute->show ?
+ attribute->show(device, attribute, buf) : 0;
+}
+
+static ssize_t acpi_device_attr_store(struct kobject *kobj,
+ struct attribute *attr, const char *buf, size_t len)
+{
+ struct acpi_device *device = to_acpi_device(kobj);
+ struct acpi_handle_attribute *attribute = to_handle_attr(attr);
+ return attribute->store ?
+ attribute->store(device, attribute, buf, len) : 0;
+}
+
+static struct sysfs_ops acpi_device_sysfs_ops = {
+ .show = acpi_device_attr_show,
+ .store = acpi_device_attr_store,
+};
+
static struct kobj_type ktype_acpi_ns = {
+ .sysfs_ops = &acpi_device_sysfs_ops,
.release = acpi_device_release,
};
@@ -72,6 +298,7 @@
device->kobj.ktype = &ktype_acpi_ns;
device->kobj.kset = &acpi_namespace_kset;
kobject_add(&device->kobj);
+ create_sysfs_files(device);
}
static int
@@ -79,6 +306,7 @@
struct acpi_device *device,
int type)
{
+ remove_sysfs_files(device);
kobject_unregister(&device->kobj);
return 0;
}
@@ -706,7 +934,7 @@
switch (type) {
case ACPI_BUS_TYPE_DEVICE:
result = acpi_bus_get_status(device);
- if (ACPI_FAILURE(result) || !device->status.present) {
+ if (ACPI_FAILURE(result)) {
result = -ENOENT;
goto end;
}
next prev parent reply other threads:[~2004-04-10 5:32 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-04-08 19:49 Alex Williamson
2004-04-09 22:21 ` Alex Williamson
2004-04-10 1:52 ` [ACPI] " John Belmonte
2004-04-10 3:12 ` Alex Williamson
2004-04-10 5:31 ` John Belmonte
2004-04-10 20:42 ` Alex Williamson
2004-04-11 3:20 ` Alex Williamson
2004-04-11 22:29 ` Matthew Wilcox
2004-04-12 3:31 ` Alex Williamson
2004-04-19 15:45 ` Alex Williamson
2004-05-06 10:02 ` Pavel Machek
2004-04-10 5:32 ` Alex Williamson [this message]
[not found] <fa.n5srcao.1k1orra@ifi.uio.no>
[not found] ` <fa.e0sva3e.u5k09i@ifi.uio.no>
2004-04-12 4:13 ` Andy Lutomirski
2004-04-12 4:32 ` Alex Williamson
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=1081575145.2562.18.camel@wilson.home.net \
--to=alex.williamson@hp.com \
--cc=acpi-devel@lists.sourceforge.net \
--cc=john@neggie.net \
--cc=linux-kernel@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®