Commit d06d54a3 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'devlink_register-last'

Leon Romanovsky says:

====================
Move devlink_register to be last devlink command

This is second version of patch series
https://lore.kernel.org/netdev/cover.1628599239.git.leonro@nvidia.com/



The main change is addition of delayed notification logic that will
allowed us to delete devlink_params_publish API (future series will
remove it completely) and conversion of all drivers to have devlink_register
being last commend.

The series itself is pretty straightforward, except liquidio driver
which performs initializations in various workqueues without proper
locks. That driver doesn't hole device_lock and it is clearly broken
for any parallel driver core flows (modprobe + devlink + PCI reset will
100% crash it).

In order to annotate devlink_register() will lockdep of holding
device_lock, I added workaround in this driver.

Thanks

----------------------
From previous cover letter:
Hi Dave and Jakub,

This series prepares code to remove devlink_reload_enable/_disable API
and in order to do, we move all devlink_register() calls to be right
before devlink_reload_enable().

The best place for such a call should be right before exiting from
the probe().

This is done because devlink_register() opens devlink netlink to the
users and gives them a venue to issue commands before initialization
is finished.

1. Some drivers were aware of such "functionality" and tried to protect
themselves with extra locks, state machines and devlink_reload_enable().
Let's assume that it worked for them, but I'm personally skeptical about
it.

2. Some drivers copied that pattern, but without locks and state
machines. That protected them from reload flows, but not from any _set_
routines.

3. And all other drivers simply didn't understand the implications of early
devlink_register() and can be seen as "broken".
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ef5d6356 bd936bd5
Loading
Loading
Loading
Loading
+6 −9
Original line number Diff line number Diff line
@@ -745,15 +745,11 @@ static int bnxt_dl_params_register(struct bnxt *bp)

	rc = devlink_params_register(bp->dl, bnxt_dl_params,
				     ARRAY_SIZE(bnxt_dl_params));
	if (rc) {
	if (rc)
		netdev_warn(bp->dev, "devlink_params_register failed. rc=%d\n",
			    rc);
	return rc;
}
	devlink_params_publish(bp->dl);

	return 0;
}

static void bnxt_dl_params_unregister(struct bnxt *bp)
{
@@ -792,9 +788,8 @@ int bnxt_dl_register(struct bnxt *bp)
	    bp->hwrm_spec_code > 0x10803)
		bp->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;

	devlink_register(dl);
	if (!BNXT_PF(bp))
		return 0;
		goto out;

	attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
	attrs.phys.port_number = bp->pf.port_id;
@@ -811,6 +806,8 @@ int bnxt_dl_register(struct bnxt *bp)
	if (rc)
		goto err_dl_port_unreg;

out:
	devlink_register(dl);
	return 0;

err_dl_port_unreg:
@@ -824,10 +821,10 @@ void bnxt_dl_unregister(struct bnxt *bp)
{
	struct devlink *dl = bp->dl;

	devlink_unregister(dl);
	if (BNXT_PF(bp)) {
		bnxt_dl_params_unregister(bp);
		devlink_port_unregister(&bp->dl_port);
	}
	devlink_unregister(dl);
	devlink_free(dl);
}
+12 −7
Original line number Diff line number Diff line
@@ -1279,6 +1279,14 @@ static int liquidio_stop_nic_module(struct octeon_device *oct)
	struct lio *lio;

	dev_dbg(&oct->pci_dev->dev, "Stopping network interfaces\n");
	device_lock(&oct->pci_dev->dev);
	if (oct->devlink) {
		devlink_unregister(oct->devlink);
		devlink_free(oct->devlink);
		oct->devlink = NULL;
	}
	device_unlock(&oct->pci_dev->dev);

	if (!oct->ifcount) {
		dev_err(&oct->pci_dev->dev, "Init for Octeon was not completed\n");
		return 1;
@@ -1300,12 +1308,6 @@ static int liquidio_stop_nic_module(struct octeon_device *oct)
	for (i = 0; i < oct->ifcount; i++)
		liquidio_destroy_nic_device(oct, i);

	if (oct->devlink) {
		devlink_unregister(oct->devlink);
		devlink_free(oct->devlink);
		oct->devlink = NULL;
	}

	dev_dbg(&oct->pci_dev->dev, "Network interfaces stopped\n");
	return 0;
}
@@ -3749,10 +3751,12 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
		}
	}

	device_lock(&octeon_dev->pci_dev->dev);
	devlink = devlink_alloc(&liquidio_devlink_ops,
				sizeof(struct lio_devlink_priv),
				&octeon_dev->pci_dev->dev);
	if (!devlink) {
		device_unlock(&octeon_dev->pci_dev->dev);
		dev_err(&octeon_dev->pci_dev->dev, "devlink alloc failed\n");
		goto setup_nic_dev_free;
	}
@@ -3760,9 +3764,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)
	lio_devlink = devlink_priv(devlink);
	lio_devlink->oct = octeon_dev;

	devlink_register(devlink);
	octeon_dev->devlink = devlink;
	octeon_dev->eswitch_mode = DEVLINK_ESWITCH_MODE_LEGACY;
	devlink_register(devlink);
	device_unlock(&octeon_dev->pci_dev->dev);

	return 0;

+11 −3
Original line number Diff line number Diff line
@@ -189,7 +189,7 @@ static const struct devlink_ops dpaa2_eth_devlink_ops = {
	.trap_group_action_set = dpaa2_eth_dl_trap_group_action_set,
};

int dpaa2_eth_dl_register(struct dpaa2_eth_priv *priv)
int dpaa2_eth_dl_alloc(struct dpaa2_eth_priv *priv)
{
	struct net_device *net_dev = priv->net_dev;
	struct device *dev = net_dev->dev.parent;
@@ -203,15 +203,23 @@ int dpaa2_eth_dl_register(struct dpaa2_eth_priv *priv)
	}
	dl_priv = devlink_priv(priv->devlink);
	dl_priv->dpaa2_priv = priv;
	return 0;
}

void dpaa2_eth_dl_free(struct dpaa2_eth_priv *priv)
{
	devlink_free(priv->devlink);
}


void dpaa2_eth_dl_register(struct dpaa2_eth_priv *priv)
{
	devlink_register(priv->devlink);
	return 0;
}

void dpaa2_eth_dl_unregister(struct dpaa2_eth_priv *priv)
{
	devlink_unregister(priv->devlink);
	devlink_free(priv->devlink);
}

int dpaa2_eth_dl_port_add(struct dpaa2_eth_priv *priv)
+6 −3
Original line number Diff line number Diff line
@@ -4431,7 +4431,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
	if (err)
		goto err_connect_mac;

	err = dpaa2_eth_dl_register(priv);
	err = dpaa2_eth_dl_alloc(priv);
	if (err)
		goto err_dl_register;

@@ -4453,6 +4453,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
	dpaa2_dbg_add(priv);
#endif

	dpaa2_eth_dl_register(priv);
	dev_info(dev, "Probed interface %s\n", net_dev->name);
	return 0;

@@ -4461,7 +4462,7 @@ static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
err_dl_port_add:
	dpaa2_eth_dl_traps_unregister(priv);
err_dl_trap_register:
	dpaa2_eth_dl_unregister(priv);
	dpaa2_eth_dl_free(priv);
err_dl_register:
	dpaa2_eth_disconnect_mac(priv);
err_connect_mac:
@@ -4508,6 +4509,8 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
	net_dev = dev_get_drvdata(dev);
	priv = netdev_priv(net_dev);

	dpaa2_eth_dl_unregister(priv);

#ifdef CONFIG_DEBUG_FS
	dpaa2_dbg_remove(priv);
#endif
@@ -4519,7 +4522,7 @@ static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)

	dpaa2_eth_dl_port_del(priv);
	dpaa2_eth_dl_traps_unregister(priv);
	dpaa2_eth_dl_unregister(priv);
	dpaa2_eth_dl_free(priv);

	if (priv->do_link_poll)
		kthread_stop(priv->poll_thread);
+4 −1
Original line number Diff line number Diff line
@@ -725,7 +725,10 @@ void dpaa2_eth_set_rx_taildrop(struct dpaa2_eth_priv *priv,

extern const struct dcbnl_rtnl_ops dpaa2_eth_dcbnl_ops;

int dpaa2_eth_dl_register(struct dpaa2_eth_priv *priv);
int dpaa2_eth_dl_alloc(struct dpaa2_eth_priv *priv);
void dpaa2_eth_dl_free(struct dpaa2_eth_priv *priv);

void dpaa2_eth_dl_register(struct dpaa2_eth_priv *priv);
void dpaa2_eth_dl_unregister(struct dpaa2_eth_priv *priv);

int dpaa2_eth_dl_port_add(struct dpaa2_eth_priv *priv);
Loading