Commit 5c5696f3 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by David S. Miller
Browse files

nfp: devlink: allow flashing the device via devlink



Devlink now allows updating device flash.  Implement this
callback.

Compared to ethtool update we no longer have to release
the networking locks - devlink doesn't take them.

Signed-off-by: default avatarJakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4eceba17
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -330,6 +330,15 @@ err_close_nsp:
	return err;
}

static int
nfp_devlink_flash_update(struct devlink *devlink, const char *path,
			 const char *component, struct netlink_ext_ack *extack)
{
	if (component)
		return -EOPNOTSUPP;
	return nfp_flash_update_common(devlink_priv(devlink), path, extack);
}

const struct devlink_ops nfp_devlink_ops = {
	.port_split		= nfp_devlink_port_split,
	.port_unsplit		= nfp_devlink_port_unsplit,
@@ -338,6 +347,7 @@ const struct devlink_ops nfp_devlink_ops = {
	.eswitch_mode_get	= nfp_devlink_eswitch_mode_get,
	.eswitch_mode_set	= nfp_devlink_eswitch_mode_set,
	.info_get		= nfp_devlink_info_get,
	.flash_update		= nfp_devlink_flash_update,
};

int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port)
+41 −0
Original line number Diff line number Diff line
@@ -300,6 +300,47 @@ 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,
			    struct netlink_ext_ack *extack)
{
	struct device *dev = &pf->pdev->dev;
	const struct firmware *fw;
	struct nfp_nsp *nsp;
	int err;

	nsp = nfp_nsp_open(pf->cpp);
	if (IS_ERR(nsp)) {
		err = PTR_ERR(nsp);
		if (extack)
			NL_SET_ERR_MSG_MOD(extack, "can't access NSP");
		else
			dev_err(dev, "Failed to access the NSP: %d\n", err);
		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;
	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;
}

static const struct firmware *
nfp_net_fw_request(struct pci_dev *pdev, struct nfp_pf *pf, const char *name)
{
+2 −0
Original line number Diff line number Diff line
@@ -164,6 +164,8 @@ 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,
			    struct netlink_ext_ack *extack);

enum nfp_dump_diag {
	NFP_DUMP_NSP_DIAG = 0,
+3 −32
Original line number Diff line number Diff line
@@ -1237,11 +1237,8 @@ static int nfp_net_set_channels(struct net_device *netdev,
static int
nfp_net_flash_device(struct net_device *netdev, struct ethtool_flash *flash)
{
	const struct firmware *fw;
	struct nfp_app *app;
	struct nfp_nsp *nsp;
	struct device *dev;
	int err;
	int ret;

	if (flash->region != ETHTOOL_FLASH_ALL_REGIONS)
		return -EOPNOTSUPP;
@@ -1250,39 +1247,13 @@ nfp_net_flash_device(struct net_device *netdev, struct ethtool_flash *flash)
	if (!app)
		return -EOPNOTSUPP;

	dev = &app->pdev->dev;

	nsp = nfp_nsp_open(app->cpp);
	if (IS_ERR(nsp)) {
		err = PTR_ERR(nsp);
		dev_err(dev, "Failed to access the NSP: %d\n", err);
		return err;
	}

	err = request_firmware_direct(&fw, flash->data, dev);
	if (err)
		goto exit_close_nsp;

	dev_info(dev, "Please be patient while writing flash image: %s\n",
		 flash->data);
	dev_hold(netdev);
	rtnl_unlock();

	err = nfp_nsp_write_flash(nsp, fw);
	if (err < 0) {
		dev_err(dev, "Flash write failed: %d\n", err);
		goto exit_rtnl_lock;
	}
	dev_info(dev, "Finished writing flash image\n");

exit_rtnl_lock:
	ret = nfp_flash_update_common(app->pf, flash->data, NULL);
	rtnl_lock();
	dev_put(netdev);
	release_firmware(fw);

exit_close_nsp:
	nfp_nsp_close(nsp);
	return err;
	return ret;
}

static const struct ethtool_ops nfp_net_ethtool_ops = {