]> git.pld-linux.org Git - packages/kernel.git/blame - 2.6.1-rc2-request_firmware-lkml.patch
- moving config-* fixed.
[packages/kernel.git] / 2.6.1-rc2-request_firmware-lkml.patch
CommitLineData
9e5a6bf4 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
3@@ -119,7 +119,7 @@
4 complete(&fw_priv->completion);
5 break;
6 case 1:
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;
12@@ -297,6 +297,7 @@
13 }
14 memset(fw_priv->fw, 0, sizeof (*fw_priv->fw));
15
16+ *class_dev_p = class_dev;
17 goto out;
18
19 error_remove_loading:
20@@ -310,7 +311,6 @@
21 kfree(class_dev);
22 *class_dev_p = NULL;
23 out:
24- *class_dev_p = class_dev;
25 return retval;
26 }
27 static void
28@@ -489,6 +489,7 @@
29 error = class_register(&firmware_class);
30 if (error) {
31 printk(KERN_ERR "%s: class_register failed\n", __FUNCTION__);
32+ return error;
33 }
34 error = class_create_file(&firmware_class, &class_attr_timeout);
35 if (error) {
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
38@@ -34,6 +34,14 @@
39 struct timer_list timeout;
40 };
41
42+static inline void
43+fw_load_abort(struct firmware_priv *fw_priv)
44+{
45+ fw_priv->abort = 1;
46+ wmb();
47+ complete(&fw_priv->completion);
48+}
49+
50 static ssize_t
51 firmware_timeout_show(struct class *class, char *buf)
52 {
53@@ -113,11 +121,6 @@
54 fw_priv->loading = simple_strtol(buf, NULL, 10);
55
56 switch (fw_priv->loading) {
57- case -1:
58- fw_priv->abort = 1;
59- wmb();
60- complete(&fw_priv->completion);
61- break;
62 case 1:
63 vfree(fw_priv->fw->data);
64 fw_priv->fw->data = NULL;
65@@ -125,8 +128,17 @@
66 fw_priv->alloc_size = 0;
67 break;
68 case 0:
69- if (prev_loading == 1)
70+ if (prev_loading == 1) {
71 complete(&fw_priv->completion);
72+ break;
73+ }
74+ /* fallthrough */
75+ default:
76+ printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
77+ fw_priv->loading);
78+ /* fallthrough */
79+ case -1:
80+ fw_load_abort(fw_priv);
81 break;
82 }
83
84@@ -164,7 +176,7 @@
85 if (!new_data) {
86 printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
87 /* Make sure that we don't keep incomplete data */
88- fw_priv->abort = 1;
89+ fw_load_abort(fw_priv);
90 return -ENOMEM;
91 }
92 fw_priv->alloc_size += PAGE_SIZE;
93@@ -221,17 +233,14 @@
94 firmware_class_timeout(u_long data)
95 {
96 struct firmware_priv *fw_priv = (struct firmware_priv *) data;
97- fw_priv->abort = 1;
98- wmb();
99- complete(&fw_priv->completion);
100+ fw_load_abort(fw_priv);
101 }
102
103 static inline void
104 fw_setup_class_device_id(struct class_device *class_dev, struct device *dev)
105 {
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);
110 }
111 static int
112 fw_setup_class_device(struct class_device **class_dev_p,
113@@ -244,6 +253,7 @@
114 GFP_KERNEL);
115
116 if (!fw_priv || !class_dev) {
117+ printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
118 retval = -ENOMEM;
119 goto error_kfree;
120 }
121@@ -251,12 +261,8 @@
122 memset(class_dev, 0, sizeof (*class_dev));
123
124 init_completion(&fw_priv->completion);
125- memcpy(&fw_priv->attr_data, &firmware_attr_data_tmpl,
126- sizeof (firmware_attr_data_tmpl));
127-
128- strncpy(&fw_priv->fw_id[0], fw_name, FIRMWARE_NAME_MAX);
129- fw_priv->fw_id[FIRMWARE_NAME_MAX - 1] = '\0';
130-
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;
135
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
138@@ -13,6 +13,7 @@
139 #include <linux/timer.h>
140 #include <linux/vmalloc.h>
141 #include <asm/hardirq.h>
142+#include <linux/bitops.h>
143
144 #include <linux/firmware.h>
145 #include "base.h"
146@@ -21,6 +22,11 @@
147 MODULE_DESCRIPTION("Multi purpose firmware loading support");
148 MODULE_LICENSE("GPL");
149
150+enum {
151+ FW_STATUS_LOADING,
152+ FW_STATUS_ABORT,
153+};
154+
155 static int loading_timeout = 10; /* In seconds */
156
157 struct firmware_priv {
158@@ -28,8 +34,7 @@
159 struct completion completion;
160 struct bin_attribute attr_data;
161 struct firmware *fw;
162- int loading;
163- int abort;
164+ unsigned long status;
165 int alloc_size;
166 struct timer_list timeout;
167 };
168@@ -37,7 +42,7 @@
169 static inline void
170 fw_load_abort(struct firmware_priv *fw_priv)
171 {
172- fw_priv->abort = 1;
173+ set_bit(FW_STATUS_ABORT, &fw_priv->status);
174 wmb();
175 complete(&fw_priv->completion);
176 }
177@@ -99,7 +104,8 @@
178 firmware_loading_show(struct class_device *class_dev, char *buf)
179 {
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);
184 }
185
186 /**
187@@ -116,26 +122,26 @@
188 const char *buf, size_t count)
189 {
190 struct firmware_priv *fw_priv = class_get_devdata(class_dev);
191- int prev_loading = fw_priv->loading;
192-
193- fw_priv->loading = simple_strtol(buf, NULL, 10);
194+ int loading = simple_strtol(buf, NULL, 10);
195
196- switch (fw_priv->loading) {
197+ switch (loading) {
198 case 1:
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);
204 break;
205 case 0:
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);
210 break;
211 }
212 /* fallthrough */
213 default:
214 printk(KERN_ERR "%s: unexpected value (%d)\n", __FUNCTION__,
215- fw_priv->loading);
216+ loading);
217 /* fallthrough */
218 case -1:
219 fw_load_abort(fw_priv);
220@@ -370,7 +376,7 @@
221 del_timer(&fw_priv->timeout);
222 fw_remove_class_device(class_dev);
223
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;
227 } else {
228 retval = -ENOENT;
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
231@@ -232,6 +232,9 @@
232 static void
233 fw_class_dev_release(struct class_device *class_dev)
234 {
235+ struct firmware_priv *fw_priv = class_get_devdata(class_dev);
236+
237+ kfree(fw_priv);
238 kfree(class_dev);
239 }
240
241@@ -258,6 +261,8 @@
242 struct class_device *class_dev = kmalloc(sizeof (struct class_device),
243 GFP_KERNEL);
244
245+ *class_dev_p = NULL;
246+
247 if (!fw_priv || !class_dev) {
248 printk(KERN_ERR "%s: kmalloc failed\n", __FUNCTION__);
249 retval = -ENOMEM;
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);
254+ goto out;
255+
256 error_kfree:
257 kfree(fw_priv);
258 kfree(class_dev);
259- *class_dev_p = NULL;
260 out:
261 return retval;
262 }
263@@ -374,7 +380,6 @@
264 wait_for_completion(&fw_priv->completion);
265
266 del_timer(&fw_priv->timeout);
267- fw_remove_class_device(class_dev);
268
269 if (fw_priv->fw->size && !test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
270 *firmware = fw_priv->fw;
271@@ -383,7 +388,7 @@
272 vfree(fw_priv->fw->data);
273 kfree(fw_priv->fw);
274 }
275- kfree(fw_priv);
276+ fw_remove_class_device(class_dev);
277 out:
278 return retval;
279 }
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
282@@ -14,6 +14,7 @@
283 #include <linux/vmalloc.h>
284 #include <asm/hardirq.h>
285 #include <linux/bitops.h>
286+#include <asm/semaphore.h>
287
288 #include <linux/firmware.h>
289 #include "base.h"
290@@ -24,11 +25,16 @@
291
292 enum {
293 FW_STATUS_LOADING,
294+ FW_STATUS_DONE,
295 FW_STATUS_ABORT,
296 };
297
298 static int loading_timeout = 10; /* In seconds */
299
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);
303+
304 struct firmware_priv {
305 char fw_id[FIRMWARE_NAME_MAX];
306 struct completion completion;
307@@ -126,11 +132,13 @@
308
309 switch (loading) {
310 case 1:
311+ down(&fw_lock);
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);
317+ up(&fw_lock);
318 break;
319 case 0:
320 if (test_bit(FW_STATUS_LOADING, &fw_priv->status)) {
321@@ -160,15 +168,26 @@
322 {
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;
328
329- if (offset > fw->size)
330- return 0;
331- if (offset + count > fw->size)
332- count = fw->size - offset;
333+ down(&fw_lock);
334+ fw = fw_priv->fw;
335+ if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
336+ ret_count = -ENODEV;
337+ goto out;
338+ }
339+ if (offset > fw->size) {
340+ ret_count = 0;
341+ goto out;
342+ }
343+ if (offset + ret_count > fw->size)
344+ ret_count = fw->size - offset;
345
346- memcpy(buffer, fw->data + offset, count);
347- return count;
348+ memcpy(buffer, fw->data + offset, ret_count);
349+out:
350+ up(&fw_lock);
351+ return ret_count;
352 }
353 static int
354 fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
355@@ -209,18 +228,26 @@
356 {
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;
360- int retval;
361+ struct firmware *fw;
362+ ssize_t retval;
363
364+ down(&fw_lock);
365+ fw = fw_priv->fw;
366+ if (test_bit(FW_STATUS_DONE, &fw_priv->status)) {
367+ retval = -ENODEV;
368+ goto out;
369+ }
370 retval = fw_realloc_buffer(fw_priv, offset + count);
371 if (retval)
372- return retval;
373+ goto out;
374
375 memcpy(fw->data + offset, buffer, count);
376
377 fw->size = max_t(size_t, offset + count, fw->size);
378-
379- return count;
380+ retval = count;
381+out:
382+ up(&fw_lock);
383+ return retval;
384 }
385 static struct bin_attribute firmware_attr_data_tmpl = {
386 .attr = {.name = "data", .mode = 0644},
387@@ -252,7 +279,7 @@
388 strlcpy(class_dev->class_id, dev->bus_id, BUS_ID_SIZE);
389 }
390 static int
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)
394 {
395 int retval = 0;
396@@ -290,6 +317,8 @@
397 goto error_kfree;
398 }
399
400+ fw_priv->fw = fw;
401+
402 retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
403 if (retval) {
404 printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
405@@ -305,20 +334,9 @@
406 goto error_remove_data;
407 }
408
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",
412- __FUNCTION__);
413- retval = -ENOMEM;
414- goto error_remove_loading;
415- }
416- memset(fw_priv->fw, 0, sizeof (*fw_priv->fw));
417-
418 *class_dev_p = class_dev;
419 goto out;
420
421-error_remove_loading:
422- class_device_remove_file(class_dev, &class_device_attr_loading);
423 error_remove_data:
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.
428 **/
429 int
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)
433 {
434 struct class_device *class_dev;
435 struct firmware_priv *fw_priv;
436+ struct firmware *firmware;
437 int retval;
438
439- if (!firmware)
440+ if (!firmware_p)
441 return -EINVAL;
442
443- *firmware = NULL;
444+ *firmware_p = firmware = kmalloc(sizeof (struct firmware), GFP_KERNEL);
445+ if (!firmware) {
446+ printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
447+ __FUNCTION__);
448+ retval = -ENOMEM;
449+ goto out;
450+ }
451+ memset(firmware, 0, sizeof (*firmware));
452
453- retval = fw_setup_class_device(&class_dev, name, device);
454+ retval = fw_setup_class_device(firmware, &class_dev, name, device);
455 if (retval)
456- goto out;
457+ goto error_kfree_fw;
458
459 fw_priv = class_get_devdata(class_dev);
460
461@@ -378,17 +404,23 @@
462 }
463
464 wait_for_completion(&fw_priv->completion);
465+ set_bit(FW_STATUS_DONE, &fw_priv->status);
466
467 del_timer(&fw_priv->timeout);
468
469- if (fw_priv->fw->size && !test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
470- *firmware = fw_priv->fw;
471- } else {
472+ down(&fw_lock);
473+ if (!fw_priv->fw->size || test_bit(FW_STATUS_ABORT, &fw_priv->status)) {
474 retval = -ENOENT;
475- vfree(fw_priv->fw->data);
476- kfree(fw_priv->fw);
477+ release_firmware(fw_priv->fw);
478+ *firmware_p = NULL;
479 }
480+ fw_priv->fw = NULL;
481+ up(&fw_lock);
482 fw_remove_class_device(class_dev);
483+ goto out;
484+
485+error_kfree_fw:
486+ kfree(firmware);
487 out:
488 return retval;
489 }
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);
495 }
496+
497 static int
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)
502 {
503- int retval = 0;
504+ int retval;
505 struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
506 GFP_KERNEL);
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;
514
515 fw_priv->timeout.function = firmware_class_timeout;
516 fw_priv->timeout.data = (u_long) fw_priv;
517 init_timer(&fw_priv->timeout);
518
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);
524@@ -316,7 +317,28 @@
525 __FUNCTION__);
526 goto error_kfree;
527 }
528+ *class_dev_p = class_dev;
529+ return 0;
530
531+error_kfree:
532+ kfree(fw_priv);
533+ kfree(class_dev);
534+ return retval;
535+}
536+static int
537+fw_setup_class_device(struct firmware *fw, struct class_device **class_dev_p,
538+ const char *fw_name, struct device *device)
539+{
540+ struct class_device *class_dev;
541+ struct firmware_priv *fw_priv;
542+ int retval;
543+
544+ *class_dev_p = NULL;
545+ retval = fw_register_class_device(&class_dev, fw_name, device);
546+ if (retval)
547+ goto out;
548+
549+ fw_priv = class_get_devdata(class_dev);
550 fw_priv->fw = fw;
551
552 retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
553@@ -341,11 +363,6 @@
554 sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
555 error_unreg_class_dev:
556 class_device_unregister(class_dev);
557- goto out;
558-
559-error_kfree:
560- kfree(fw_priv);
561- kfree(class_dev);
562 out:
563 return retval;
564 }
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 @@
568 goto out;
569
570 fw_priv = class_get_devdata(class_dev);
571- fw_priv->fw = fw;
572
573+ fw_priv->fw = fw;
574 retval = sysfs_create_bin_file(&class_dev->kobj, &fw_priv->attr_data);
575 if (retval) {
576 printk(KERN_ERR "%s: sysfs_create_bin_file failed\n",
577 __FUNCTION__);
578- goto error_unreg_class_dev;
579+ goto error_unreg;
580 }
581
582 retval = class_device_create_file(class_dev,
583@@ -353,28 +353,17 @@
584 if (retval) {
585 printk(KERN_ERR "%s: class_device_create_file failed\n",
586 __FUNCTION__);
587- goto error_remove_data;
588+ goto error_unreg;
589 }
590
591 *class_dev_p = class_dev;
592 goto out;
593
594-error_remove_data:
595- sysfs_remove_bin_file(&class_dev->kobj, &fw_priv->attr_data);
596-error_unreg_class_dev:
597+error_unreg:
598 class_device_unregister(class_dev);
599 out:
600 return retval;
601 }
602-static void
603-fw_remove_class_device(struct class_device *class_dev)
604-{
605- struct firmware_priv *fw_priv = class_get_devdata(class_dev);
606-
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);
610-}
611
612 /**
613 * request_firmware: - request firmware to hotplug and wait for it
614@@ -433,7 +422,7 @@
615 }
616 fw_priv->fw = NULL;
617 up(&fw_lock);
618- fw_remove_class_device(class_dev);
619+ class_device_unregister(class_dev);
620 goto out;
621
622 error_kfree_fw:
623@@ -569,7 +558,6 @@
624 static void __exit
625 firmware_class_exit(void)
626 {
627- class_remove_file(&firmware_class, &class_attr_timeout);
628 class_unregister(&firmware_class);
629 }
630
This page took 0.118294 seconds and 4 git commands to generate.