diff options
author | Russ Weight <russell.h.weight@intel.com> | 2022-04-21 14:22:00 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-04-26 12:34:28 +0200 |
commit | 97730bbb242cde22b7140acd202ffd88823886c9 (patch) | |
tree | b09e50663744488f3b91ed37a764837a06355bb2 /drivers/base/firmware_loader/sysfs.c | |
parent | e0c11a8b985137aebf4bcd07cd957b80ac23924d (diff) |
firmware_loader: Add firmware-upload support
Extend the firmware subsystem to support a persistent sysfs interface that
userspace may use to initiate a firmware update. For example, FPGA based
PCIe cards load firmware and FPGA images from local FLASH when the card
boots. The images in FLASH may be updated with new images provided by the
user at his/her convenience.
A device driver may call firmware_upload_register() to expose persistent
"loading" and "data" sysfs files. These files are used in the same way as
the fallback sysfs "loading" and "data" files. When 0 is written to
"loading" to complete the write of firmware data, the data is transferred
to the lower-level driver using pre-registered call-back functions. The
data transfer is done in the context of a kernel worker thread.
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: Tianfei zhang <tianfei.zhang@intel.com>
Tested-by: Matthew Gerlach <matthew.gerlach@linux.intel.com>
Signed-off-by: Russ Weight <russell.h.weight@intel.com>
Link: https://lore.kernel.org/r/20220421212204.36052-5-russell.h.weight@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/firmware_loader/sysfs.c')
-rw-r--r-- | drivers/base/firmware_loader/sysfs.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/base/firmware_loader/sysfs.c b/drivers/base/firmware_loader/sysfs.c index 1509cb6b6e60..4a956cc3b7ea 100644 --- a/drivers/base/firmware_loader/sysfs.c +++ b/drivers/base/firmware_loader/sysfs.c @@ -6,8 +6,8 @@ #include <linux/slab.h> #include <linux/types.h> -#include "firmware.h" #include "sysfs.h" +#include "sysfs_upload.h" /* * sysfs support for firmware loader @@ -94,6 +94,10 @@ static void fw_dev_release(struct device *dev) { struct fw_sysfs *fw_sysfs = to_fw_sysfs(dev); + if (fw_sysfs->fw_upload_priv) { + free_fw_priv(fw_sysfs->fw_priv); + kfree(fw_sysfs->fw_upload_priv); + } kfree(fw_sysfs); } @@ -199,6 +203,14 @@ static ssize_t firmware_loading_store(struct device *dev, written = rc; } else { fw_state_done(fw_priv); + + /* + * If this is a user-initiated firmware upload + * then start the upload in a worker thread now. + */ + rc = fw_upload_start(fw_sysfs); + if (rc) + written = rc; } break; } @@ -208,6 +220,9 @@ static ssize_t firmware_loading_store(struct device *dev, fallthrough; case -1: fw_load_abort(fw_sysfs); + if (fw_sysfs->fw_upload_priv) + fw_state_init(fw_sysfs->fw_priv); + break; } out: @@ -215,7 +230,7 @@ out: return written; } -static DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); +DEVICE_ATTR(loading, 0644, firmware_loading_show, firmware_loading_store); static void firmware_rw_data(struct fw_priv *fw_priv, char *buffer, loff_t offset, size_t count, bool read) |