public inbox for linux-acpi@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [ACPI] Re: [PATCH] filling in ACPI method access via sysfs namespace
  2004-04-10  1:52   ` John Belmonte
@ 2004-04-10  3:12     ` Alex Williamson
  2004-04-10  5:31       ` John Belmonte
  2004-04-10  5:32       ` Alex Williamson
  0 siblings, 2 replies; 7+ messages in thread
From: Alex Williamson @ 2004-04-10  3:12 UTC (permalink / raw)
  To: John Belmonte; +Cc: acpi-devel, linux-kernel

On Fri, 2004-04-09 at 19:52, John Belmonte wrote:
> The limitation of this interface is that it's not able to call an ACPI 
> method with some arguments and get the return value, correct?

   Yes, that's unfortunately a limitation.  Most of the standard
interfaces either take no parameters or have no return value, so they
fit nicely into this framework.  I'm open to suggestions on how to work
around this.  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.  Other ideas?  Thanks,

	Alex

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ACPI] Re: [PATCH] filling in ACPI method access via sysfs namespace
  2004-04-10  3:12     ` [ACPI] " Alex Williamson
@ 2004-04-10  5:31       ` John Belmonte
  2004-04-10 20:42         ` Alex Williamson
  2004-04-10  5:32       ` Alex Williamson
  1 sibling, 1 reply; 7+ messages in thread
From: John Belmonte @ 2004-04-10  5:31 UTC (permalink / raw)
  To: Alex Williamson; +Cc: acpi-devel, linux-kernel

Alex Williamson wrote:
> On Fri, 2004-04-09 at 19:52, John Belmonte wrote:
> 
>>The limitation of this interface is that it's not able to call an ACPI 
>>method with some arguments and get the return value, correct?
> 
>    Yes, that's unfortunately a limitation.  Most of the standard
> interfaces either take no parameters or have no return value, so they
> fit nicely into this framework.  I'm open to suggestions on how to work
> around this.  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.  Other ideas?  Thanks,

You may want to look at the acpi-devel thread "[rfc] generic testing 
ACPI module", where this issue was discussed 
(http://sourceforge.net/mailarchive/message.php?msg_id=7455349).

-John


-- 
http:// if  ile.org/

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ACPI] Re: [PATCH] filling in ACPI method access via sysfs namespace
  2004-04-10  3:12     ` [ACPI] " Alex Williamson
  2004-04-10  5:31       ` John Belmonte
@ 2004-04-10  5:32       ` Alex Williamson
  1 sibling, 0 replies; 7+ messages in thread
From: Alex Williamson @ 2004-04-10  5:32 UTC (permalink / raw)
  To: John Belmonte; +Cc: acpi-devel, linux-kernel

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;
 		}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ACPI] Re: [PATCH] filling in ACPI method access via sysfs namespace
  2004-04-10 20:42         ` Alex Williamson
@ 2004-04-11  3:20           ` Alex Williamson
  2004-04-11 22:29             ` Matthew Wilcox
  0 siblings, 1 reply; 7+ messages in thread
From: Alex Williamson @ 2004-04-11  3:20 UTC (permalink / raw)
  To: John Belmonte; +Cc: acpi-devel, linux-kernel

On Sat, 2004-04-10 at 14:42, Alex Williamson wrote:
> 
>    Ok, I took a look.  The open/write/read/close interface seems to be
> the best approach.  It shouldn't be too hard, except the read/write
> interfaces don't pass in the attribute pointer like they do for the
> show/store interface.

   I made the assumption that this wasn't that big of a stretch to the
bin file interface and extended it to add the arribute pointer.  Below
is what I came up with.  There are luckly only a handful of places using
the current sysfs bin file interface, so the additional changes are
pretty small.  I'm guessing I can probably get rid of the spinlocks I
added for the previous implementation, but they're not hurting anything
for now.  Am I getting closer?  Thanks,

	Alex

 drivers/acpi/scan.c             |  236 +++++++++++++++++++++++++++++++++++++++-
 drivers/base/firmware_class.c   |    8 -
 drivers/i2c/chips/eeprom.c      |    3 
 drivers/pci/pci-sysfs.c         |    6 -
 drivers/scsi/qla2xxx/qla_os.c   |   32 ++---
 drivers/video/aty/radeon_base.c |    6 -
 drivers/zorro/zorro-sysfs.c     |    4 
 fs/sysfs/bin.c                  |    4 
 include/linux/sysfs.h           |    6 -
 9 files changed, 273 insertions(+), 32 deletions(-)

===== 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	Sat Apr 10 20:55:30 2004
@@ -25,6 +25,238 @@
 static LIST_HEAD(acpi_device_list);
 static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
 
+struct acpi_handle_attribute {
+	struct attribute attr;
+	size_t size;
+	ssize_t (*read)(struct kobject *, struct attribute *,
+	                char *, loff_t, size_t);
+	ssize_t (*write)(struct kobject *, struct attribute *,
+	                 char *, loff_t, size_t); 
+	union acpi_object *args;
+	size_t length;
+	spinlock_t lock;
+};
+
+#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 ssize_t
+acpi_device_write_raw(
+	struct kobject		*kobj,
+	struct attribute	*attr,
+	char			*buf,
+	loff_t			off,
+	size_t			length)
+{
+	struct acpi_handle_attribute *attrib = to_handle_attr(attr);
+
+	/*
+	 * Not sure if offsets should be ignored or enforced, suppose we could
+	 * pass multiple arguments that way, but this interface already
+	 * accepts multiple arguments packed into an acpi_object array
+	 */
+	if (off)
+		return -ENODEV;
+
+	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 kobject		*kobj,
+	struct attribute	*attr,
+	char			*buf,
+	loff_t			off,
+	size_t			length)
+{
+	struct acpi_device *device = to_acpi_device(kobj);
+	struct acpi_handle_attribute *attrib = to_handle_attr(attr);
+	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;
+
+	/* Ditto, see comment above */
+	if (off)
+		return -ENODEV;
+
+	spin_lock(&attrib->lock);
+
+	/*
+	 * For convenience, handle cases where the last argument
+	 * is too small.
+	 */
+	count = attrib->length / sizeof(union acpi_object);
+	if (attrib->length % sizeof(union acpi_object))
+		count++;
+
+	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;
+
+		size = count * sizeof(union acpi_object);
+		args = kmalloc(size, GFP_KERNEL);
+		if (!args) {
+			kfree(arg_list);
+			spin_unlock(&attrib->lock);
+			return -ENODEV;
+		}
+		memset(args, 0, size);
+		memcpy(args, attrib->args, min(attrib->length, size));
+
+		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;
+
+	size = min((unsigned long)buffer.length, PAGE_SIZE);
+	memcpy(buf, buffer.pointer, size);
+	acpi_os_free(buffer.pointer);
+
+	return size;
+}
+
+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 bin_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->size = PAGE_SIZE;
+		attrib->attr.mode = S_IFREG | S_IRUSR |
+		                    S_IWUSR | S_IRGRP | S_IWGRP;
+		attrib->read = acpi_device_read_raw;
+		attrib->write = acpi_device_write_raw;
+		spin_lock_init(&((struct acpi_handle_attribute *)attrib)->lock);
+
+		error = sysfs_create_bin_file(&dev->kobj, attrib);
+		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 bin_attribute         *old_attrib;
+	struct dentry                *dentry;
+
+	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;
+
+		down(&(dev->kobj.dentry->d_inode->i_sem));
+		dentry = sysfs_get_dentry(dev->kobj.dentry, pathname);
+		if (!IS_ERR(dentry))
+			old_attrib = dentry->d_fsdata;
+		else
+			old_attrib = NULL;
+		up(&(dev->kobj.dentry->d_inode->i_sem));
+		
+		if (old_attrib) {
+			if (strncmp(pathname, old_attrib->attr.name,
+			    strlen(pathname)) != 0)
+				continue;
+
+			sysfs_remove_bin_file(&dev->kobj, old_attrib);
+
+			kfree(old_attrib->attr.name);
+			kfree(old_attrib);
+		}
+	}
+}
+
 static void acpi_device_release(struct kobject * kobj)
 {
 	struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
@@ -72,6 +304,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 +312,7 @@
 	struct acpi_device	*device, 
 	int			type)
 {
+	remove_sysfs_files(device);
 	kobject_unregister(&device->kobj);
 	return 0;
 }
@@ -706,7 +940,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;
 		}
===== drivers/base/firmware_class.c 1.16 vs edited =====
--- 1.16/drivers/base/firmware_class.c	Mon Mar  1 20:01:49 2004
+++ edited/drivers/base/firmware_class.c	Sat Apr 10 15:31:43 2004
@@ -167,8 +167,8 @@
 			firmware_loading_show, firmware_loading_store);
 
 static ssize_t
-firmware_data_read(struct kobject *kobj,
-		   char *buffer, loff_t offset, size_t count)
+firmware_data_read(struct kobject *kobj, struct attribute *attr,
+                   char *buffer, loff_t offset, size_t count)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
 	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
@@ -227,8 +227,8 @@
  *	the driver as a firmware image.
  **/
 static ssize_t
-firmware_data_write(struct kobject *kobj,
-		    char *buffer, loff_t offset, size_t count)
+firmware_data_write(struct kobject *kobj, struct attribute *attr,
+                    char *buffer, loff_t offset, size_t count)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
 	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
===== drivers/i2c/chips/eeprom.c 1.6 vs edited =====
--- 1.6/drivers/i2c/chips/eeprom.c	Mon Mar 15 03:38:36 2004
+++ edited/drivers/i2c/chips/eeprom.c	Sat Apr 10 15:32:02 2004
@@ -122,7 +122,8 @@
 	up(&data->update_lock);
 }
 
-static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct kobject *kobj, struct attribute *attr,
+                           char *buf, loff_t off, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
 	struct eeprom_data *data = i2c_get_clientdata(client);
===== drivers/pci/pci-sysfs.c 1.8 vs edited =====
--- 1.8/drivers/pci/pci-sysfs.c	Mon Feb  9 21:55:42 2004
+++ edited/drivers/pci/pci-sysfs.c	Sat Apr 10 20:39:02 2004
@@ -63,7 +63,8 @@
 static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
 
 static ssize_t
-pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_config(struct kobject *kobj, struct attribute *attr,
+                char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = 64;
@@ -117,7 +118,8 @@
 }
 
 static ssize_t
-pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_config(struct kobject *kobj, struct attribute *attr,
+                 char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = count;
===== drivers/scsi/qla2xxx/qla_os.c 1.6 vs edited =====
--- 1.6/drivers/scsi/qla2xxx/qla_os.c	Wed Feb 18 20:42:35 2004
+++ edited/drivers/scsi/qla2xxx/qla_os.c	Sat Apr 10 15:34:14 2004
@@ -435,10 +435,10 @@
 int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
 void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
 
-static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *, char *, loff_t,
-    size_t);
-static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *, char *, loff_t,
-    size_t);
+static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
+static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
 static struct bin_attribute sysfs_fw_dump_attr = {
 	.attr = {
 		.name = "fw_dump",
@@ -448,10 +448,10 @@
 	.read = qla2x00_sysfs_read_fw_dump,
 	.write = qla2x00_sysfs_write_fw_dump,
 };
-static ssize_t qla2x00_sysfs_read_nvram(struct kobject *, char *, loff_t,
-    size_t);
-static ssize_t qla2x00_sysfs_write_nvram(struct kobject *, char *, loff_t,
-    size_t);
+static ssize_t qla2x00_sysfs_read_nvram(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
+static ssize_t qla2x00_sysfs_write_nvram(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
 static struct bin_attribute sysfs_nvram_attr = {
 	.attr = {
 		.name = "nvram",
@@ -473,8 +473,8 @@
 
 
 /* SysFS attributes. */
-static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -491,8 +491,8 @@
 	return (count);
 }
 
-static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -546,8 +546,8 @@
 	return (count);
 }
 
-static ssize_t qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_read_nvram(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -573,8 +573,8 @@
 	return (count);
 }
 
-static ssize_t qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_write_nvram(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
===== drivers/video/aty/radeon_base.c 1.12 vs edited =====
--- 1.12/drivers/video/aty/radeon_base.c	Fri Mar  5 03:40:50 2004
+++ edited/drivers/video/aty/radeon_base.c	Sat Apr 10 15:35:04 2004
@@ -2014,7 +2014,8 @@
 }
 
 
-static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid1(struct kobject *kobj, struct attribute *attr,
+                                 char *buf, loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -2025,7 +2026,8 @@
 }
 
 
-static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid2(struct kobject *kobj, struct attribute *attr,
+                                 char *buf, loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct pci_dev *pdev = to_pci_dev(dev);
===== drivers/zorro/zorro-sysfs.c 1.1 vs edited =====
--- 1.1/drivers/zorro/zorro-sysfs.c	Sun Jan 18 23:35:41 2004
+++ edited/drivers/zorro/zorro-sysfs.c	Sat Apr 10 15:35:55 2004
@@ -47,8 +47,8 @@
 
 static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
 
-static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
-				 size_t count)
+static ssize_t zorro_read_config(struct kobject *kobj, struct attribute *attr,
+                                 char *buf, loff_t off, size_t count)
 {
 	struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
 					   kobj));
===== fs/sysfs/bin.c 1.12 vs edited =====
--- 1.12/fs/sysfs/bin.c	Fri Aug 29 10:40:51 2003
+++ edited/fs/sysfs/bin.c	Sat Apr 10 15:36:38 2004
@@ -20,7 +20,7 @@
 	struct bin_attribute * attr = dentry->d_fsdata;
 	struct kobject * kobj = dentry->d_parent->d_fsdata;
 
-	return attr->read(kobj, buffer, off, count);
+	return attr->read(kobj, &attr->attr, buffer, off, count);
 }
 
 static ssize_t
@@ -63,7 +63,7 @@
 	struct bin_attribute *attr = dentry->d_fsdata;
 	struct kobject *kobj = dentry->d_parent->d_fsdata;
 
-	return attr->write(kobj, buffer, offset, count);
+	return attr->write(kobj, &attr->attr, buffer, offset, count);
 }
 
 static ssize_t write(struct file * file, const char __user * userbuf,
===== include/linux/sysfs.h 1.32 vs edited =====
--- 1.32/include/linux/sysfs.h	Tue Aug 12 09:53:51 2003
+++ edited/include/linux/sysfs.h	Sat Apr 10 16:32:12 2004
@@ -21,8 +21,10 @@
 struct bin_attribute {
 	struct attribute	attr;
 	size_t			size;
-	ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
-	ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
+	ssize_t (*read)(struct kobject *, struct attribute *,
+	                char *, loff_t, size_t);
+	ssize_t (*write)(struct kobject *, struct attribute *,
+	                 char *, loff_t, size_t);
 };
 
 int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ACPI] Re: [PATCH] filling in ACPI method access via sysfs namespace
  2004-04-11 22:29             ` Matthew Wilcox
@ 2004-04-12  3:31               ` Alex Williamson
  0 siblings, 0 replies; 7+ messages in thread
From: Alex Williamson @ 2004-04-12  3:31 UTC (permalink / raw)
  To: Matthew Wilcox; +Cc: John Belmonte, acpi-devel, linux-kernel

On Sun, 2004-04-11 at 16:29, Matthew Wilcox wrote:
> 
> It seems unintuitive that you have to read the file for the method to
> take effect.  How about having the write function invoke the method and
> (if there is a result) store it for later read-back via the read function?
> It should be discarded on close, of course.  A read() on a file with
> no stored result should invoke the ACPI method (on the assumption this
> is a parameter-less method) and return the result directly.  Closing a
> file should discard any result from the method.

   How's this?  It behaves the way you described, but might be doing
some questionable things with the buffer to get there.  Is there a
better place to store the return data than back into the buf passed to
write() (aka file->private_data)?  Without adding callbacks to
open/close, I'm not sure how else we can dispose of the results on
close.  Thanks,

	Alex

 drivers/acpi/scan.c             |  210 +++++++++++++++++++++++++++++++++++++++-
 drivers/base/firmware_class.c   |    8 -
 drivers/i2c/chips/eeprom.c      |    3 
 drivers/pci/pci-sysfs.c         |    6 -
 drivers/scsi/qla2xxx/qla_os.c   |   32 +++---
 drivers/video/aty/radeon_base.c |    6 -
 drivers/zorro/zorro-sysfs.c     |    4 
 fs/sysfs/bin.c                  |    5 
 include/linux/sysfs.h           |    6 -
 9 files changed, 248 insertions(+), 32 deletions(-)

===== 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	Sun Apr 11 21:22:45 2004
@@ -25,6 +25,212 @@
 static LIST_HEAD(acpi_device_list);
 static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
 
+#define to_acpi_device(n) container_of(n, struct acpi_device, kobj)
+#define to_bin_attr(n) container_of(n, struct bin_attribute, attr);
+
+#define LENGTH_OFFSET (PAGE_SIZE - sizeof(acpi_size))
+
+static ssize_t
+acpi_device_write_raw(
+	struct kobject		*kobj,
+	struct attribute	*attr,
+	char			*buf,
+	loff_t			off,
+	size_t			length)
+{
+	struct acpi_device *device = to_acpi_device(kobj);
+	struct bin_attribute *attrib = to_bin_attr(attr);
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	struct acpi_object_list *arg_list = NULL;
+	union acpi_object **cur_arg, *args = NULL;
+	acpi_status status;
+	u32 count, i;
+	size_t size;
+
+	/*
+	 * Not sure if offsets should be ignored or enforced, suppose we could
+	 * pass multiple arguments that way, but this interface already
+	 * accepts multiple arguments packed into an acpi_object array
+	 */
+	if (off)
+		return -ENODEV;
+
+	/*
+	 * For convenience, handle cases where the last argument
+	 * is too small.
+	 */
+	count = length / sizeof(union acpi_object);
+	if (length % sizeof(union acpi_object))
+		count++;
+
+	if (count) {
+		size = sizeof(struct acpi_object_list) +
+		       ((count - 1) * sizeof(union acpi_object *));
+
+		arg_list = kmalloc(size, GFP_KERNEL);
+		if (!arg_list)
+			return -ENODEV;
+
+		memset(arg_list, 0, size);
+		arg_list->count = count;
+
+		args = (union acpi_object *)buf;
+
+		cur_arg = &arg_list->pointer;
+		for (i = 0 ; i < count ; i++)
+			cur_arg[i] = &args[i];
+	}
+
+	status = acpi_evaluate_object(device->handle, attrib->attr.name,
+	                              arg_list, &buffer);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	if (arg_list)
+		kfree(arg_list);
+
+	memset(buf, 0, PAGE_SIZE);
+	memcpy(buf, buffer.pointer, min((unsigned long)buffer.length,
+	                                LENGTH_OFFSET));
+	memcpy(buf + LENGTH_OFFSET, &buffer.length, sizeof(acpi_size));
+	acpi_os_free(buffer.pointer);
+	return length;
+}
+
+static ssize_t
+acpi_device_read_raw(
+	struct kobject		*kobj,
+	struct attribute	*attr,
+	char			*buf,
+	loff_t			off,
+	size_t			length)
+{
+	struct acpi_device *device = to_acpi_device(kobj);
+	struct bin_attribute *attrib = to_bin_attr(attr);
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_size prev_length;
+	acpi_status status;
+	size_t size;
+
+	/* Ditto, see comment above */
+	if (off)
+		return -ENODEV;
+
+	memcpy(&prev_length, buf + LENGTH_OFFSET, sizeof(acpi_size));
+
+	if (prev_length) {
+		memset(buf + LENGTH_OFFSET, 0, sizeof(acpi_size));
+		return min((unsigned long)prev_length, LENGTH_OFFSET);
+	}
+
+	status = acpi_evaluate_object(device->handle, attrib->attr.name,
+	                              NULL, &buffer);
+	if (ACPI_FAILURE(status))
+		return -ENODEV;
+
+	size = min((unsigned long)buffer.length, LENGTH_OFFSET);
+	memset(buf, 0, PAGE_SIZE);
+	memcpy(buf, buffer.pointer, size);
+	acpi_os_free(buffer.pointer);
+	return size;
+}
+
+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 bin_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 bin_attribute), GFP_KERNEL);
+		if (!attrib)
+			continue;
+
+		memset(attrib, 0, sizeof(struct bin_attribute));
+
+		attrib->attr.name = kmalloc(strlen(pathname), GFP_KERNEL);
+		if (!attrib->attr.name) {
+			kfree(attrib);
+			continue;
+		}
+
+		strcpy(attrib->attr.name, pathname);
+
+		attrib->size = LENGTH_OFFSET;
+		attrib->attr.mode = S_IFREG | S_IRUSR |
+		                    S_IWUSR | S_IRGRP | S_IWGRP;
+		attrib->read = acpi_device_read_raw;
+		attrib->write = acpi_device_write_raw;
+
+		error = sysfs_create_bin_file(&dev->kobj, attrib);
+		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 bin_attribute         *old_attrib;
+	struct dentry                *dentry;
+
+	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;
+
+		down(&(dev->kobj.dentry->d_inode->i_sem));
+		dentry = sysfs_get_dentry(dev->kobj.dentry, pathname);
+		if (!IS_ERR(dentry))
+			old_attrib = dentry->d_fsdata;
+		else
+			old_attrib = NULL;
+		up(&(dev->kobj.dentry->d_inode->i_sem));
+		
+		if (old_attrib) {
+			if (strncmp(pathname, old_attrib->attr.name,
+			    strlen(pathname)) != 0)
+				continue;
+
+			sysfs_remove_bin_file(&dev->kobj, old_attrib);
+
+			kfree(old_attrib->attr.name);
+			kfree(old_attrib);
+		}
+	}
+}
+
 static void acpi_device_release(struct kobject * kobj)
 {
 	struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
@@ -72,6 +278,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 +286,7 @@
 	struct acpi_device	*device, 
 	int			type)
 {
+	remove_sysfs_files(device);
 	kobject_unregister(&device->kobj);
 	return 0;
 }
@@ -706,7 +914,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;
 		}
===== drivers/base/firmware_class.c 1.16 vs edited =====
--- 1.16/drivers/base/firmware_class.c	Mon Mar  1 20:01:49 2004
+++ edited/drivers/base/firmware_class.c	Sun Apr 11 20:16:41 2004
@@ -167,8 +167,8 @@
 			firmware_loading_show, firmware_loading_store);
 
 static ssize_t
-firmware_data_read(struct kobject *kobj,
-		   char *buffer, loff_t offset, size_t count)
+firmware_data_read(struct kobject *kobj, struct attribute *attr,
+                   char *buffer, loff_t offset, size_t count)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
 	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
@@ -227,8 +227,8 @@
  *	the driver as a firmware image.
  **/
 static ssize_t
-firmware_data_write(struct kobject *kobj,
-		    char *buffer, loff_t offset, size_t count)
+firmware_data_write(struct kobject *kobj, struct attribute *attr,
+                    char *buffer, loff_t offset, size_t count)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
 	struct firmware_priv *fw_priv = class_get_devdata(class_dev);
===== drivers/i2c/chips/eeprom.c 1.6 vs edited =====
--- 1.6/drivers/i2c/chips/eeprom.c	Mon Mar 15 03:38:36 2004
+++ edited/drivers/i2c/chips/eeprom.c	Sun Apr 11 20:16:41 2004
@@ -122,7 +122,8 @@
 	up(&data->update_lock);
 }
 
-static ssize_t eeprom_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t eeprom_read(struct kobject *kobj, struct attribute *attr,
+                           char *buf, loff_t off, size_t count)
 {
 	struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj));
 	struct eeprom_data *data = i2c_get_clientdata(client);
===== drivers/pci/pci-sysfs.c 1.8 vs edited =====
--- 1.8/drivers/pci/pci-sysfs.c	Mon Feb  9 21:55:42 2004
+++ edited/drivers/pci/pci-sysfs.c	Sun Apr 11 20:16:41 2004
@@ -63,7 +63,8 @@
 static DEVICE_ATTR(resource,S_IRUGO,pci_show_resources,NULL);
 
 static ssize_t
-pci_read_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_read_config(struct kobject *kobj, struct attribute *attr,
+                char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = 64;
@@ -117,7 +118,8 @@
 }
 
 static ssize_t
-pci_write_config(struct kobject *kobj, char *buf, loff_t off, size_t count)
+pci_write_config(struct kobject *kobj, struct attribute *attr,
+                 char *buf, loff_t off, size_t count)
 {
 	struct pci_dev *dev = to_pci_dev(container_of(kobj,struct device,kobj));
 	unsigned int size = count;
===== drivers/scsi/qla2xxx/qla_os.c 1.6 vs edited =====
--- 1.6/drivers/scsi/qla2xxx/qla_os.c	Wed Feb 18 20:42:35 2004
+++ edited/drivers/scsi/qla2xxx/qla_os.c	Sun Apr 11 20:16:41 2004
@@ -435,10 +435,10 @@
 int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha);
 void qla2x00_free_sp_pool(scsi_qla_host_t *ha);
 
-static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *, char *, loff_t,
-    size_t);
-static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *, char *, loff_t,
-    size_t);
+static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
+static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
 static struct bin_attribute sysfs_fw_dump_attr = {
 	.attr = {
 		.name = "fw_dump",
@@ -448,10 +448,10 @@
 	.read = qla2x00_sysfs_read_fw_dump,
 	.write = qla2x00_sysfs_write_fw_dump,
 };
-static ssize_t qla2x00_sysfs_read_nvram(struct kobject *, char *, loff_t,
-    size_t);
-static ssize_t qla2x00_sysfs_write_nvram(struct kobject *, char *, loff_t,
-    size_t);
+static ssize_t qla2x00_sysfs_read_nvram(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
+static ssize_t qla2x00_sysfs_write_nvram(struct kobject *, struct attribute *,
+    char *, loff_t, size_t);
 static struct bin_attribute sysfs_nvram_attr = {
 	.attr = {
 		.name = "nvram",
@@ -473,8 +473,8 @@
 
 
 /* SysFS attributes. */
-static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_read_fw_dump(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -491,8 +491,8 @@
 	return (count);
 }
 
-static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_write_fw_dump(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -546,8 +546,8 @@
 	return (count);
 }
 
-static ssize_t qla2x00_sysfs_read_nvram(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_read_nvram(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
@@ -573,8 +573,8 @@
 	return (count);
 }
 
-static ssize_t qla2x00_sysfs_write_nvram(struct kobject *kobj, char *buf,
-    loff_t off, size_t count)
+static ssize_t qla2x00_sysfs_write_nvram(struct kobject *kobj,
+    struct attribute *attr, char *buf, loff_t off, size_t count)
 {
 	struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj,
 	    struct device, kobj)));
===== drivers/video/aty/radeon_base.c 1.12 vs edited =====
--- 1.12/drivers/video/aty/radeon_base.c	Fri Mar  5 03:40:50 2004
+++ edited/drivers/video/aty/radeon_base.c	Sun Apr 11 20:16:41 2004
@@ -2014,7 +2014,8 @@
 }
 
 
-static ssize_t radeon_show_edid1(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid1(struct kobject *kobj, struct attribute *attr,
+                                 char *buf, loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -2025,7 +2026,8 @@
 }
 
 
-static ssize_t radeon_show_edid2(struct kobject *kobj, char *buf, loff_t off, size_t count)
+static ssize_t radeon_show_edid2(struct kobject *kobj, struct attribute *attr,
+                                 char *buf, loff_t off, size_t count)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 	struct pci_dev *pdev = to_pci_dev(dev);
===== drivers/zorro/zorro-sysfs.c 1.1 vs edited =====
--- 1.1/drivers/zorro/zorro-sysfs.c	Sun Jan 18 23:35:41 2004
+++ edited/drivers/zorro/zorro-sysfs.c	Sun Apr 11 20:16:41 2004
@@ -47,8 +47,8 @@
 
 static DEVICE_ATTR(resource, S_IRUGO, zorro_show_resource, NULL);
 
-static ssize_t zorro_read_config(struct kobject *kobj, char *buf, loff_t off,
-				 size_t count)
+static ssize_t zorro_read_config(struct kobject *kobj, struct attribute *attr,
+                                 char *buf, loff_t off, size_t count)
 {
 	struct zorro_dev *z = to_zorro_dev(container_of(kobj, struct device,
 					   kobj));
===== fs/sysfs/bin.c 1.12 vs edited =====
--- 1.12/fs/sysfs/bin.c	Fri Aug 29 10:40:51 2003
+++ edited/fs/sysfs/bin.c	Sun Apr 11 20:16:41 2004
@@ -20,7 +20,7 @@
 	struct bin_attribute * attr = dentry->d_fsdata;
 	struct kobject * kobj = dentry->d_parent->d_fsdata;
 
-	return attr->read(kobj, buffer, off, count);
+	return attr->read(kobj, &attr->attr, buffer, off, count);
 }
 
 static ssize_t
@@ -63,7 +63,7 @@
 	struct bin_attribute *attr = dentry->d_fsdata;
 	struct kobject *kobj = dentry->d_parent->d_fsdata;
 
-	return attr->write(kobj, buffer, offset, count);
+	return attr->write(kobj, &attr->attr, buffer, offset, count);
 }
 
 static ssize_t write(struct file * file, const char __user * userbuf,
@@ -109,6 +109,7 @@
 
 	error = -ENOMEM;
 	file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	memset(file->private_data, 0, PAGE_SIZE);
 	if (!file->private_data)
 		goto Done;
 
===== include/linux/sysfs.h 1.32 vs edited =====
--- 1.32/include/linux/sysfs.h	Tue Aug 12 09:53:51 2003
+++ edited/include/linux/sysfs.h	Sun Apr 11 20:16:41 2004
@@ -21,8 +21,10 @@
 struct bin_attribute {
 	struct attribute	attr;
 	size_t			size;
-	ssize_t (*read)(struct kobject *, char *, loff_t, size_t);
-	ssize_t (*write)(struct kobject *, char *, loff_t, size_t);
+	ssize_t (*read)(struct kobject *, struct attribute *,
+	                char *, loff_t, size_t);
+	ssize_t (*write)(struct kobject *, struct attribute *,
+	                 char *, loff_t, size_t);
 };
 
 int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [ACPI] Re: [PATCH] filling in ACPI method access via sysfs   namespace
       [not found] ` <fa.e0sva3e.u5k09i@ifi.uio.no>
@ 2004-04-12  4:13   ` Andy Lutomirski
       [not found]     ` <407A1787.5060508-YSGFQ8SKJZVDPfheJLI6IQ@public.gmane.org>
  0 siblings, 1 reply; 7+ messages in thread
From: Andy Lutomirski @ 2004-04-12  4:13 UTC (permalink / raw)
  To: Alex Williamson; +Cc: Matthew Wilcox, John Belmonte, acpi-devel, linux-kernel

Alex Williamson wrote:

> On Sun, 2004-04-11 at 16:29, Matthew Wilcox wrote:
> 
>>It seems unintuitive that you have to read the file for the method to
>>take effect.  How about having the write function invoke the method and
>>(if there is a result) store it for later read-back via the read function?
>>It should be discarded on close, of course.  A read() on a file with
>>no stored result should invoke the ACPI method (on the assumption this
>>is a parameter-less method) and return the result directly.  Closing a
>>file should discard any result from the method.
> 
> 
>    How's this?  It behaves the way you described, but might be doing
> some questionable things with the buffer to get there.  Is there a
> better place to store the return data than back into the buf passed to
> write() (aka file->private_data)?  Without adding callbacks to
> open/close, I'm not sure how else we can dispose of the results on
> close.  Thanks,

Is there any reason this shouldn't be an ioctl?

--Andy

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Re: [PATCH] filling in ACPI method access via sysfs   namespace
       [not found]     ` <407A1787.5060508-YSGFQ8SKJZVDPfheJLI6IQ@public.gmane.org>
@ 2004-04-12  4:32       ` Alex Williamson
  0 siblings, 0 replies; 7+ messages in thread
From: Alex Williamson @ 2004-04-12  4:32 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: Matthew Wilcox, John Belmonte,
	acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f, linux-kernel

On Sun, 2004-04-11 at 22:13, Andy Lutomirski wrote:

> Is there any reason this shouldn't be an ioctl?
> 

   See the thread John pointed me to on Friday:

http://sourceforge.net/mailarchive/message.php?msg_id=7455349

Matthew ended it with "sysfs does not support ioctls.  case closed." 
I'm rather fond of the methods living in the sysfs directory
structure...

	Alex



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-04-12  4:32 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <fa.n5srcao.1k1orra@ifi.uio.no>
     [not found] ` <fa.e0sva3e.u5k09i@ifi.uio.no>
2004-04-12  4:13   ` [ACPI] Re: [PATCH] filling in ACPI method access via sysfs namespace Andy Lutomirski
     [not found]     ` <407A1787.5060508-YSGFQ8SKJZVDPfheJLI6IQ@public.gmane.org>
2004-04-12  4:32       ` Alex Williamson
2004-04-08 19:49 Alex Williamson
2004-04-09 22:21 ` Alex Williamson
2004-04-10  1:52   ` John Belmonte
2004-04-10  3:12     ` [ACPI] " Alex Williamson
2004-04-10  5:31       ` John Belmonte
2004-04-10 20:42         ` Alex Williamson
2004-04-11  3:20           ` [ACPI] " Alex Williamson
2004-04-11 22:29             ` Matthew Wilcox
2004-04-12  3:31               ` [ACPI] " Alex Williamson
2004-04-10  5:32       ` Alex Williamson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox