]> git.pld-linux.org Git - packages/kernel.git/blob - 2.6.1-rc2-request_firmware-lkml.patch
- obsolete
[packages/kernel.git] / 2.6.1-rc2-request_firmware-lkml.patch
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.07612 seconds and 3 git commands to generate.