OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [LINUX_2_4_26_OR32/] [linux/] [linux-2.4/] [lib/] [firmware_class.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * firmware_class.c - Multi purpose firmware loading support
3
 *
4
 * Copyright (c) 2003 Manuel Estrada Sainz <ranty@debian.org>
5
 *
6
 * Please see Documentation/firmware_class/ for more information.
7
 *
8
 */
9
/*
10
 * Based on kernel/kmod.c and drivers/usb/usb.c
11
 */
12
/*
13
        kernel/kmod.c
14
        Kirk Petersen
15
 
16
        Reorganized not to be a daemon by Adam Richter, with guidance
17
        from Greg Zornetzer.
18
 
19
        Modified to avoid chroot and file sharing problems.
20
        Mikael Pettersson
21
 
22
        Limit the concurrent number of kmod modprobes to catch loops from
23
        "modprobe needs a service that is in a module".
24
        Keith Owens <kaos@ocs.com.au> December 1999
25
 
26
        Unblock all signals when we exec a usermode process.
27
        Shuu Yamaguchi <shuu@wondernetworkresources.com> December 2000
28
*/
29
/*
30
 * drivers/usb/usb.c
31
 *
32
 * (C) Copyright Linus Torvalds 1999
33
 * (C) Copyright Johannes Erdfelt 1999-2001
34
 * (C) Copyright Andreas Gal 1999
35
 * (C) Copyright Gregory P. Smith 1999
36
 * (C) Copyright Deti Fliegl 1999 (new USB architecture)
37
 * (C) Copyright Randy Dunlap 2000
38
 * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
39
 * (C) Copyright Yggdrasil Computing, Inc. 2000
40
 *     (usb_device_id matching changes by Adam J. Richter)
41
 */
42
 
43
#include <linux/config.h>
44
#include <linux/module.h>
45
#include <linux/string.h>
46
#include <linux/types.h>
47
#include <linux/init.h>
48
#include <linux/slab.h>
49
#include <linux/kmod.h>
50
#include <linux/proc_fs.h>
51
#include <linux/vmalloc.h>
52
#include <asm/hardirq.h>
53
 
54
#include "linux/firmware.h"
55
 
56
MODULE_AUTHOR("Manuel Estrada Sainz <ranty@debian.org>");
57
MODULE_DESCRIPTION("Multi purpose firmware loading support");
58
MODULE_LICENSE("GPL");
59
 
60
#define err(format, arg...) \
61
     printk(KERN_ERR  "%s:%s: " format "\n",__FILE__, __FUNCTION__ , ## arg)
62
#define warn(format, arg...) \
63
     printk(KERN_WARNING "%s:%s: " format "\n",__FILE__, __FUNCTION__ , ## arg)
64
#define dbg(format, arg...) \
65
     printk(KERN_DEBUG "%s:%s: " format "\n",__FILE__, __FUNCTION__ , ## arg)
66
 
67
static int loading_timeout = 10;        /* In seconds */
68
static struct proc_dir_entry *proc_dir_timeout;
69
static struct proc_dir_entry *proc_dir;
70
 
71
#ifdef CONFIG_HOTPLUG
72
 
73
static int
74
call_helper(char *verb, const char *name, const char *device)
75
{
76
        char *argv[3], **envp, *buf, *scratch;
77
        int i = 0;
78
 
79
        int retval = 0;
80
 
81
        if (!hotplug_path[0])
82
                return -ENOENT;
83
        if (in_interrupt()) {
84
                err("in_interrupt");
85
                return -EFAULT;
86
        }
87
        if (!current->fs->root) {
88
                warn("call_policy %s -- no FS yet", verb);
89
                return -EPERM;
90
        }
91
 
92
        if (!(envp = (char **) kmalloc(20 * sizeof (char *), GFP_KERNEL))) {
93
                err("unable to allocate envp");
94
                return -ENOMEM;
95
        }
96
        if (!(buf = kmalloc(256, GFP_KERNEL))) {
97
                kfree(envp);
98
                err("unable to allocate buf");
99
                return -ENOMEM;
100
        }
101
 
102
        /* only one standardized param to hotplug command: type */
103
        argv[0] = hotplug_path;
104
        argv[1] = "firmware";
105
        argv[2] = 0;
106
 
107
        /* minimal command environment */
108
        envp[i++] = "HOME=/";
109
        envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
110
 
111
#ifdef  DEBUG
112
        /* hint that policy agent should enter no-stdout debug mode */
113
        envp[i++] = "DEBUG=kernel";
114
#endif
115
        scratch = buf;
116
 
117
        if (device) {
118
                envp[i++] = scratch;
119
                scratch += snprintf(scratch, FIRMWARE_NAME_MAX+25,
120
                                    "DEVPATH=/driver/firmware/%s", device) + 1;
121
        }
122
 
123
        envp[i++] = scratch;
124
        scratch += sprintf(scratch, "ACTION=%s", verb) + 1;
125
 
126
        envp[i++] = scratch;
127
        scratch += snprintf(scratch, FIRMWARE_NAME_MAX,
128
                            "FIRMWARE=%s", name) + 1;
129
 
130
        envp[i++] = 0;
131
 
132
#ifdef  DEBUG
133
        dbg("firmware: %s %s %s", argv[0], argv[1], verb);
134
#endif
135
 
136
        retval = call_usermodehelper(argv[0], argv, envp);
137
        if (retval) {
138
                printk("call_usermodehelper return %d\n", retval);
139
        }
140
 
141
        kfree(buf);
142
        kfree(envp);
143
        return retval;
144
}
145
#else
146
 
147
static inline int
148
call_helper(char *verb, const char *name, const char *device)
149
{
150
        return -ENOENT;
151
}
152
 
153
#endif /* CONFIG_HOTPLUG */
154
 
155
struct firmware_priv {
156
        struct completion completion;
157
        struct proc_dir_entry *proc_dir;
158
        struct proc_dir_entry *attr_data;
159
        struct proc_dir_entry *attr_loading;
160
        struct firmware *fw;
161
        int loading;
162
        int abort;
163
        int alloc_size;
164
        struct timer_list timeout;
165
};
166
 
167
static int
168
firmware_timeout_show(char *buf, char **start, off_t off,
169
                      int count, int *eof, void *data)
170
{
171
        return sprintf(buf, "%d\n", loading_timeout);
172
}
173
 
174
/**
175
 * firmware_timeout_store:
176
 * Description:
177
 *      Sets the number of seconds to wait for the firmware.  Once
178
 *      this expires an error will be return to the driver and no
179
 *      firmware will be provided.
180
 *
181
 *      Note: zero means 'wait for ever'
182
 *
183
 **/
184
static int
185
firmware_timeout_store(struct file *file, const char *buf,
186
                       unsigned long count, void *data)
187
{
188
        loading_timeout = simple_strtol(buf, NULL, 10);
189
        return count;
190
}
191
 
192
static int
193
firmware_loading_show(char *buf, char **start, off_t off,
194
                      int count, int *eof, void *data)
195
{
196
        struct firmware_priv *fw_priv = data;
197
        return sprintf(buf, "%d\n", fw_priv->loading);
198
}
199
 
200
/**
201
 * firmware_loading_store: - loading control file
202
 * Description:
203
 *      The relevant values are:
204
 *
205
 *       1: Start a load, discarding any previous partial load.
206
 *       0: Conclude the load and handle the data to the driver code.
207
 *      -1: Conclude the load with an error and discard any written data.
208
 **/
209
static int
210
firmware_loading_store(struct file *file, const char *buf,
211
                       unsigned long count, void *data)
212
{
213
        struct firmware_priv *fw_priv = data;
214
        int prev_loading = fw_priv->loading;
215
 
216
        fw_priv->loading = simple_strtol(buf, NULL, 10);
217
 
218
        switch (fw_priv->loading) {
219
        case -1:
220
                fw_priv->abort = 1;
221
                wmb();
222
                complete(&fw_priv->completion);
223
                break;
224
        case 1:
225
                kfree(fw_priv->fw->data);
226
                fw_priv->fw->data = NULL;
227
                fw_priv->fw->size = 0;
228
                fw_priv->alloc_size = 0;
229
                break;
230
        case 0:
231
                if (prev_loading == 1)
232
                        complete(&fw_priv->completion);
233
                break;
234
        }
235
 
236
        return count;
237
}
238
 
239
static int
240
firmware_data_read(char *buffer, char **start, off_t offset,
241
                   int count, int *eof, void *data)
242
{
243
        struct firmware_priv *fw_priv = data;
244
        struct firmware *fw = fw_priv->fw;
245
 
246
        if (offset > fw->size)
247
                return 0;
248
        if (offset + count > fw->size)
249
                count = fw->size - offset;
250
 
251
        memcpy(buffer, fw->data + offset, count);
252
        *start = (void *) ((long) count);
253
        return count;
254
}
255
static int
256
fw_realloc_buffer(struct firmware_priv *fw_priv, int min_size)
257
{
258
        u8 *new_data;
259
        int new_size;
260
 
261
        if (min_size <= fw_priv->alloc_size)
262
                return 0;
263
        if((min_size % PAGE_SIZE) == 0)
264
                new_size = min_size;
265
        else
266
                new_size = (min_size + PAGE_SIZE) & PAGE_MASK;
267
        new_data = vmalloc(new_size);
268
        if (!new_data) {
269
                printk(KERN_ERR "%s: unable to alloc buffer\n", __FUNCTION__);
270
                /* Make sure that we don't keep incomplete data */
271
                fw_priv->abort = 1;
272
                return -ENOMEM;
273
        }
274
        fw_priv->alloc_size = new_size;
275
        if (fw_priv->fw->data) {
276
                memcpy(new_data, fw_priv->fw->data, fw_priv->fw->size);
277
                vfree(fw_priv->fw->data);
278
        }
279
        fw_priv->fw->data = new_data;
280
        BUG_ON(min_size > fw_priv->alloc_size);
281
        return 0;
282
}
283
 
284
/**
285
 * firmware_data_write:
286
 *
287
 * Description:
288
 *
289
 *      Data written to the 'data' attribute will be later handled to
290
 *      the driver as a firmware image.
291
 **/
292
static int
293
firmware_data_write(struct file *file, const char *buffer,
294
                    unsigned long count, void *data)
295
{
296
        struct firmware_priv *fw_priv = data;
297
        struct firmware *fw = fw_priv->fw;
298
        int offset = file->f_pos;
299
        int retval;
300
 
301
        retval = fw_realloc_buffer(fw_priv, offset + count);
302
        if (retval) {
303
                printk("%s: retval:%d\n", __FUNCTION__, retval);
304
                return retval;
305
        }
306
 
307
        memcpy(fw->data + offset, buffer, count);
308
 
309
        fw->size = max_t(size_t, offset + count, fw->size);
310
        file->f_pos += count;
311
        return count;
312
}
313
 
314
static void
315
firmware_class_timeout(u_long data)
316
{
317
        struct firmware_priv *fw_priv = (struct firmware_priv *) data;
318
        fw_priv->abort = 1;
319
        wmb();
320
        complete(&fw_priv->completion);
321
}
322
static int
323
fw_setup_class_device(struct firmware_priv **fw_priv_p,
324
                      const char *fw_name, const char *device)
325
{
326
        int retval;
327
        struct firmware_priv *fw_priv = kmalloc(sizeof (struct firmware_priv),
328
                                                GFP_KERNEL);
329
        *fw_priv_p = fw_priv;
330
        if (!fw_priv) {
331
                retval = -ENOMEM;
332
                goto out;
333
        }
334
        memset(fw_priv, 0, sizeof (*fw_priv));
335
 
336
        init_completion(&fw_priv->completion);
337
 
338
        fw_priv->timeout.function = firmware_class_timeout;
339
        fw_priv->timeout.data = (u_long) fw_priv;
340
        init_timer(&fw_priv->timeout);
341
 
342
        retval = -EAGAIN;
343
        fw_priv->proc_dir = create_proc_entry(device, 0644 | S_IFDIR, proc_dir);
344
        if (!fw_priv->proc_dir)
345
                goto err_free_fw_priv;
346
 
347
        fw_priv->attr_data = create_proc_entry("data", 0644 | S_IFREG,
348
                                               fw_priv->proc_dir);
349
        if (!fw_priv->attr_data)
350
                goto err_remove_dir;
351
 
352
        fw_priv->attr_data->read_proc = firmware_data_read;
353
        fw_priv->attr_data->write_proc = firmware_data_write;
354
        fw_priv->attr_data->data = fw_priv;
355
 
356
        fw_priv->attr_loading = create_proc_entry("loading", 0644 | S_IFREG,
357
                                                  fw_priv->proc_dir);
358
        if (!fw_priv->attr_loading)
359
                goto err_remove_data;
360
 
361
        fw_priv->attr_loading->read_proc = firmware_loading_show;
362
        fw_priv->attr_loading->write_proc = firmware_loading_store;
363
        fw_priv->attr_loading->data = fw_priv;
364
 
365
        retval = 0;
366
        fw_priv->fw = kmalloc(sizeof (struct firmware), GFP_KERNEL);
367
        if (!fw_priv->fw) {
368
                printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n",
369
                       __FUNCTION__);
370
                retval = -ENOMEM;
371
                goto err_remove_loading;
372
        }
373
        memset(fw_priv->fw, 0, sizeof (*fw_priv->fw));
374
 
375
        goto out;
376
 
377
err_remove_loading:
378
        remove_proc_entry("loading", fw_priv->proc_dir);
379
err_remove_data:
380
        remove_proc_entry("data", fw_priv->proc_dir);
381
err_remove_dir:
382
        remove_proc_entry(device, proc_dir);
383
err_free_fw_priv:
384
        kfree(fw_priv);
385
out:
386
        return retval;
387
}
388
static void
389
fw_remove_class_device(struct firmware_priv *fw_priv)
390
{
391
        remove_proc_entry("loading", fw_priv->proc_dir);
392
        remove_proc_entry("data", fw_priv->proc_dir);
393
        remove_proc_entry(fw_priv->proc_dir->name, proc_dir);
394
}
395
 
396
/**
397
 * request_firmware: - request firmware to hotplug and wait for it
398
 * Description:
399
 *      @firmware will be used to return a firmware image by the name
400
 *      of @name for device @device.
401
 *
402
 *      Should be called from user context where sleeping is allowed.
403
 *
404
 *      @name will be use as $FIRMWARE in the hotplug environment and
405
 *      should be distinctive enough not to be confused with any other
406
 *      firmware image for this or any other device.
407
 **/
408
int
409
request_firmware(const struct firmware **firmware, const char *name,
410
                 const char *device)
411
{
412
        struct firmware_priv *fw_priv;
413
        int retval;
414
 
415
        if (!firmware) {
416
                retval = -EINVAL;
417
                goto out;
418
        }
419
        *firmware = NULL;
420
 
421
        retval = fw_setup_class_device(&fw_priv, name, device);
422
        if (retval)
423
                goto out;
424
 
425
        retval = call_helper("add", name, device);
426
        if (retval)
427
                goto out;
428
        if (loading_timeout) {
429
                fw_priv->timeout.expires = jiffies + loading_timeout * HZ;
430
                add_timer(&fw_priv->timeout);
431
        }
432
 
433
        wait_for_completion(&fw_priv->completion);
434
 
435
        del_timer(&fw_priv->timeout);
436
        fw_remove_class_device(fw_priv);
437
 
438
        if (fw_priv->fw->size && !fw_priv->abort) {
439
                *firmware = fw_priv->fw;
440
        } else {
441
                retval = -ENOENT;
442
                vfree(fw_priv->fw->data);
443
                kfree(fw_priv->fw);
444
        }
445
out:
446
        kfree(fw_priv);
447
        return retval;
448
}
449
 
450
void
451
release_firmware(const struct firmware *fw)
452
{
453
        if (fw) {
454
                vfree(fw->data);
455
                kfree(fw);
456
        }
457
}
458
 
459
/**
460
 * register_firmware: - provide a firmware image for later usage
461
 *
462
 * Description:
463
 *      Make sure that @data will be available by requesting firmware @name.
464
 *
465
 *      Note: This will not be possible until some kind of persistence
466
 *      is available.
467
 **/
468
void
469
register_firmware(const char *name, const u8 *data, size_t size)
470
{
471
        /* This is meaningless without firmware caching, so until we
472
         * decide if firmware caching is reasonable just leave it as a
473
         * noop */
474
}
475
 
476
/* Async support */
477
struct firmware_work {
478
        struct tq_struct work;
479
        struct module *module;
480
        const char *name;
481
        const char *device;
482
        void *context;
483
        void (*cont)(const struct firmware *fw, void *context);
484
};
485
 
486
static void
487
request_firmware_work_func(void *arg)
488
{
489
        struct firmware_work *fw_work = arg;
490
        const struct firmware *fw;
491
        if (!arg)
492
                return;
493
        request_firmware(&fw, fw_work->name, fw_work->device);
494
        fw_work->cont(fw, fw_work->context);
495
        release_firmware(fw);
496
        __MOD_DEC_USE_COUNT(fw_work->module);
497
        kfree(fw_work);
498
}
499
 
500
/**
501
 * request_firmware_nowait:
502
 *
503
 * Description:
504
 *      Asynchronous variant of request_firmware() for contexts where
505
 *      it is not possible to sleep.
506
 *
507
 *      @cont will be called asynchronously when the firmware request is over.
508
 *
509
 *      @context will be passed over to @cont.
510
 *
511
 *      @fw may be %NULL if firmware request fails.
512
 *
513
 **/
514
int
515
request_firmware_nowait(
516
        struct module *module,
517
        const char *name, const char *device, void *context,
518
        void (*cont)(const struct firmware *fw, void *context))
519
{
520
        struct firmware_work *fw_work = kmalloc(sizeof (struct firmware_work),
521
                                                GFP_ATOMIC);
522
        if (!fw_work)
523
                return -ENOMEM;
524
        if (!try_inc_mod_count(module)) {
525
                kfree(fw_work);
526
                return -EFAULT;
527
        }
528
 
529
        *fw_work = (struct firmware_work) {
530
                .module = module,
531
                .name = name,
532
                .device = device,
533
                .context = context,
534
                .cont = cont,
535
        };
536
        INIT_TQUEUE(&fw_work->work, request_firmware_work_func, fw_work);
537
 
538
        schedule_task(&fw_work->work);
539
        return 0;
540
}
541
 
542
static int __init
543
firmware_class_init(void)
544
{
545
        proc_dir = create_proc_entry("driver/firmware", 0755 | S_IFDIR, NULL);
546
        if (!proc_dir)
547
                return -EAGAIN;
548
        proc_dir_timeout = create_proc_entry("timeout",
549
                                             0644 | S_IFREG, proc_dir);
550
        if (!proc_dir_timeout) {
551
                remove_proc_entry("driver/firmware", NULL);
552
                return -EAGAIN;
553
        }
554
        proc_dir_timeout->read_proc = firmware_timeout_show;
555
        proc_dir_timeout->write_proc = firmware_timeout_store;
556
        return 0;
557
}
558
static void __exit
559
firmware_class_exit(void)
560
{
561
        remove_proc_entry("timeout", proc_dir);
562
        remove_proc_entry("driver/firmware", NULL);
563
}
564
 
565
module_init(firmware_class_init);
566
module_exit(firmware_class_exit);
567
 
568
#ifndef CONFIG_FW_LOADER
569
EXPORT_SYMBOL(release_firmware);
570
EXPORT_SYMBOL(request_firmware);
571
EXPORT_SYMBOL(request_firmware_nowait);
572
EXPORT_SYMBOL(register_firmware);
573
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.