| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | =================== |
| 2 | Fallback mechanisms |
| 3 | =================== |
| 4 | |
| 5 | A fallback mechanism is supported to allow to overcome failures to do a direct |
| 6 | filesystem lookup on the root filesystem or when the firmware simply cannot be |
| 7 | installed for practical reasons on the root filesystem. The kernel |
| 8 | configuration options related to supporting the firmware fallback mechanism are: |
| 9 | |
| 10 | * CONFIG_FW_LOADER_USER_HELPER: enables building the firmware fallback |
| 11 | mechanism. Most distributions enable this option today. If enabled but |
| 12 | CONFIG_FW_LOADER_USER_HELPER_FALLBACK is disabled, only the custom fallback |
| 13 | mechanism is available and for the request_firmware_nowait() call. |
| 14 | * CONFIG_FW_LOADER_USER_HELPER_FALLBACK: force enables each request to |
| 15 | enable the kobject uevent fallback mechanism on all firmware API calls |
| 16 | except request_firmware_direct(). Most distributions disable this option |
| 17 | today. The call request_firmware_nowait() allows for one alternative |
| 18 | fallback mechanism: if this kconfig option is enabled and your second |
| 19 | argument to request_firmware_nowait(), uevent, is set to false you are |
| 20 | informing the kernel that you have a custom fallback mechanism and it will |
| 21 | manually load the firmware. Read below for more details. |
| 22 | |
| 23 | Note that this means when having this configuration: |
| 24 | |
| 25 | CONFIG_FW_LOADER_USER_HELPER=y |
| 26 | CONFIG_FW_LOADER_USER_HELPER_FALLBACK=n |
| 27 | |
| 28 | the kobject uevent fallback mechanism will never take effect even |
| 29 | for request_firmware_nowait() when uevent is set to true. |
| 30 | |
| 31 | Justifying the firmware fallback mechanism |
| 32 | ========================================== |
| 33 | |
| 34 | Direct filesystem lookups may fail for a variety of reasons. Known reasons for |
| 35 | this are worth itemizing and documenting as it justifies the need for the |
| 36 | fallback mechanism: |
| 37 | |
| 38 | * Race against access with the root filesystem upon bootup. |
| 39 | |
| 40 | * Races upon resume from suspend. This is resolved by the firmware cache, but |
| 41 | the firmware cache is only supported if you use uevents, and its not |
| 42 | supported for request_firmware_into_buf(). |
| 43 | |
| 44 | * Firmware is not accessible through typical means: |
| 45 | * It cannot be installed into the root filesystem |
| 46 | * The firmware provides very unique device specific data tailored for |
| 47 | the unit gathered with local information. An example is calibration |
| 48 | data for WiFi chipsets for mobile devices. This calibration data is |
| 49 | not common to all units, but tailored per unit. Such information may |
| 50 | be installed on a separate flash partition other than where the root |
| 51 | filesystem is provided. |
| 52 | |
| 53 | Types of fallback mechanisms |
| 54 | ============================ |
| 55 | |
| 56 | There are really two fallback mechanisms available using one shared sysfs |
| 57 | interface as a loading facility: |
| 58 | |
| 59 | * Kobject uevent fallback mechanism |
| 60 | * Custom fallback mechanism |
| 61 | |
| 62 | First lets document the shared sysfs loading facility. |
| 63 | |
| 64 | Firmware sysfs loading facility |
| 65 | =============================== |
| 66 | |
| 67 | In order to help device drivers upload firmware using a fallback mechanism |
| 68 | the firmware infrastructure creates a sysfs interface to enable userspace |
| 69 | to load and indicate when firmware is ready. The sysfs directory is created |
| 70 | via fw_create_instance(). This call creates a new struct device named after |
| 71 | the firmware requested, and establishes it in the device hierarchy by |
| 72 | associating the device used to make the request as the device's parent. |
| 73 | The sysfs directory's file attributes are defined and controlled through |
| 74 | the new device's class (firmware_class) and group (fw_dev_attr_groups). |
| 75 | This is actually where the original firmware_class module name came from, |
| 76 | given that originally the only firmware loading mechanism available was the |
| 77 | mechanism we now use as a fallback mechanism, which registers a struct class |
| 78 | firmware_class. Because the attributes exposed are part of the module name, the |
| 79 | module name firmware_class cannot be renamed in the future, to ensure backward |
| 80 | compatibility with old userspace. |
| 81 | |
| 82 | To load firmware using the sysfs interface we expose a loading indicator, |
| 83 | and a file upload firmware into: |
| 84 | |
| 85 | * /sys/$DEVPATH/loading |
| 86 | * /sys/$DEVPATH/data |
| 87 | |
| 88 | To upload firmware you will echo 1 onto the loading file to indicate |
| 89 | you are loading firmware. You then write the firmware into the data file, |
| 90 | and you notify the kernel the firmware is ready by echo'ing 0 onto |
| 91 | the loading file. |
| 92 | |
| 93 | The firmware device used to help load firmware using sysfs is only created if |
| 94 | direct firmware loading fails and if the fallback mechanism is enabled for your |
| 95 | firmware request, this is set up with :c:func:`firmware_fallback_sysfs`. It is |
| 96 | important to re-iterate that no device is created if a direct filesystem lookup |
| 97 | succeeded. |
| 98 | |
| 99 | Using:: |
| 100 | |
| 101 | echo 1 > /sys/$DEVPATH/loading |
| 102 | |
| 103 | Will clean any previous partial load at once and make the firmware API |
| 104 | return an error. When loading firmware the firmware_class grows a buffer |
| 105 | for the firmware in PAGE_SIZE increments to hold the image as it comes in. |
| 106 | |
| 107 | firmware_data_read() and firmware_loading_show() are just provided for the |
| 108 | test_firmware driver for testing, they are not called in normal use or |
| 109 | expected to be used regularly by userspace. |
| 110 | |
| 111 | firmware_fallback_sysfs |
| 112 | ----------------------- |
| 113 | .. kernel-doc:: drivers/base/firmware_loader/fallback.c |
| 114 | :functions: firmware_fallback_sysfs |
| 115 | |
| 116 | Firmware kobject uevent fallback mechanism |
| 117 | ========================================== |
| 118 | |
| 119 | Since a device is created for the sysfs interface to help load firmware as a |
| 120 | fallback mechanism userspace can be informed of the addition of the device by |
| 121 | relying on kobject uevents. The addition of the device into the device |
| 122 | hierarchy means the fallback mechanism for firmware loading has been initiated. |
| 123 | For details of implementation refer to fw_load_sysfs_fallback(), in particular |
| 124 | on the use of dev_set_uevent_suppress() and kobject_uevent(). |
| 125 | |
| 126 | The kernel's kobject uevent mechanism is implemented in lib/kobject_uevent.c, |
| 127 | it issues uevents to userspace. As a supplement to kobject uevents Linux |
| 128 | distributions could also enable CONFIG_UEVENT_HELPER_PATH, which makes use of |
| 129 | core kernel's usermode helper (UMH) functionality to call out to a userspace |
| 130 | helper for kobject uevents. In practice though no standard distribution has |
| 131 | ever used the CONFIG_UEVENT_HELPER_PATH. If CONFIG_UEVENT_HELPER_PATH is |
| 132 | enabled this binary would be called each time kobject_uevent_env() gets called |
| 133 | in the kernel for each kobject uevent triggered. |
| 134 | |
| 135 | Different implementations have been supported in userspace to take advantage of |
| 136 | this fallback mechanism. When firmware loading was only possible using the |
| 137 | sysfs mechanism the userspace component "hotplug" provided the functionality of |
| 138 | monitoring for kobject events. Historically this was superseded be systemd's |
| 139 | udev, however firmware loading support was removed from udev as of systemd |
| 140 | commit be2ea723b1d0 ("udev: remove userspace firmware loading support") |
| 141 | as of v217 on August, 2014. This means most Linux distributions today are |
| 142 | not using or taking advantage of the firmware fallback mechanism provided |
| 143 | by kobject uevents. This is specially exacerbated due to the fact that most |
| 144 | distributions today disable CONFIG_FW_LOADER_USER_HELPER_FALLBACK. |
| 145 | |
| 146 | Refer to do_firmware_uevent() for details of the kobject event variables |
| 147 | setup. The variables currently passed to userspace with a "kobject add" |
| 148 | event are: |
| 149 | |
| 150 | * FIRMWARE=firmware name |
| 151 | * TIMEOUT=timeout value |
| 152 | * ASYNC=whether or not the API request was asynchronous |
| 153 | |
| 154 | By default DEVPATH is set by the internal kernel kobject infrastructure. |
| 155 | Below is an example simple kobject uevent script:: |
| 156 | |
| 157 | # Both $DEVPATH and $FIRMWARE are already provided in the environment. |
| 158 | MY_FW_DIR=/lib/firmware/ |
| 159 | echo 1 > /sys/$DEVPATH/loading |
| 160 | cat $MY_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data |
| 161 | echo 0 > /sys/$DEVPATH/loading |
| 162 | |
| 163 | Firmware custom fallback mechanism |
| 164 | ================================== |
| 165 | |
| 166 | Users of the request_firmware_nowait() call have yet another option available |
| 167 | at their disposal: rely on the sysfs fallback mechanism but request that no |
| 168 | kobject uevents be issued to userspace. The original logic behind this |
| 169 | was that utilities other than udev might be required to lookup firmware |
| 170 | in non-traditional paths -- paths outside of the listing documented in the |
| 171 | section 'Direct filesystem lookup'. This option is not available to any of |
| 172 | the other API calls as uevents are always forced for them. |
| 173 | |
| 174 | Since uevents are only meaningful if the fallback mechanism is enabled |
| 175 | in your kernel it would seem odd to enable uevents with kernels that do not |
| 176 | have the fallback mechanism enabled in their kernels. Unfortunately we also |
| 177 | rely on the uevent flag which can be disabled by request_firmware_nowait() to |
| 178 | also setup the firmware cache for firmware requests. As documented above, |
| 179 | the firmware cache is only set up if uevent is enabled for an API call. |
| 180 | Although this can disable the firmware cache for request_firmware_nowait() |
| 181 | calls, users of this API should not use it for the purposes of disabling |
| 182 | the cache as that was not the original purpose of the flag. Not setting |
| 183 | the uevent flag means you want to opt-in for the firmware fallback mechanism |
| 184 | but you want to suppress kobject uevents, as you have a custom solution which |
| 185 | will monitor for your device addition into the device hierarchy somehow and |
| 186 | load firmware for you through a custom path. |
| 187 | |
| 188 | Firmware fallback timeout |
| 189 | ========================= |
| 190 | |
| 191 | The firmware fallback mechanism has a timeout. If firmware is not loaded |
| 192 | onto the sysfs interface by the timeout value an error is sent to the |
| 193 | driver. By default the timeout is set to 60 seconds if uevents are |
| 194 | desirable, otherwise MAX_JIFFY_OFFSET is used (max timeout possible). |
| 195 | The logic behind using MAX_JIFFY_OFFSET for non-uevents is that a custom |
| 196 | solution will have as much time as it needs to load firmware. |
| 197 | |
| 198 | You can customize the firmware timeout by echo'ing your desired timeout into |
| 199 | the following file: |
| 200 | |
| 201 | * /sys/class/firmware/timeout |
| 202 | |
| 203 | If you echo 0 into it means MAX_JIFFY_OFFSET will be used. The data type |
| 204 | for the timeout is an int. |