123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- .. SPDX-License-Identifier: GPL-2.0
- ===================
- Firmware Upload API
- ===================
- A device driver that registers with the firmware loader will expose
- persistent sysfs nodes to enable users to initiate firmware updates for
- that device. It is the responsibility of the device driver and/or the
- device itself to perform any validation on the data received. Firmware
- upload uses the same *loading* and *data* sysfs files described in the
- documentation for firmware fallback. It also adds additional sysfs files
- to provide status on the transfer of the firmware image to the device.
- Register for firmware upload
- ============================
- A device driver registers for firmware upload by calling
- firmware_upload_register(). Among the parameter list is a name to
- identify the device under /sys/class/firmware. A user may initiate a
- firmware upload by echoing a 1 to the *loading* sysfs file for the target
- device. Next, the user writes the firmware image to the *data* sysfs
- file. After writing the firmware data, the user echos 0 to the *loading*
- sysfs file to signal completion. Echoing 0 to *loading* also triggers the
- transfer of the firmware to the lower-lever device driver in the context
- of a kernel worker thread.
- To use the firmware upload API, write a driver that implements a set of
- ops. The probe function calls firmware_upload_register() and the remove
- function calls firmware_upload_unregister() such as::
- static const struct fw_upload_ops m10bmc_ops = {
- .prepare = m10bmc_sec_prepare,
- .write = m10bmc_sec_write,
- .poll_complete = m10bmc_sec_poll_complete,
- .cancel = m10bmc_sec_cancel,
- .cleanup = m10bmc_sec_cleanup,
- };
- static int m10bmc_sec_probe(struct platform_device *pdev)
- {
- const char *fw_name, *truncate;
- struct m10bmc_sec *sec;
- struct fw_upload *fwl;
- unsigned int len;
- sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL);
- if (!sec)
- return -ENOMEM;
- sec->dev = &pdev->dev;
- sec->m10bmc = dev_get_drvdata(pdev->dev.parent);
- dev_set_drvdata(&pdev->dev, sec);
- fw_name = dev_name(sec->dev);
- truncate = strstr(fw_name, ".auto");
- len = (truncate) ? truncate - fw_name : strlen(fw_name);
- sec->fw_name = kmemdup_nul(fw_name, len, GFP_KERNEL);
- fwl = firmware_upload_register(sec->dev, sec->fw_name, &m10bmc_ops, sec);
- if (IS_ERR(fwl)) {
- dev_err(sec->dev, "Firmware Upload driver failed to start\n");
- kfree(sec->fw_name);
- return PTR_ERR(fwl);
- }
- sec->fwl = fwl;
- return 0;
- }
- static int m10bmc_sec_remove(struct platform_device *pdev)
- {
- struct m10bmc_sec *sec = dev_get_drvdata(&pdev->dev);
- firmware_upload_unregister(sec->fwl);
- kfree(sec->fw_name);
- return 0;
- }
- firmware_upload_register
- ------------------------
- .. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c
- :identifiers: firmware_upload_register
- firmware_upload_unregister
- --------------------------
- .. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.c
- :identifiers: firmware_upload_unregister
- Firmware Upload Ops
- -------------------
- .. kernel-doc:: include/linux/firmware.h
- :identifiers: fw_upload_ops
- Firmware Upload Progress Codes
- ------------------------------
- The following progress codes are used internally by the firmware loader.
- Corresponding strings are reported through the status sysfs node that
- is described below and are documented in the ABI documentation.
- .. kernel-doc:: drivers/base/firmware_loader/sysfs_upload.h
- :identifiers: fw_upload_prog
- Firmware Upload Error Codes
- ---------------------------
- The following error codes may be returned by the driver ops in case of
- failure:
- .. kernel-doc:: include/linux/firmware.h
- :identifiers: fw_upload_err
- Sysfs Attributes
- ================
- In addition to the *loading* and *data* sysfs files, there are additional
- sysfs files to monitor the status of the data transfer to the target
- device and to determine the final pass/fail status of the transfer.
- Depending on the device and the size of the firmware image, a firmware
- update could take milliseconds or minutes.
- The additional sysfs files are:
- * status - provides an indication of the progress of a firmware update
- * error - provides error information for a failed firmware update
- * remaining_size - tracks the data transfer portion of an update
- * cancel - echo 1 to this file to cancel the update
|