Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | |
2 | request_firmware() hotplug interface: | |
3 | ------------------------------------ | |
4 | Copyright (C) 2003 Manuel Estrada Sainz <ranty@debian.org> | |
5 | ||
6 | Why: | |
7 | --- | |
8 | ||
9 | Today, the most extended way to use firmware in the Linux kernel is linking | |
10 | it statically in a header file. Which has political and technical issues: | |
11 | ||
12 | 1) Some firmware is not legal to redistribute. | |
13 | 2) The firmware occupies memory permanently, even though it often is just | |
14 | used once. | |
15 | 3) Some people, like the Debian crowd, don't consider some firmware free | |
16 | enough and remove entire drivers (e.g.: keyspan). | |
17 | ||
18 | High level behavior (mixed): | |
19 | ============================ | |
20 | ||
21 | kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device) | |
22 | ||
23 | userspace: | |
24 | - /sys/class/firmware/xxx/{loading,data} appear. | |
25 | - hotplug gets called with a firmware identifier in $FIRMWARE | |
26 | and the usual hotplug environment. | |
27 | - hotplug: echo 1 > /sys/class/firmware/xxx/loading | |
28 | ||
29 | kernel: Discard any previous partial load. | |
30 | ||
31 | userspace: | |
32 | - hotplug: cat appropriate_firmware_image > \ | |
33 | /sys/class/firmware/xxx/data | |
34 | ||
35 | kernel: grows a buffer in PAGE_SIZE increments to hold the image as it | |
36 | comes in. | |
37 | ||
38 | userspace: | |
39 | - hotplug: echo 0 > /sys/class/firmware/xxx/loading | |
40 | ||
41 | kernel: request_firmware() returns and the driver has the firmware | |
42 | image in fw_entry->{data,size}. If something went wrong | |
43 | request_firmware() returns non-zero and fw_entry is set to | |
44 | NULL. | |
45 | ||
46 | kernel(driver): Driver code calls release_firmware(fw_entry) releasing | |
47 | the firmware image and any related resource. | |
48 | ||
49 | High level behavior (driver code): | |
50 | ================================== | |
51 | ||
52 | if(request_firmware(&fw_entry, $FIRMWARE, device) == 0) | |
53 | copy_fw_to_device(fw_entry->data, fw_entry->size); | |
54 | release(fw_entry); | |
55 | ||
56 | Sample/simple hotplug script: | |
57 | ============================ | |
58 | ||
59 | # Both $DEVPATH and $FIRMWARE are already provided in the environment. | |
60 | ||
61 | HOTPLUG_FW_DIR=/usr/lib/hotplug/firmware/ | |
62 | ||
63 | echo 1 > /sys/$DEVPATH/loading | |
64 | cat $HOTPLUG_FW_DIR/$FIRMWARE > /sysfs/$DEVPATH/data | |
65 | echo 0 > /sys/$DEVPATH/loading | |
66 | ||
67 | Random notes: | |
68 | ============ | |
69 | ||
70 | - "echo -1 > /sys/class/firmware/xxx/loading" will cancel the load at | |
71 | once and make request_firmware() return with error. | |
72 | ||
73 | - firmware_data_read() and firmware_loading_show() are just provided | |
74 | for testing and completeness, they are not called in normal use. | |
75 | ||
76 | - There is also /sys/class/firmware/timeout which holds a timeout in | |
77 | seconds for the whole load operation. | |
78 | ||
79 | - request_firmware_nowait() is also provided for convenience in | |
80 | non-user contexts. | |
81 | ||
82 | ||
83 | about in-kernel persistence: | |
84 | --------------------------- | |
85 | Under some circumstances, as explained below, it would be interesting to keep | |
86 | firmware images in non-swappable kernel memory or even in the kernel image | |
87 | (probably within initramfs). | |
88 | ||
89 | Note that this functionality has not been implemented. | |
90 | ||
91 | - Why OPTIONAL in-kernel persistence may be a good idea sometimes: | |
92 | ||
93 | - If the device that needs the firmware is needed to access the | |
94 | filesystem. When upon some error the device has to be reset and the | |
95 | firmware reloaded, it won't be possible to get it from userspace. | |
96 | e.g.: | |
97 | - A diskless client with a network card that needs firmware. | |
98 | - The filesystem is stored in a disk behind an scsi device | |
99 | that needs firmware. | |
100 | - Replacing buggy DSDT/SSDT ACPI tables on boot. | |
101 | Note: this would require the persistent objects to be included | |
102 | within the kernel image, probably within initramfs. | |
103 | ||
104 | And the same device can be needed to access the filesystem or not depending | |
105 | on the setup, so I think that the choice on what firmware to make | |
106 | persistent should be left to userspace. | |
107 |