devlink: move request_firmware out of driver
authorJacob Keller <jacob.e.keller@intel.com>
Wed, 18 Nov 2020 19:06:35 +0000 (11:06 -0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 20 Nov 2020 05:40:57 +0000 (21:40 -0800)
All drivers which implement the devlink flash update support, with the
exception of netdevsim, use either request_firmware or
request_firmware_direct to locate the firmware file. Rather than having
each driver do this separately as part of its .flash_update
implementation, perform the request_firmware within net/core/devlink.c

Replace the file_name parameter in the struct devlink_flash_update_params
with a pointer to the fw object.

Use request_firmware rather than request_firmware_direct. Although most
Linux distributions today do not have the fallback mechanism
implemented, only about half the drivers used the _direct request, as
compared to the generic request_firmware. In the event that
a distribution does support the fallback mechanism, the devlink flash
update ought to be able to use it to provide the firmware contents. For
distributions which do not support the fallback userspace mechanism,
there should be essentially no difference between request_firmware and
request_firmware_direct.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Acked-by: Shannon Nelson <snelson@pensando.io>
Acked-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
15 files changed:
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
drivers/net/ethernet/huawei/hinic/hinic_devlink.c
drivers/net/ethernet/intel/ice/ice_devlink.c
drivers/net/ethernet/mellanox/mlx5/core/devlink.c
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/netronome/nfp/nfp_devlink.c
drivers/net/ethernet/netronome/nfp/nfp_main.c
drivers/net/ethernet/netronome/nfp/nfp_main.h
drivers/net/ethernet/pensando/ionic/ionic_devlink.c
drivers/net/ethernet/pensando/ionic/ionic_devlink.h
drivers/net/ethernet/pensando/ionic/ionic_fw.c
include/net/devlink.h
net/core/devlink.c

index 184b6d0513b2a2fb9b819cd1513215f564ef4bb7..4ebae8a236fdd3ce81299c9e0abd6139c92f067b 100644 (file)
@@ -32,7 +32,7 @@ bnxt_dl_flash_update(struct devlink *dl,
 
        devlink_flash_update_begin_notify(dl);
        devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0);
-       rc = bnxt_flash_package_from_file(bp->dev, params->file_name, 0);
+       rc = bnxt_flash_package_from_fw_obj(bp->dev, params->fw, 0);
        if (!rc)
                devlink_flash_update_status_notify(dl, "Flashing done", NULL, 0, 0);
        else
index 1471c9a362388d0004b83e55fdaf750cd3c0f23f..7b444fcb628919fc5a295f958a04f31adf623981 100644 (file)
@@ -2419,13 +2419,12 @@ static int bnxt_flash_firmware_from_file(struct net_device *dev,
        return rc;
 }
 
-int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
-                                u32 install_type)
+int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware *fw,
+                                  u32 install_type)
 {
        struct bnxt *bp = netdev_priv(dev);
        struct hwrm_nvm_install_update_output *resp = bp->hwrm_cmd_resp_addr;
        struct hwrm_nvm_install_update_input install = {0};
-       const struct firmware *fw;
        u32 item_len;
        int rc = 0;
        u16 index;
@@ -2440,13 +2439,6 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
                return rc;
        }
 
-       rc = request_firmware(&fw, filename, &dev->dev);
-       if (rc != 0) {
-               netdev_err(dev, "PKG error %d requesting file: %s\n",
-                          rc, filename);
-               return rc;
-       }
-
        if (fw->size > item_len) {
                netdev_err(dev, "PKG insufficient update area in nvram: %lu\n",
                           (unsigned long)fw->size);
@@ -2478,7 +2470,6 @@ int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
                                          dma_handle);
                }
        }
-       release_firmware(fw);
        if (rc)
                goto err_exit;
 
@@ -2517,6 +2508,26 @@ err_exit:
        return rc;
 }
 
+static int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
+                                       u32 install_type)
+{
+       const struct firmware *fw;
+       int rc;
+
+       rc = request_firmware(&fw, filename, &dev->dev);
+       if (rc != 0) {
+               netdev_err(dev, "PKG error %d requesting file: %s\n",
+                          rc, filename);
+               return rc;
+       }
+
+       rc = bnxt_flash_package_from_fw_obj(dev, fw, install_type);
+
+       release_firmware(fw);
+
+       return rc;
+}
+
 static int bnxt_flash_device(struct net_device *dev,
                             struct ethtool_flash *flash)
 {
index fa6fbde52bea14ef697c24071acf60154dece7cc..0a57cb6a4a4bf029f0c3d0687b5edecf53e56a43 100644 (file)
@@ -94,8 +94,8 @@ u32 bnxt_fw_to_ethtool_speed(u16);
 u16 bnxt_get_fw_auto_link_speeds(u32);
 int bnxt_hwrm_nvm_get_dev_info(struct bnxt *bp,
                               struct hwrm_nvm_get_dev_info_output *nvm_dev_info);
-int bnxt_flash_package_from_file(struct net_device *dev, const char *filename,
-                                u32 install_type);
+int bnxt_flash_package_from_fw_obj(struct net_device *dev, const struct firmware *fw,
+                                  u32 install_type);
 void bnxt_ethtool_init(struct bnxt *bp);
 void bnxt_ethtool_free(struct bnxt *bp);
 
index 2630d667f3939278e0a584397a6cbeaa0cbdb04a..58d5646444b0251714df32d627dd57c700a6ce9e 100644 (file)
@@ -285,18 +285,8 @@ static int hinic_devlink_flash_update(struct devlink *devlink,
                                      struct netlink_ext_ack *extack)
 {
        struct hinic_devlink_priv *priv = devlink_priv(devlink);
-       const struct firmware *fw;
-       int err;
-
-       err = request_firmware_direct(&fw, params->file_name,
-                                     &priv->hwdev->hwif->pdev->dev);
-       if (err)
-               return err;
-
-       err = hinic_firmware_update(priv, fw, extack);
-       release_firmware(fw);
 
-       return err;
+       return hinic_firmware_update(priv, params->fw, extack);
 }
 
 static const struct devlink_ops hinic_devlink_ops = {
index 511da59bd6f2875d2f167eded45c1a765c01d1c7..0036d3e7df0bf513cfeaad582d4e1009902b3c01 100644 (file)
@@ -247,9 +247,7 @@ ice_devlink_flash_update(struct devlink *devlink,
                         struct netlink_ext_ack *extack)
 {
        struct ice_pf *pf = devlink_priv(devlink);
-       struct device *dev = &pf->pdev->dev;
        struct ice_hw *hw = &pf->hw;
-       const struct firmware *fw;
        u8 preservation;
        int err;
 
@@ -277,21 +275,11 @@ ice_devlink_flash_update(struct devlink *devlink,
        if (err)
                return err;
 
-       err = request_firmware(&fw, params->file_name, dev);
-       if (err) {
-               NL_SET_ERR_MSG_MOD(extack, "Unable to read file from disk");
-               return err;
-       }
-
-       dev_dbg(dev, "Beginning flash update with file '%s'\n", params->file_name);
-
        devlink_flash_update_begin_notify(devlink);
        devlink_flash_update_status_notify(devlink, "Preparing to flash", NULL, 0, 0);
-       err = ice_flash_pldm_image(pf, fw, preservation, extack);
+       err = ice_flash_pldm_image(pf, params->fw, preservation, extack);
        devlink_flash_update_end_notify(devlink);
 
-       release_firmware(fw);
-
        return err;
 }
 
index a28f95df2901d39bed296d1ebb606d21bdf82704..e2ed341648e4c4065712bce146472c662111b5b6 100644 (file)
@@ -13,17 +13,8 @@ static int mlx5_devlink_flash_update(struct devlink *devlink,
                                     struct netlink_ext_ack *extack)
 {
        struct mlx5_core_dev *dev = devlink_priv(devlink);
-       const struct firmware *fw;
-       int err;
-
-       err = request_firmware_direct(&fw, params->file_name, &dev->pdev->dev);
-       if (err)
-               return err;
-
-       err = mlx5_firmware_flash(dev, fw, extack);
-       release_firmware(fw);
 
-       return err;
+       return mlx5_firmware_flash(dev, params->fw, extack);
 }
 
 static u8 mlx5_fw_ver_major(u32 version)
index 1a86535c496858dd413fda33bb0c18d9cee5f222..630109f139a0bff7b4387f3249e6fc5d46dae389 100644 (file)
@@ -1117,16 +1117,7 @@ static int mlxsw_core_fw_flash_update(struct mlxsw_core *mlxsw_core,
                                      struct devlink_flash_update_params *params,
                                      struct netlink_ext_ack *extack)
 {
-       const struct firmware *firmware;
-       int err;
-
-       err = request_firmware_direct(&firmware, params->file_name, mlxsw_core->bus_info->dev);
-       if (err)
-               return err;
-       err = mlxsw_core_fw_flash(mlxsw_core, firmware, extack);
-       release_firmware(firmware);
-
-       return err;
+       return mlxsw_core_fw_flash(mlxsw_core, params->fw, extack);
 }
 
 static int mlxsw_core_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id,
index 97d2b03208de01f8497d58b7c89f6513a71ef19b..713ee3041d491992190863ea99061937ac04f4c3 100644 (file)
@@ -333,7 +333,7 @@ nfp_devlink_flash_update(struct devlink *devlink,
                         struct devlink_flash_update_params *params,
                         struct netlink_ext_ack *extack)
 {
-       return nfp_flash_update_common(devlink_priv(devlink), params->file_name, extack);
+       return nfp_flash_update_common(devlink_priv(devlink), params->fw, extack);
 }
 
 const struct devlink_ops nfp_devlink_ops = {
index e672614d29065c11782249c84f3388d73d03df43..742a420152b364b723e47fa96c72a472d1a97c10 100644 (file)
@@ -301,11 +301,10 @@ static int nfp_pcie_sriov_configure(struct pci_dev *pdev, int num_vfs)
                return nfp_pcie_sriov_enable(pdev, num_vfs);
 }
 
-int nfp_flash_update_common(struct nfp_pf *pf, const char *path,
+int nfp_flash_update_common(struct nfp_pf *pf, const struct firmware *fw,
                            struct netlink_ext_ack *extack)
 {
        struct device *dev = &pf->pdev->dev;
-       const struct firmware *fw;
        struct nfp_nsp *nsp;
        int err;
 
@@ -319,24 +318,12 @@ int nfp_flash_update_common(struct nfp_pf *pf, const char *path,
                return err;
        }
 
-       err = request_firmware_direct(&fw, path, dev);
-       if (err) {
-               NL_SET_ERR_MSG_MOD(extack,
-                                  "unable to read flash file from disk");
-               goto exit_close_nsp;
-       }
-
-       dev_info(dev, "Please be patient while writing flash image: %s\n",
-                path);
-
        err = nfp_nsp_write_flash(nsp, fw);
        if (err < 0)
-               goto exit_release_fw;
+               goto exit_close_nsp;
        dev_info(dev, "Finished writing flash image\n");
        err = 0;
 
-exit_release_fw:
-       release_firmware(fw);
 exit_close_nsp:
        nfp_nsp_close(nsp);
        return err;
index fa6b13a059419bdc2013ed8e7a425ffca2e68cc5..a7dede946a33f5d058104399a17393ed9eca4bff 100644 (file)
@@ -166,7 +166,7 @@ nfp_pf_map_rtsym(struct nfp_pf *pf, const char *name, const char *sym_fmt,
                 unsigned int min_size, struct nfp_cpp_area **area);
 int nfp_mbox_cmd(struct nfp_pf *pf, u32 cmd, void *in_data, u64 in_length,
                 void *out_data, u64 out_length);
-int nfp_flash_update_common(struct nfp_pf *pf, const char *path,
+int nfp_flash_update_common(struct nfp_pf *pf, const struct firmware *fw,
                            struct netlink_ext_ack *extack);
 
 enum nfp_dump_diag {
index 51d64718ed9f05178f9f15d1491399eb9b1b4f60..b41301a5b0df823b2130fdbc6b9a56febfa4134c 100644 (file)
@@ -15,7 +15,7 @@ static int ionic_dl_flash_update(struct devlink *dl,
 {
        struct ionic *ionic = devlink_priv(dl);
 
-       return ionic_firmware_update(ionic->lif, params->file_name, extack);
+       return ionic_firmware_update(ionic->lif, params->fw, extack);
 }
 
 static int ionic_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
index 5c01a9e306d8d2b039c57d704f8638851b3c2fb0..0a77e8e810c5db4c885718a017246073eee7f61a 100644 (file)
@@ -6,7 +6,7 @@
 
 #include <net/devlink.h>
 
-int ionic_firmware_update(struct ionic_lif *lif, const char *fw_name,
+int ionic_firmware_update(struct ionic_lif *lif, const struct firmware *fw,
                          struct netlink_ext_ack *extack);
 
 struct ionic *ionic_devlink_alloc(struct device *dev);
index d7bbf336c6f65c505e176e13646f035e0fef15cd..8922c316abe3a39b1aaf24e044f5955a2c7a5ad9 100644 (file)
@@ -91,7 +91,7 @@ static int ionic_fw_status_long_wait(struct ionic *ionic,
        return err;
 }
 
-int ionic_firmware_update(struct ionic_lif *lif, const char *fw_name,
+int ionic_firmware_update(struct ionic_lif *lif, const struct firmware *fw,
                          struct netlink_ext_ack *extack)
 {
        struct ionic_dev *idev = &lif->ionic->idev;
@@ -99,24 +99,17 @@ int ionic_firmware_update(struct ionic_lif *lif, const char *fw_name,
        struct ionic *ionic = lif->ionic;
        union ionic_dev_cmd_comp comp;
        u32 buf_sz, copy_sz, offset;
-       const struct firmware *fw;
        struct devlink *dl;
        int next_interval;
        int err = 0;
        u8 fw_slot;
 
-       netdev_info(netdev, "Installing firmware %s\n", fw_name);
+       netdev_info(netdev, "Installing firmware\n");
 
        dl = priv_to_devlink(ionic);
        devlink_flash_update_begin_notify(dl);
        devlink_flash_update_status_notify(dl, "Preparing to flash", NULL, 0, 0);
 
-       err = request_firmware(&fw, fw_name, ionic->dev);
-       if (err) {
-               NL_SET_ERR_MSG_MOD(extack, "Unable to find firmware file");
-               goto err_out;
-       }
-
        buf_sz = sizeof(idev->dev_cmd_regs->data);
 
        netdev_dbg(netdev,
@@ -200,7 +193,6 @@ err_out:
                devlink_flash_update_status_notify(dl, "Flash failed", NULL, 0, 0);
        else
                devlink_flash_update_status_notify(dl, "Flash done", NULL, 0, 0);
-       release_firmware(fw);
        devlink_flash_update_end_notify(dl);
        return err;
 }
index b01bb9bca5a2a96ee35e52afc4947304d84fe989..d1d125a3332211bcd927189aced413dcfa82a28c 100644 (file)
@@ -19,6 +19,7 @@
 #include <net/flow_offload.h>
 #include <uapi/linux/devlink.h>
 #include <linux/xarray.h>
+#include <linux/firmware.h>
 
 #define DEVLINK_RELOAD_STATS_ARRAY_SIZE \
        (__DEVLINK_RELOAD_LIMIT_MAX * __DEVLINK_RELOAD_ACTION_MAX)
@@ -566,15 +567,15 @@ enum devlink_param_generic_id {
 
 /**
  * struct devlink_flash_update_params - Flash Update parameters
- * @file_name: the name of the flash firmware file to update from
+ * @fw: pointer to the firmware data to update from
  * @component: the flash component to update
  *
- * With the exception of file_name, drivers must opt-in to parameters by
+ * With the exception of fw, drivers must opt-in to parameters by
  * setting the appropriate bit in the supported_flash_update_params field in
  * their devlink_ops structure.
  */
 struct devlink_flash_update_params {
-       const char *file_name;
+       const struct firmware *fw;
        const char *component;
        u32 overwrite_mask;
 };
index 4b0211590aacf1e7378091c5203fae83c75bacb8..7c5a5da8e338b60d4c3dc6fc10d868dc8b79312d 100644 (file)
@@ -3431,10 +3431,12 @@ EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify);
 static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
                                       struct genl_info *info)
 {
-       struct nlattr *nla_component, *nla_overwrite_mask;
+       struct nlattr *nla_component, *nla_overwrite_mask, *nla_file_name;
        struct devlink_flash_update_params params = {};
        struct devlink *devlink = info->user_ptr[0];
+       const char *file_name;
        u32 supported_params;
+       int ret;
 
        if (!devlink->ops->flash_update)
                return -EOPNOTSUPP;
@@ -3444,8 +3446,6 @@ static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
 
        supported_params = devlink->ops->supported_flash_update_params;
 
-       params.file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]);
-
        nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
        if (nla_component) {
                if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT)) {
@@ -3469,7 +3469,19 @@ static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
                params.overwrite_mask = sections.value & sections.selector;
        }
 
-       return devlink->ops->flash_update(devlink, &params, info->extack);
+       nla_file_name = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME];
+       file_name = nla_data(nla_file_name);
+       ret = request_firmware(&params.fw, file_name, devlink->dev);
+       if (ret) {
+               NL_SET_ERR_MSG_ATTR(info->extack, nla_file_name, "failed to locate the requested firmware file");
+               return ret;
+       }
+
+       ret = devlink->ops->flash_update(devlink, &params, info->extack);
+
+       release_firmware(params.fw);
+
+       return ret;
 }
 
 static const struct devlink_param devlink_param_generic[] = {
@@ -10227,12 +10239,16 @@ int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
                goto out;
        }
 
-       params.file_name = file_name;
+       ret = request_firmware(&params.fw, file_name, devlink->dev);
+       if (ret)
+               goto out;
 
        mutex_lock(&devlink->lock);
        ret = devlink->ops->flash_update(devlink, &params, NULL);
        mutex_unlock(&devlink->lock);
 
+       release_firmware(params.fw);
+
 out:
        rtnl_lock();
        dev_put(dev);