[PATCH] Re: request_firmware() hotplug interface, third round and a halve

From: Manuel Estrada Sainz (ranty@debian.org)
Date: Wed May 21 2003 - 13:52:12 EST


On Wed, May 21, 2003 at 12:23:18AM -0700, Greg KH wrote:
> Oops, forgot to respond to this, sorry...
>
> On Sun, May 18, 2003 at 12:19:22AM +0200, Manuel Estrada Sainz wrote:
[snip]
> > - There is a timeout, changeable from userspace. Feedback on a
> > reasonable default value appreciated.
>
> Is this really needed? Especially as you now have:

 There is currently no way to know if hotplug couldn't be called at all
 or if it failed because it didn't have firmware load support.

 If that happens, we would be waiting for ever. And I'd rather make that
 a countable number of seconds :)

 I'll make '0' mean no timeout at all.

> > - Extended 'loading' semantics:
> > echo 1 > loading:
> > start a new load, and flush any data from a previous
> > partial load.
> > echo 0 > loading:
> > finish load.
> > echo -1 > loading:
> > cancel load and give an error to the driver.
>
> Looks good.
>
> I'd recommend sending the sysfs patches to Pat Mochel. He's the one to
> take those.

 Done.
 
> Some minor comments about the code:
>
> > diff --exclude=CVS -urN linux-2.5.orig/drivers/base/Makefile linux-2.5.mine/drivers/base/Makefile
> > --- linux-2.5.orig/drivers/base/Makefile 2003-05-17 20:44:03.000000000 +0200
> > +++ linux-2.5.mine/drivers/base/Makefile 2003-05-17 23:17:21.000000000 +0200
> > @@ -3,4 +3,6 @@
> > obj-y := core.o sys.o interface.o power.o bus.o \
> > driver.o class.o platform.o \
> > cpu.o firmware.o init.o
> > +obj-m := firmware_class.o firmware_sample_driver.o \
> > + firmware_sample_firmware_class.o
>
> Why make the firmware_class.o always a module? Shouldn't it only be
> included in the core, if a driver that uses it is selected?

 That was the quickest way to get modules to play with :-)

 I am not sure on how to implement "if a driver that uses it is
 selected" and not sure on where to add the Kconfig entries to make it
 available to out-of-kernel modules.

 If the approach in the attached patches is still not right, please
 complain.
 
 Maybe kbuild could allow forcing one option from another, a companion
 for 'depends', lets call it 'hard_depends'

         depends FOO
                If FOO is not there the entry won't even be shown in the
                menu.
         hard_depends FOO
                FOO gets set to satisfy the dependency.

 When trying to deselect an item that is hard_depended upon, the system
 could complain and tell you which options should be deselected or even
 offer to do it automatically.

 This would also simplify the selection of crc32 and
 compression/decompression code. And allow removal of all those comments
 like "Video4Linux support is needed for USB Multimedia device support".

> > +static inline struct class_device *to_class_dev(struct kobject *obj)
> > +{
> > + return container_of(obj,struct class_device,kobj);
> > +}
> > +static inline
> > +struct class_device_attribute *to_class_dev_attr(struct attribute *_attr)
> > +{
> > + return container_of(_attr,struct class_device_attribute,attr);
> > +}
>
> Move these two to drivers/base/base.h as they shouldn't be defined in
> two different files.

 OK, I also removed equivalent macros from class.c
 
> > +int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr);
> > +int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr);
>
> If you need these, add them to include/linux/sysfs.h.
>
> > +struct firmware_priv {
> > + char fw_id[FIRMWARE_NAME_MAX];
> > + struct completion completion;
> > + struct bin_attribute attr_data;
> > + struct firmware *fw;
> > + s32 loading:2;
> > + u32 abort:1;
>
> Why s32 and u32? Why not just ints for both of them?

 Since they are bit fields, I wanted to have more control over them and a
 single bit bit-field should be unsigned, but I guess that David is
 right, it is not worth it. Both are full int's now.
 
> > +struct class firmware_class = {
> > + .name = "firmware",
> > + .hotplug = firmware_class_hotplug,
> > +};
>
> Oops, forgot tabs there...
>
> > + switch(fw_priv->loading){
>
> Please add a space before the '{'.
>
> > + case 0:
> > + if(prev_loading==1)
>
> And a space after the if. You do this in lots of places.

 Fixed, and just in case, I put it through Lindent which BTW is a little
 evil :-) so I hand removed the evilness I could not take.

> Other than those very minor things, this looks quite good.

 Great.

 Patches:
        firmware-class.diff:
                The code itself against bk-cvs.

        class-casts.diff:
                to_class_dev/to_class_dev_attr changes against bk-cvs.

        sysfs-bin-header.diff
        sysfs-bin-lost-dget.diff
        sysfs-bin-flexible-size.diff:
                Just for completeness, since the above will not work
                without them, but I already send them to Pat Mochel in a
                separate mail.

         incremental.diff:
                Incremental patch for easier reading, although there are
                lots of formating changes.

 Thanks

         Manuel

 PS: Sorry, I forgot the patches last time :(
 PS2: Now that I really include the patches I realized their size, and
 compressed some.

-- 
--- Manuel Estrada Sainz <ranty@debian.org>
                         <ranty@bigfoot.com>
			 <ranty@users.sourceforge.net>
------------------------ <manuel.estrada@hispalinux.es> -------------------
Let us have the serenity to accept the things we cannot change, courage to
change the things we can, and wisdom to know the difference.

diff -u linux-2.5.mine/drivers/base/Makefile linux-2.5.mine/drivers/base/Makefile --- linux-2.5.mine/drivers/base/Makefile 2003-05-17 23:17:21.000000000 +0200 +++ linux-2.5.mine/drivers/base/Makefile 2003-05-21 16:25:44.000000000 +0200 @@ -5,4 +5,10 @@ cpu.o firmware.o init.o -obj-m := firmware_class.o firmware_sample_driver.o \ - firmware_sample_firmware_class.o +obj-$(CONFIG_FW_LOADER) += firmware_class.o + +#The next three lines are just to make testing easier and should not get into +#the kernel +obj-$(CONFIG_FW_LOADER_SAMPLE) += firmware_class.o +obj-$(CONFIG_FW_LOADER_SAMPLE) += firmware_sample_driver.o \ + firmware_sample_firmware_class.o + obj-$(CONFIG_NUMA) += node.o memblk.o reverted: --- include/linux/sysfs.h 21 May 2003 13:49:29 -0000 +++ include/linux/sysfs.h 15 May 2003 23:50:23 -0000 1.9 @@ -23,9 +23,6 @@ ssize_t (*write)(struct kobject *, char *, loff_t, size_t); }; -int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); -int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); - struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); only in patch2: unchanged: --- linux-2.5.orig/drivers/base/base.h 2003-05-21 17:38:39.000000000 +0200 +++ linux-2.5.mine/drivers/base/base.h 2003-05-21 10:25:09.000000000 +0200 @@ -4,3 +4,12 @@ extern int bus_add_driver(struct device_driver *); extern void bus_remove_driver(struct device_driver *); +static inline struct class_device *to_class_dev(struct kobject *obj) +{ + return container_of(obj,struct class_device,kobj); +} +static inline +struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) +{ + return container_of(_attr,struct class_device_attribute,attr); +} only in patch2: unchanged: --- linux-2.5.orig/drivers/base/class.c 2003-05-21 17:38:39.000000000 +0200 +++ linux-2.5.mine/drivers/base/class.c 2003-05-21 10:19:41.000000000 +0200 @@ -148,9 +148,6 @@ } -#define to_class_dev(obj) container_of(obj,struct class_device,kobj) -#define to_class_dev_attr(_attr) container_of(_attr,struct class_device_attribute,attr) - static ssize_t class_device_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) only in patch2: unchanged: --- linux-2.5.orig/drivers/base/Kconfig.lib 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.5.mine/drivers/base/Kconfig.lib 2003-05-21 16:24:14.000000000 +0200 @@ -0,0 +1,17 @@ +# +# To be sourced from lib/Kconfig +# + +config FW_LOADER + tristate "Hotplug firmware loading support" + ---help--- + This option is provided for the case where no in-kernel-tree modules + require hotplug firmware loading support, but a module built outside + the kernel tree does. + +config FW_LOADER_SAMPLE + tristate "Hotplug firmware loading samples" + ---help--- + This should not get in the kernel, it is just here to make playing + with firmware loading easier. + only in patch2: unchanged: --- linux-2.5.orig/lib/Kconfig 2003-05-21 17:38:39.000000000 +0200 +++ linux-2.5.mine/lib/Kconfig 2003-05-21 16:12:41.000000000 +0200 @@ -26,5 +26,6 @@ (PPP_DEFLATE=m || JFFS2_FS=m || CRYPTO_DEFLATE=m) default y if PPP_DEFLATE=y || JFFS2_FS=y || CRYPTO_DEFLATE=y -endmenu +source "drivers/base/Kconfig.lib" +endmenu only in patch2: unchanged: --- linux-2.5.orig/include/linux/sysfs.h 2003-05-21 17:38:39.000000000 +0200 +++ linux-2.5.mine/include/linux/sysfs.h 2003-05-21 10:22:08.000000000 +0200 @@ -23,6 +23,9 @@ ssize_t (*write)(struct kobject *, char *, loff_t, size_t); }; +int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); +int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); + struct sysfs_ops { ssize_t (*show)(struct kobject *, struct attribute *,char *); ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t); diff -u linux-2.5.mine/drivers/base/firmware_class.c linux-2.5.mine/drivers/base/firmware_class.c --- linux-2.5.mine/drivers/base/firmware_class.c 2003-05-17 22:44:27.000000000 +0200 +++ linux-2.5.mine/drivers/base/firmware_class.c 2003-05-21 16:38:06.000000000 +0200 @@ -11,88 +11,82 @@ #include <linux/timer.h> #include <asm/hardirq.h> -#include "linux/firmware.h" +#include <linux/firmware.h> +#include "base.h" MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>"); MODULE_DESCRIPTION("Multi purpose firmware loading support"); MODULE_LICENSE("GPL"); -static int loading_timeout = 10; /* In seconds */ - -static inline struct class_device *to_class_dev(struct kobject *obj) -{ - return container_of(obj,struct class_device,kobj); -} -static inline -struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) -{ - return container_of(_attr,struct class_device_attribute,attr); -} - -int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); -int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); +static int loading_timeout = 10; /* In seconds */ struct firmware_priv { char fw_id[FIRMWARE_NAME_MAX]; struct completion completion; struct bin_attribute attr_data; struct firmware *fw; - s32 loading:2; - u32 abort:1; + int loading; + int abort; int alloc_size; struct timer_list timeout; }; -static ssize_t firmware_timeout_show(struct class *class, char *buf) +static ssize_t +firmware_timeout_show(struct class *class, char *buf) { return sprintf(buf, "%d\n", loading_timeout); } -static ssize_t firmware_timeout_store(struct class *class, - const char *buf, size_t count) +static ssize_t +firmware_timeout_store(struct class *class, const char *buf, size_t count) { loading_timeout = simple_strtol(buf, NULL, 10); return count; } + CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); int firmware_class_hotplug(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size); struct class firmware_class = { - .name = "firmware", - .hotplug = firmware_class_hotplug, + .name = "firmware", + .hotplug = firmware_class_hotplug, }; - -int firmware_class_hotplug(struct class_device *class_dev, char **envp, - int num_envp, char *buffer, int buffer_size) +int +firmware_class_hotplug(struct class_device *class_dev, char **envp, + int num_envp, char *buffer, int buffer_size) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); - int i=0; - char *scratch=buffer; + int i = 0; + char *scratch = buffer; - if (buffer_size < (FIRMWARE_NAME_MAX+10)) + if (buffer_size < (FIRMWARE_NAME_MAX + 10)) + return -ENOMEM; + if (num_envp < 1) return -ENOMEM; - envp [i++] = scratch; + envp[i++] = scratch; scratch += sprintf(scratch, "FIRMWARE=%s", fw_priv->fw_id) + 1; return 0; } -static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf) +static ssize_t +firmware_loading_show(struct class_device *class_dev, char *buf) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); return sprintf(buf, "%d\n", fw_priv->loading); } -static ssize_t firmware_loading_store(struct class_device *class_dev, - const char *buf, size_t count) +static ssize_t +firmware_loading_store(struct class_device *class_dev, + const char *buf, size_t count) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); int prev_loading = fw_priv->loading; fw_priv->loading = simple_strtol(buf, NULL, 10); - - switch(fw_priv->loading){ + + switch (fw_priv->loading) { case -1: fw_priv->abort = 1; wmb(); @@ -100,23 +94,25 @@ break; case 1: kfree(fw_priv->fw->data); - fw_priv->fw->data=NULL; - fw_priv->fw->size=0; - fw_priv->alloc_size=0; + fw_priv->fw->data = NULL; + fw_priv->fw->size = 0; + fw_priv->alloc_size = 0; break; case 0: - if(prev_loading==1) + if (prev_loading == 1) complete(&fw_priv->completion); break; } return count; } + CLASS_DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); -static ssize_t firmware_data_read(struct kobject *kobj, - char *buffer, loff_t offset, size_t count) +static ssize_t +firmware_data_read(struct kobject *kobj, + 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); @@ -132,32 +128,33 @@ memcpy(buffer, fw->data, fw->size); return count; } -static int fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) +static int +fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size) { u8 *new_data; if (min_size <= fw_priv->alloc_size) return 0; - new_data = kmalloc(fw_priv->alloc_size+PAGE_SIZE, GFP_KERNEL); - if(!new_data){ - printk(KERN_ERR "%s: unable to alloc buffer\n", - __FUNCTION__); + new_data = kmalloc(fw_priv->alloc_size + PAGE_SIZE, GFP_KERNEL); + if (!new_data) { + printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__); /* Make sure that we don't keep incomplete data */ fw_priv->abort = 1; return -ENOMEM; } fw_priv->alloc_size += PAGE_SIZE; - if(fw_priv->fw->data){ + if (fw_priv->fw->data) { memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size); kfree(fw_priv->fw->data); } - fw_priv->fw->data=new_data; + fw_priv->fw->data = new_data; BUG_ON(min_size > fw_priv->alloc_size); return 0; } -static ssize_t firmware_data_write(struct kobject *kobj, - char *buffer, loff_t offset, size_t count) +static ssize_t +firmware_data_write(struct kobject *kobj, + 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); @@ -165,16 +162,15 @@ int retval; printk("%s: count:%d offset:%lld\n", __FUNCTION__, count, offset); - retval = fw_realloc_buffer(fw_priv, offset+count); - if(retval){ + retval = fw_realloc_buffer(fw_priv, offset + count); + if (retval) { printk("%s: retval:%d\n", __FUNCTION__, retval); return retval; } - printk("%s: retval:%d\n", __FUNCTION__, retval); - memcpy(fw->data+offset, buffer, count); + memcpy(fw->data + offset, buffer, count); - fw->size = max_t(size_t, offset+count, fw->size); + fw->size = max_t(size_t, offset + count, fw->size); return count; } @@ -184,41 +180,42 @@ .read = firmware_data_read, .write = firmware_data_write, }; -static void firmware_class_timeout(u_long data) +static void +firmware_class_timeout(u_long data) { struct firmware_priv *fw_priv = (struct firmware_priv *)data; - fw_priv->abort=1; + fw_priv->abort = 1; wmb(); - complete(&fw_priv->completion); + complete(&fw_priv->completion); } -static inline void fw_setup_class_device_id(struct class_device *class_dev, - struct device *dev) +static inline void +fw_setup_class_device_id(struct class_device *class_dev, struct device *dev) { #warning we should watch out for name collisions strncpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE); - class_dev->class_id[BUS_ID_SIZE-1] = '\0'; + class_dev->class_id[BUS_ID_SIZE - 1] = '\0'; } -static int fw_setup_class_device(struct class_device *class_dev, - const char *fw_name, - struct device *device) +static int +fw_setup_class_device(struct class_device *class_dev, + const char *fw_name, struct device *device) { int retval = 0; - struct firmware_priv *fw_priv = kmalloc(sizeof(struct firmware_priv), + struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv), GFP_KERNEL); - if(!fw_priv){ + if (!fw_priv) { retval = -ENOMEM; goto out; } - memset(fw_priv, 0, sizeof(*fw_priv)); - memset(class_dev, 0, sizeof(*class_dev)); + memset(fw_priv, 0, sizeof (*fw_priv)); + memset(class_dev, 0, sizeof (*class_dev)); init_completion(&fw_priv->completion); memcpy(&fw_priv->attr_data, &firmware_attr_data_tmpl, - sizeof(firmware_attr_data_tmpl)); + sizeof (firmware_attr_data_tmpl)); strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); - fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0'; + fw_priv->fw_id[FIRMWARE_NAME_MAX - 1] = '\0'; fw_setup_class_device_id(class_dev, device); class_dev->dev = device; @@ -227,18 +224,17 @@ fw_priv->timeout.data = (u_long)fw_priv; init_timer(&fw_priv->timeout); - class_dev->class = &firmware_class, + class_dev->class = &firmware_class; class_set_devdata(class_dev, fw_priv); retval = class_device_register(class_dev); - if (retval){ + if (retval) { printk(KERN_ERR "%s: class_device_register failed\n", __FUNCTION__); goto error_free_fw_priv; } - retval = sysfs_create_bin_file(&class_dev->kobj, - &fw_priv->attr_data); - if (retval){ + retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data); + if (retval) { printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", __FUNCTION__); goto error_unreg_class_dev; @@ -246,23 +242,23 @@ retval = class_device_create_file(class_dev, &class_device_attr_loading); - if (retval){ + if (retval) { printk(KERN_ERR "%s: class_device_create_file failed\n", __FUNCTION__); goto error_remove_data; } - fw_priv->fw=kmalloc(sizeof(struct firmware), GFP_KERNEL); - if(!fw_priv->fw){ + fw_priv->fw = kmalloc(sizeof (struct firmware), GFP_KERNEL); + if (!fw_priv->fw) { printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", __FUNCTION__); retval = -ENOMEM; goto error_remove_loading; } - memset(fw_priv->fw, 0, sizeof(*fw_priv->fw)); + memset(fw_priv->fw, 0, sizeof (*fw_priv->fw)); goto out; - + error_remove_loading: class_device_remove_file(class_dev, &class_device_attr_loading); error_remove_data: @@ -274,7 +270,8 @@ out: return retval; } -static void fw_remove_class_device(struct class_device *class_dev) +static void +fw_remove_class_device(struct class_device *class_dev) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); @@ -283,38 +280,41 @@ class_device_unregister(class_dev); } -int request_firmware (const struct firmware **firmware, const char *name, - struct device *device) +int +request_firmware(const struct firmware **firmware, const char *name, + struct device *device) { - struct class_device *class_dev = kmalloc(sizeof(struct class_device), + struct class_device *class_dev = kmalloc(sizeof (struct class_device), GFP_KERNEL); struct firmware_priv *fw_priv; int retval; - if(!class_dev) + if (!class_dev) return -ENOMEM; - if(!firmware){ + if (!firmware) { retval = -EINVAL; goto out; } - *firmware=NULL; + *firmware = NULL; retval = fw_setup_class_device(class_dev, name, device); - if(retval) + if (retval) goto out; fw_priv = class_get_devdata(class_dev); - fw_priv->timeout.expires = jiffies + loading_timeout*HZ; - add_timer(&fw_priv->timeout); + if (loading_timeout) { + fw_priv->timeout.expires = jiffies + loading_timeout * HZ; + add_timer(&fw_priv->timeout); + } wait_for_completion(&fw_priv->completion); del_timer(&fw_priv->timeout); fw_remove_class_device(class_dev); - if(fw_priv->fw->size && !fw_priv->abort){ + if (fw_priv->fw->size && !fw_priv->abort) { *firmware = fw_priv->fw; } else { retval = -ENOENT; @@ -326,15 +326,18 @@ kfree(class_dev); return retval; } -void release_firmware (const struct firmware *fw) + +void +release_firmware(const struct firmware *fw) { - if(fw){ + if (fw) { kfree(fw->data); kfree(fw); } } -void register_firmware (const char *name, const u8 *data, size_t size) +void +register_firmware(const char *name, const u8 *data, size_t size) { /* This is meaningless without firmware caching, so until we * decide if firmware caching is reasonable just leave it as a @@ -351,11 +354,12 @@ void (*cont)(const struct firmware *fw, void *context); }; -static void request_firmware_work_func(void *arg) +static void +request_firmware_work_func(void *arg) { struct firmware_work *fw_work = arg; const struct firmware *fw; - if(!arg) + if (!arg) return; request_firmware(&fw, fw_work->name, fw_work->device); fw_work->cont(fw, fw_work->context); @@ -364,21 +368,22 @@ kfree(fw_work); } -int request_firmware_nowait ( +int +request_firmware_nowait( struct module *module, const char *name, struct device *device, void *context, void (*cont)(const struct firmware *fw, void *context)) { - struct firmware_work *fw_work = kmalloc(sizeof(struct firmware_work), + struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work), GFP_ATOMIC); - if(!fw_work) + if (!fw_work) return -ENOMEM; - if(!try_module_get(module)){ + if (!try_module_get(module)) { kfree(fw_work); return -EFAULT; } - *fw_work = (struct firmware_work){ + *fw_work = (struct firmware_work) { .module = module, .name = name, .device = device, @@ -391,30 +396,30 @@ return 0; } - - -static int __init firmware_class_init(void) +static int __init +firmware_class_init(void) { int error; - error = class_register(&firmware_class); - if (error) { - printk(KERN_ERR "%s: class_register failed\n", - __FUNCTION__); + error = class_register(&firmware_class); + if (error) { + printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__); } error = class_create_file(&firmware_class, &class_attr_timeout); - if (error){ + if (error) { printk(KERN_ERR "%s: class_create_file failed\n", __FUNCTION__); class_unregister(&firmware_class); } - return error; + return error; } -static void __exit firmware_class_exit(void) +static void __exit +firmware_class_exit(void) { class_remove_file(&firmware_class, &class_attr_timeout); class_unregister(&firmware_class); } + module_init(firmware_class_init); module_exit(firmware_class_exit); diff -u linux-2.5.mine/drivers/base/firmware_sample_firmware_class.c linux-2.5.mine/drivers/base/firmware_sample_firmware_class.c --- linux-2.5.mine/drivers/base/firmware_sample_firmware_class.c 2003-05-17 23:19:44.000000000 +0200 +++ linux-2.5.mine/drivers/base/firmware_sample_firmware_class.c 2003-05-21 15:58:34.000000000 +0200 @@ -32,8 +32,8 @@ struct firmware_priv { char fw_id[FIRMWARE_NAME_MAX]; - s32 loading:2; - u32 abort:1; + int loading; + int abort; }; extern struct class firmware_class; @@ -68,8 +68,8 @@ return count; } -CLASS_DEVICE_ATTR(loading, 0644, - firmware_loading_show, firmware_loading_store); +static CLASS_DEVICE_ATTR(loading, 0644, + firmware_loading_show, firmware_loading_store); static ssize_t firmware_data_read(struct kobject *kobj, char *buffer, loff_t offset, size_t count)






- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri May 23 2003 - 22:00:45 EST