Skip to content

Commit

Permalink
Merge branch 'devlink_register-last'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Sep 27, 2021
2 parents ef5d635 + bd936bd commit d06d54a
Show file tree
Hide file tree
Showing 30 changed files with 202 additions and 177 deletions.
15 changes: 6 additions & 9 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -745,14 +745,10 @@ 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;
return rc;
}

static void bnxt_dl_params_unregister(struct bnxt *bp)
Expand Down Expand Up @@ -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;
Expand All @@ -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:
Expand All @@ -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);
}
19 changes: 12 additions & 7 deletions drivers/net/ethernet/cavium/liquidio/lio_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -3749,20 +3751,23 @@ 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;
}

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;

Expand Down
14 changes: 11 additions & 3 deletions drivers/net/ethernet/freescale/dpaa2/dpaa2-eth-devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down
9 changes: 6 additions & 3 deletions drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;

Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
5 changes: 4 additions & 1 deletion drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 2 additions & 5 deletions drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -754,11 +754,9 @@ static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
return err;
}

hinic_devlink_register(hwdev->devlink_dev);
err = hinic_func_to_func_init(hwdev);
if (err) {
dev_err(&hwif->pdev->dev, "Failed to init mailbox\n");
hinic_devlink_unregister(hwdev->devlink_dev);
hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
return err;
}
Expand All @@ -781,7 +779,7 @@ static int init_pfhwdev(struct hinic_pfhwdev *pfhwdev)
}

hinic_set_pf_action(hwif, HINIC_PF_MGMT_ACTIVE);

hinic_devlink_register(hwdev->devlink_dev);
return 0;
}

Expand All @@ -793,6 +791,7 @@ static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
{
struct hinic_hwdev *hwdev = &pfhwdev->hwdev;

hinic_devlink_unregister(hwdev->devlink_dev);
hinic_set_pf_action(hwdev->hwif, HINIC_PF_MGMT_INIT);

if (!HINIC_IS_VF(hwdev->hwif)) {
Expand All @@ -810,8 +809,6 @@ static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)

hinic_func_to_func_free(hwdev);

hinic_devlink_unregister(hwdev->devlink_dev);

hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
}

Expand Down
6 changes: 2 additions & 4 deletions drivers/net/ethernet/intel/ice/ice_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -4258,8 +4258,6 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)

pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);

ice_devlink_register(pf);

#ifndef CONFIG_DYNAMIC_DEBUG
if (debug < -1)
hw->debug_mask = debug;
Expand Down Expand Up @@ -4493,6 +4491,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
dev_warn(dev, "RDMA is not supported on this device\n");
}

ice_devlink_register(pf);
return 0;

err_init_aux_unroll:
Expand All @@ -4516,7 +4515,6 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
ice_devlink_destroy_regions(pf);
ice_deinit_hw(hw);
err_exit_unroll:
ice_devlink_unregister(pf);
pci_disable_pcie_error_reporting(pdev);
pci_disable_device(pdev);
return err;
Expand Down Expand Up @@ -4593,6 +4591,7 @@ static void ice_remove(struct pci_dev *pdev)
struct ice_pf *pf = pci_get_drvdata(pdev);
int i;

ice_devlink_unregister(pf);
for (i = 0; i < ICE_MAX_RESET_WAIT; i++) {
if (!ice_is_reset_in_progress(pf->state))
break;
Expand Down Expand Up @@ -4629,7 +4628,6 @@ static void ice_remove(struct pci_dev *pdev)
ice_deinit_pf(pf);
ice_devlink_destroy_regions(pf);
ice_deinit_hw(&pf->hw);
ice_devlink_unregister(pf);

/* Issue a PFR as part of the prescribed driver unload flow. Do not
* do it via ice_schedule_reset() since there is no need to rebuild
Expand Down
10 changes: 2 additions & 8 deletions drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1510,7 +1510,6 @@ int rvu_register_dl(struct rvu *rvu)
return -ENOMEM;
}

devlink_register(dl);
rvu_dl = devlink_priv(dl);
rvu_dl->dl = dl;
rvu_dl->rvu = rvu;
Expand All @@ -1531,13 +1530,11 @@ int rvu_register_dl(struct rvu *rvu)
goto err_dl_health;
}

devlink_params_publish(dl);

devlink_register(dl);
return 0;

err_dl_health:
rvu_health_reporters_destroy(rvu);
devlink_unregister(dl);
devlink_free(dl);
return err;
}
Expand All @@ -1547,12 +1544,9 @@ void rvu_unregister_dl(struct rvu *rvu)
struct rvu_devlink *rvu_dl = rvu->rvu_dl;
struct devlink *dl = rvu_dl->dl;

if (!dl)
return;

devlink_unregister(dl);
devlink_params_unregister(dl, rvu_af_dl_params,
ARRAY_SIZE(rvu_af_dl_params));
rvu_health_reporters_destroy(rvu);
devlink_unregister(dl);
devlink_free(dl);
}
15 changes: 3 additions & 12 deletions drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ int otx2_register_dl(struct otx2_nic *pfvf)
return -ENOMEM;
}

devlink_register(dl);
otx2_dl = devlink_priv(dl);
otx2_dl->dl = dl;
otx2_dl->pfvf = pfvf;
Expand All @@ -122,29 +121,21 @@ int otx2_register_dl(struct otx2_nic *pfvf)
goto err_dl;
}

devlink_params_publish(dl);

devlink_register(dl);
return 0;

err_dl:
devlink_unregister(dl);
devlink_free(dl);
return err;
}

void otx2_unregister_dl(struct otx2_nic *pfvf)
{
struct otx2_devlink *otx2_dl = pfvf->dl;
struct devlink *dl;

if (!otx2_dl || !otx2_dl->dl)
return;

dl = otx2_dl->dl;
struct devlink *dl = otx2_dl->dl;

devlink_unregister(dl);
devlink_params_unregister(dl, otx2_dl_params,
ARRAY_SIZE(otx2_dl_params));

devlink_unregister(dl);
devlink_free(dl);
}
Loading

0 comments on commit d06d54a

Please sign in to comment.