1 --- linux-2.5.orig/drivers/base/firmware_class.c 2004-01-02 20:42:03.000000000 +0100
2 +++ linux-2.5/drivers/base/firmware_class.c 2004-01-02 21:43:17.000000000 +0100
4 complete(&fw_priv->completion);
7 - kfree(fw_priv->fw->data);
8 + vfree(fw_priv->fw->data);
9 fw_priv->fw->data = NULL;
10 fw_priv->fw->size = 0;
11 fw_priv->alloc_size = 0;
14 memset(fw_priv->fw, 0, sizeof (*fw_priv->fw));
16 + *class_dev_p = class_dev;
24 - *class_dev_p = class_dev;
29 error = class_register(&firmware_class);
31 printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__);
34 error = class_create_file(&firmware_class, &class_attr_timeout);
36 --- linux-2.5.orig/drivers/base/firmware_class.c 2004-01-06 03:23:14.000000000 +0100
37 +++ linux-2.5/drivers/base/firmware_class.c 2004-01-06 03:53:30.000000000 +0100
39 struct timer_list timeout;
43 +fw_load_abort(struct firmware_priv *fw_priv)
47 + complete(&fw_priv->completion);
51 firmware_timeout_show(struct class *class, char *buf)
54 fw_priv->loading = simple_strtol(buf, NULL, 10);
56 switch (fw_priv->loading) {
60 - complete(&fw_priv->completion);
63 vfree(fw_priv->fw->data);
64 fw_priv->fw->data = NULL;
66 fw_priv->alloc_size = 0;
69 - if (prev_loading == 1)
70 + if (prev_loading == 1) {
71 complete(&fw_priv->completion);
76 + printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
80 + fw_load_abort(fw_priv);
86 printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
87 /* Make sure that we don't keep incomplete data */
89 + fw_load_abort(fw_priv);
92 fw_priv->alloc_size += PAGE_SIZE;
94 firmware_class_timeout(u_long data)
96 struct firmware_priv *fw_priv = (struct firmware_priv *) data;
99 - complete(&fw_priv->completion);
100 + fw_load_abort(fw_priv);
104 fw_setup_class_device_id(struct class_device *class_dev, struct device *dev)
106 /* XXX warning we should watch out for name collisions */
107 - strncpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
108 - class_dev->class_id[BUS_ID_SIZE - 1] = '\0';
109 + strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
112 fw_setup_class_device(struct class_device **class_dev_p,
116 if (!fw_priv || !class_dev) {
117 + printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
122 memset(class_dev, 0, sizeof (*class_dev));
124 init_completion(&fw_priv->completion);
125 - memcpy(&fw_priv->attr_data, &firmware_attr_data_tmpl,
126 - sizeof (firmware_attr_data_tmpl));
128 - strncpy(&fw_priv->fw_id[0], fw_name, FIRMWARE_NAME_MAX);
129 - fw_priv->fw_id[FIRMWARE_NAME_MAX - 1] = '\0';
131 + fw_priv->attr_data = firmware_attr_data_tmpl;
132 + strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
133 fw_setup_class_device_id(class_dev, device);
134 class_dev->dev = device;
136 --- linux-2.5.orig/drivers/base/firmware_class.c 2004-01-06 14:29:01.000000000 +0100
137 +++ linux-2.5/drivers/base/firmware_class.c 2004-01-06 21:29:09.000000000 +0100
139 #include <linux/timer.h>
140 #include <linux/vmalloc.h>
141 #include <asm/hardirq.h>
142 +#include <linux/bitops.h>
144 #include <linux/firmware.h>
147 MODULE_DESCRIPTION("Multi purpose firmware loading support");
148 MODULE_LICENSE("GPL");
155 static int loading_timeout = 10; /* In seconds */
157 struct firmware_priv {
159 struct completion completion;
160 struct bin_attribute attr_data;
164 + unsigned long status;
166 struct timer_list timeout;
170 fw_load_abort(struct firmware_priv *fw_priv)
172 - fw_priv->abort = 1;
173 + set_bit(FW_STATUS_ABORT, &fw_priv->status);
175 complete(&fw_priv->completion);
178 firmware_loading_show(struct class_device *class_dev, char *buf)
180 struct firmware_priv *fw_priv = class_get_devdata(class_dev);
181 - return sprintf(buf, "%d\n", fw_priv->loading);
182 + int loading = test_bit(FW_STATUS_LOADING, &fw_priv->status);
183 + return sprintf(buf, "%d\n", loading);
187 @@ -116,26 +122,26 @@
188 const char *buf, size_t count)
190 struct firmware_priv *fw_priv = class_get_devdata(class_dev);
191 - int prev_loading = fw_priv->loading;
193 - fw_priv->loading = simple_strtol(buf, NULL, 10);
194 + int loading = simple_strtol(buf, NULL, 10);
196 - switch (fw_priv->loading) {
199 vfree(fw_priv->fw->data);
200 fw_priv->fw->data = NULL;
201 fw_priv->fw->size = 0;
202 fw_priv->alloc_size = 0;
203 + set_bit(FW_STATUS_LOADING, &fw_priv->status);
206 - if (prev_loading == 1) {
207 + if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
208 complete(&fw_priv->completion);
209 + clear_bit(FW_STATUS_LOADING, &fw_priv->status);
214 printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
219 fw_load_abort(fw_priv);
221 del_timer(&fw_priv->timeout);
222 fw_remove_class_device(class_dev);
224 - if (fw_priv->fw->size && !fw_priv->abort) {
225 + if (fw_priv->fw->size && !test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
226 *firmware = fw_priv->fw;
229 --- linux-2.5.orig/drivers/base/firmware_class.c 2004-01-06 13:30:48.000000000 +0100
230 +++ linux-2.5/drivers/base/firmware_class.c 2004-01-06 13:31:38.000000000 +0100
233 fw_class_dev_release(struct class_device *class_dev)
235 + struct firmware_priv *fw_priv = class_get_devdata(class_dev);
242 struct class_device *class_dev = kmalloc(sizeof (struct class_device),
245 + *class_dev_p = NULL;
247 if (!fw_priv || !class_dev) {
248 printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
250 @@ -318,10 +323,11 @@
251 sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
252 error_unreg_class_dev:
253 class_device_unregister(class_dev);
259 - *class_dev_p = NULL;
264 wait_for_completion(&fw_priv->completion);
266 del_timer(&fw_priv->timeout);
267 - fw_remove_class_device(class_dev);
269 if (fw_priv->fw->size && !test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
270 *firmware = fw_priv->fw;
272 vfree(fw_priv->fw->data);
276 + fw_remove_class_device(class_dev);
280 --- linux-2.5.orig/drivers/base/firmware_class.c 2004-01-06 13:41:22.000000000 +0100
281 +++ linux-2.5/drivers/base/firmware_class.c 2004-01-06 13:43:58.000000000 +0100
283 #include <linux/vmalloc.h>
284 #include <asm/hardirq.h>
285 #include <linux/bitops.h>
286 +#include <asm/semaphore.h>
288 #include <linux/firmware.h>
298 static int loading_timeout = 10; /* In seconds */
300 +/* fw_lock could be moved to 'struct firmware_priv' but since it is just
301 + * guarding for corner cases a global lock should be OK */
302 +static DECLARE_MUTEX(fw_lock);
304 struct firmware_priv {
305 char fw_id[FIRMWARE_NAME_MAX];
306 struct completion completion;
307 @@ -126,11 +132,13 @@
312 vfree(fw_priv->fw->data);
313 fw_priv->fw->data = NULL;
314 fw_priv->fw->size = 0;
315 fw_priv->alloc_size = 0;
316 set_bit(FW_STATUS_LOADING, &fw_priv->status);
320 if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
321 @@ -160,15 +168,26 @@
323 struct class_device *class_dev = to_class_dev(kobj);
324 struct firmware_priv *fw_priv = class_get_devdata(class_dev);
325 - struct firmware *fw = fw_priv->fw;
326 + struct firmware *fw;
327 + ssize_t ret_count = count;
329 - if (offset > fw->size)
331 - if (offset + count > fw->size)
332 - count = fw->size - offset;
335 + if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
336 + ret_count = -ENODEV;
339 + if (offset > fw->size) {
343 + if (offset + ret_count > fw->size)
344 + ret_count = fw->size - offset;
346 - memcpy(buffer, fw->data + offset, count);
348 + memcpy(buffer, fw->data + offset, ret_count);
354 fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
355 @@ -209,18 +228,26 @@
357 struct class_device *class_dev = to_class_dev(kobj);
358 struct firmware_priv *fw_priv = class_get_devdata(class_dev);
359 - struct firmware *fw = fw_priv->fw;
361 + struct firmware *fw;
366 + if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
370 retval = fw_realloc_buffer(fw_priv, offset + count);
375 memcpy(fw->data + offset, buffer, count);
377 fw->size = max_t(size_t, offset + count, fw->size);
385 static struct bin_attribute firmware_attr_data_tmpl = {
386 .attr = {.name = "data", .mode = 0644},
388 strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
391 -fw_setup_class_device(struct class_device **class_dev_p,
392 +fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
393 const char *fw_name, struct device *device)
402 retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
404 printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
406 goto error_remove_data;
409 - fw_priv->fw = kmalloc(sizeof (struct firmware), GFP_KERNEL);
410 - if (!fw_priv->fw) {
411 - printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
414 - goto error_remove_loading;
416 - memset(fw_priv->fw, 0, sizeof (*fw_priv->fw));
418 *class_dev_p = class_dev;
421 -error_remove_loading:
422 - class_device_remove_file(class_dev, &class_device_attr_loading);
424 sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
425 error_unreg_class_dev:
426 @@ -354,21 +372,29 @@
427 * firmware image for this or any other device.
430 -request_firmware(const struct firmware **firmware, const char *name,
431 +request_firmware(const struct firmware **firmware_p, const char *name,
432 struct device *device)
434 struct class_device *class_dev;
435 struct firmware_priv *fw_priv;
436 + struct firmware *firmware;
444 + *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
446 + printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
451 + memset(firmware, 0, sizeof (*firmware));
453 - retval = fw_setup_class_device(&class_dev, name, device);
454 + retval = fw_setup_class_device(firmware, &class_dev, name, device);
457 + goto error_kfree_fw;
459 fw_priv = class_get_devdata(class_dev);
461 @@ -378,17 +404,23 @@
464 wait_for_completion(&fw_priv->completion);
465 + set_bit(FW_STATUS_DONE, &fw_priv->status);
467 del_timer(&fw_priv->timeout);
469 - if (fw_priv->fw->size && !test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
470 - *firmware = fw_priv->fw;
473 + if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
475 - vfree(fw_priv->fw->data);
476 - kfree(fw_priv->fw);
477 + release_firmware(fw_priv->fw);
478 + *firmware_p = NULL;
480 + fw_priv->fw = NULL;
482 fw_remove_class_device(class_dev);
490 --- linux-2.5.orig/drivers/base/firmware_class.c 2004-01-06 13:40:49.000000000 +0100
491 +++ linux-2.5/drivers/base/firmware_class.c 2004-01-06 13:40:58.000000000 +0100
492 @@ -278,11 +278,12 @@
493 /* XXX warning we should watch out for name collisions */
494 strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
498 -fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
499 - const char *fw_name, struct device *device)
500 +fw_register_class_device(struct class_device **class_dev_p,
501 + const char *fw_name, struct device *device)
505 struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
507 struct class_device *class_dev = kmalloc(sizeof (struct class_device),
508 @@ -301,13 +302,13 @@
509 init_completion(&fw_priv->completion);
510 fw_priv->attr_data = firmware_attr_data_tmpl;
511 strlcpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX);
512 - fw_setup_class_device_id(class_dev, device);
513 - class_dev->dev = device;
515 fw_priv->timeout.function = firmware_class_timeout;
516 fw_priv->timeout.data = (u_long) fw_priv;
517 init_timer(&fw_priv->timeout);
519 + fw_setup_class_device_id(class_dev, device);
520 + class_dev->dev = device;
521 class_dev->class = &firmware_class;
522 class_set_devdata(class_dev, fw_priv);
523 retval = class_device_register(class_dev);
528 + *class_dev_p = class_dev;
537 +fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
538 + const char *fw_name, struct device *device)
540 + struct class_device *class_dev;
541 + struct firmware_priv *fw_priv;
544 + *class_dev_p = NULL;
545 + retval = fw_register_class_device(&class_dev, fw_name, device);
549 + fw_priv = class_get_devdata(class_dev);
552 retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
554 sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
555 error_unreg_class_dev:
556 class_device_unregister(class_dev);
565 --- linux-2.5.orig/drivers/base/firmware_class.c 2004-01-06 13:40:58.000000000 +0100
566 +++ linux-2.5/drivers/base/firmware_class.c 2004-01-06 13:41:07.000000000 +0100
567 @@ -339,13 +339,13 @@
570 fw_priv = class_get_devdata(class_dev);
574 retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
576 printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
578 - goto error_unreg_class_dev;
582 retval = class_device_create_file(class_dev,
583 @@ -353,28 +353,17 @@
585 printk(KERN_ERR "%s: class_device_create_file failed\n",
587 - goto error_remove_data;
591 *class_dev_p = class_dev;
595 - sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
596 -error_unreg_class_dev:
598 class_device_unregister(class_dev);
603 -fw_remove_class_device(struct class_device *class_dev)
605 - struct firmware_priv *fw_priv = class_get_devdata(class_dev);
607 - class_device_remove_file(class_dev, &class_device_attr_loading);
608 - sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
609 - class_device_unregister(class_dev);
613 * request_firmware: - request firmware to hotplug and wait for it
618 - fw_remove_class_device(class_dev);
619 + class_device_unregister(class_dev);
625 firmware_class_exit(void)
627 - class_remove_file(&firmware_class, &class_attr_timeout);
628 class_unregister(&firmware_class);