diff options
Diffstat (limited to 'Documentation/firmware_class/README')
-rw-r--r-- | Documentation/firmware_class/README | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README new file mode 100644 index 000000000000..43e836c07ae8 --- /dev/null +++ b/Documentation/firmware_class/README | |||
@@ -0,0 +1,124 @@ | |||
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 | |||
108 | - Why register_firmware()+__init can be useful: | ||
109 | - For boot devices needing firmware. | ||
110 | - To make the transition easier: | ||
111 | The firmware can be declared __init and register_firmware() | ||
112 | called on module_init. Then the firmware is warranted to be | ||
113 | there even if "firmware hotplug userspace" is not there yet or | ||
114 | it doesn't yet provide the needed firmware. | ||
115 | Once the firmware is widely available in userspace, it can be | ||
116 | removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE). | ||
117 | |||
118 | In either case, if firmware hotplug support is there, it can move the | ||
119 | firmware out of kernel memory into the real filesystem for later | ||
120 | usage. | ||
121 | |||
122 | Note: If persistence is implemented on top of initramfs, | ||
123 | register_firmware() may not be appropriate. | ||
124 | |||