lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Sat, 27 Nov 2021 19:45:30 +0200 From: Ido Schimmel <idosch@...sch.org> To: netdev@...r.kernel.org Cc: davem@...emloft.net, kuba@...nel.org, andrew@...n.ch, mkubecek@...e.cz, pali@...nel.org, jacob.e.keller@...el.com, vadimp@...dia.com, mlxsw@...dia.com, Ido Schimmel <idosch@...dia.com> Subject: [RFC PATCH net-next 4/4] netdevsim: Implement support for ethtool_ops::start_fw_flash_module From: Ido Schimmel <idosch@...dia.com> For RFC purposes only, implement support for ethtool_ops::start_fw_flash_module. A real implementation is expected to call CMIS common code (WIP) that can be shared across all MAC drivers. Signed-off-by: Ido Schimmel <idosch@...dia.com> --- drivers/net/netdevsim/ethtool.c | 129 ++++++++++++++++++++++++++++++ drivers/net/netdevsim/netdevsim.h | 10 +++ 2 files changed, 139 insertions(+) diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c index 690cd12a4245..f126b03bf5b0 100644 --- a/drivers/net/netdevsim/ethtool.c +++ b/drivers/net/netdevsim/ethtool.c @@ -3,6 +3,8 @@ #include <linux/debugfs.h> #include <linux/ethtool.h> +#include <linux/ethtool_netlink.h> +#include <linux/firmware.h> #include <linux/random.h> #include "netdevsim.h" @@ -171,6 +173,127 @@ static int nsim_get_module_fw_info(struct net_device *dev, return 0; } +static void nsim_module_fw_flash_download(struct netdevsim *ns) +{ + struct ethtool_module_fw_flash_ntf_params params = {}; + + params.status = ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS; + params.status_msg = "Downloading firmware image"; + params.done = 0; + params.total = 1500; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + msleep(5000); + + params.done = 750; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + msleep(5000); + + params.done = 1500; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + msleep(5000); +} + +static void nsim_module_fw_flash_validate(struct netdevsim *ns) +{ + struct ethtool_module_fw_flash_ntf_params params = {}; + + params.status = ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS; + params.status_msg = "Validating firmware image download"; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + msleep(5000); +} + +static void nsim_module_fw_flash_run(struct netdevsim *ns) +{ + struct ethtool_module_fw_flash_ntf_params params = {}; + + params.status = ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS; + params.status_msg = "Running firmware image"; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + msleep(5000); +} + +static void nsim_module_fw_flash_commit(struct netdevsim *ns) +{ + struct ethtool_module_fw_flash_ntf_params params = {}; + + if (!ns->ethtool.module_fw.params.commit) + return; + + params.status = ETHTOOL_MODULE_FW_FLASH_STATUS_IN_PROGRESS; + params.status_msg = "Committing firmware image"; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + msleep(5000); +} + +static void nsim_module_fw_flash(struct work_struct *work) +{ + struct ethtool_module_fw_flash_ntf_params params = {}; + struct netdevsim *ns; + + ns = container_of(work, struct netdevsim, ethtool.module_fw.work); + + params.status = ETHTOOL_MODULE_FW_FLASH_STATUS_STARTED; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + if (!ns->ethtool.module_fw.fw) + goto commit; + + nsim_module_fw_flash_download(ns); + nsim_module_fw_flash_validate(ns); + nsim_module_fw_flash_run(ns); +commit: + nsim_module_fw_flash_commit(ns); + + params.status = ETHTOOL_MODULE_FW_FLASH_STATUS_COMPLETED; + ethnl_module_fw_flash_ntf(ns->netdev, ¶ms); + + dev_put(ns->netdev); + rtnl_lock(); + ns->ethtool.module_fw.in_progress = false; + rtnl_unlock(); + release_firmware(ns->ethtool.module_fw.fw); +} + +static int +nsim_start_fw_flash_module(struct net_device *dev, + const struct ethtool_module_fw_flash_params *params, + struct netlink_ext_ack *extack) +{ + struct netdevsim *ns = netdev_priv(dev); + + if (ns->ethtool.module_fw.in_progress) { + NL_SET_ERR_MSG(extack, "Module firmware flashing already in progress"); + return -EBUSY; + } + + ns->ethtool.module_fw.fw = NULL; + if (params->file_name) { + int err; + + err = request_firmware(&ns->ethtool.module_fw.fw, + params->file_name, &dev->dev); + if (err) { + NL_SET_ERR_MSG(extack, + "Failed to request module firmware image"); + return err; + } + } + + ns->ethtool.module_fw.in_progress = true; + dev_hold(dev); + ns->ethtool.module_fw.params = *params; + schedule_work(&ns->ethtool.module_fw.work); + + return 0; +} + static const struct ethtool_ops nsim_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_ALL_PARAMS, .get_pause_stats = nsim_get_pause_stats, @@ -185,6 +308,7 @@ static const struct ethtool_ops nsim_ethtool_ops = { .get_fecparam = nsim_get_fecparam, .set_fecparam = nsim_set_fecparam, .get_module_fw_info = nsim_get_module_fw_info, + .start_fw_flash_module = nsim_start_fw_flash_module, }; static void nsim_ethtool_ring_init(struct netdevsim *ns) @@ -228,4 +352,9 @@ void nsim_ethtool_init(struct netdevsim *ns) &ns->ethtool.ring.rx_mini_max_pending); debugfs_create_u32("tx_max_pending", 0600, dir, &ns->ethtool.ring.tx_max_pending); + + /* The work item holds a reference on the netdev, so its unregistration + * cannot be completed while the work is queued or executing. + */ + INIT_WORK(&ns->ethtool.module_fw.work, nsim_module_fw_flash); } diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index c49771f27f17..afa8f9c7f22c 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -16,6 +16,7 @@ #include <linux/debugfs.h> #include <linux/device.h> #include <linux/ethtool.h> +#include <linux/firmware.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/netdevice.h> @@ -59,14 +60,23 @@ struct nsim_ethtool_pauseparam { bool report_stats_tx; }; +struct nsim_ethtool_module_fw { + struct ethtool_module_fw_flash_params params; + struct work_struct work; + const struct firmware *fw; + bool in_progress; +}; + struct nsim_ethtool { u32 get_err; u32 set_err; u32 channels; struct nsim_ethtool_pauseparam pauseparam; + struct nsim_ethtool_module_fw module_fw; struct ethtool_coalesce coalesce; struct ethtool_ringparam ring; struct ethtool_fecparam fec; + }; struct netdevsim { -- 2.31.1
Powered by blists - more mailing lists