| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 |  | 
 | 2 |  request_firmware() hotplug interface: | 
 | 3 |  ------------------------------------ | 
| Markus Rechberger | 87d37a4 | 2007-06-04 18:45:44 +0200 | [diff] [blame] | 4 | 	Copyright (C) 2003 Manuel Estrada Sainz | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 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 |  |