Skip to content

Commit e20aa07

Browse files
Yinjun Zhangkuba-moo
authored andcommitted
nfp: fix schedule in atomic context when sync mc address
The callback `.ndo_set_rx_mode` is called in atomic context, sleep is not allowed in the implementation. Now use workqueue mechanism to avoid this issue. Fixes: de62486 ("nfp: add support for multicast filter") Signed-off-by: Yinjun Zhang <yinjun.zhang@corigine.com> Reviewed-by: Louis Peens <louis.peens@corigine.com> Signed-off-by: Simon Horman <simon.horman@corigine.com> Link: https://lore.kernel.org/r/20221220152100.1042774-1-simon.horman@corigine.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 3d8f2c4 commit e20aa07

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

drivers/net/ethernet/netronome/nfp/nfp_net.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,9 @@ struct nfp_net_dp {
617617
* @vnic_no_name: For non-port PF vNIC make ndo_get_phys_port_name return
618618
* -EOPNOTSUPP to keep backwards compatibility (set by app)
619619
* @port: Pointer to nfp_port structure if vNIC is a port
620+
* @mc_lock: Protect mc_addrs list
621+
* @mc_addrs: List of mc addrs to add/del to HW
622+
* @mc_work: Work to update mc addrs
620623
* @app_priv: APP private data for this vNIC
621624
*/
622625
struct nfp_net {
@@ -718,6 +721,10 @@ struct nfp_net {
718721

719722
struct nfp_port *port;
720723

724+
spinlock_t mc_lock;
725+
struct list_head mc_addrs;
726+
struct work_struct mc_work;
727+
721728
void *app_priv;
722729
};
723730

drivers/net/ethernet/netronome/nfp/nfp_net_common.c

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,9 +1334,14 @@ int nfp_ctrl_open(struct nfp_net *nn)
13341334
return err;
13351335
}
13361336

1337-
static int nfp_net_mc_cfg(struct net_device *netdev, const unsigned char *addr, const u32 cmd)
1337+
struct nfp_mc_addr_entry {
1338+
u8 addr[ETH_ALEN];
1339+
u32 cmd;
1340+
struct list_head list;
1341+
};
1342+
1343+
static int nfp_net_mc_cfg(struct nfp_net *nn, const unsigned char *addr, const u32 cmd)
13381344
{
1339-
struct nfp_net *nn = netdev_priv(netdev);
13401345
int ret;
13411346

13421347
ret = nfp_net_mbox_lock(nn, NFP_NET_CFG_MULTICAST_SZ);
@@ -1351,6 +1356,25 @@ static int nfp_net_mc_cfg(struct net_device *netdev, const unsigned char *addr,
13511356
return nfp_net_mbox_reconfig_and_unlock(nn, cmd);
13521357
}
13531358

1359+
static int nfp_net_mc_prep(struct nfp_net *nn, const unsigned char *addr, const u32 cmd)
1360+
{
1361+
struct nfp_mc_addr_entry *entry;
1362+
1363+
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
1364+
if (!entry)
1365+
return -ENOMEM;
1366+
1367+
ether_addr_copy(entry->addr, addr);
1368+
entry->cmd = cmd;
1369+
spin_lock_bh(&nn->mc_lock);
1370+
list_add_tail(&entry->list, &nn->mc_addrs);
1371+
spin_unlock_bh(&nn->mc_lock);
1372+
1373+
schedule_work(&nn->mc_work);
1374+
1375+
return 0;
1376+
}
1377+
13541378
static int nfp_net_mc_sync(struct net_device *netdev, const unsigned char *addr)
13551379
{
13561380
struct nfp_net *nn = netdev_priv(netdev);
@@ -1361,12 +1385,35 @@ static int nfp_net_mc_sync(struct net_device *netdev, const unsigned char *addr)
13611385
return -EINVAL;
13621386
}
13631387

1364-
return nfp_net_mc_cfg(netdev, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_ADD);
1388+
return nfp_net_mc_prep(nn, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_ADD);
13651389
}
13661390

13671391
static int nfp_net_mc_unsync(struct net_device *netdev, const unsigned char *addr)
13681392
{
1369-
return nfp_net_mc_cfg(netdev, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_DEL);
1393+
struct nfp_net *nn = netdev_priv(netdev);
1394+
1395+
return nfp_net_mc_prep(nn, addr, NFP_NET_CFG_MBOX_CMD_MULTICAST_DEL);
1396+
}
1397+
1398+
static void nfp_net_mc_addr_config(struct work_struct *work)
1399+
{
1400+
struct nfp_net *nn = container_of(work, struct nfp_net, mc_work);
1401+
struct nfp_mc_addr_entry *entry, *tmp;
1402+
struct list_head tmp_list;
1403+
1404+
INIT_LIST_HEAD(&tmp_list);
1405+
1406+
spin_lock_bh(&nn->mc_lock);
1407+
list_splice_init(&nn->mc_addrs, &tmp_list);
1408+
spin_unlock_bh(&nn->mc_lock);
1409+
1410+
list_for_each_entry_safe(entry, tmp, &tmp_list, list) {
1411+
if (nfp_net_mc_cfg(nn, entry->addr, entry->cmd))
1412+
nn_err(nn, "Config mc address to HW failed.\n");
1413+
1414+
list_del(&entry->list);
1415+
kfree(entry);
1416+
}
13701417
}
13711418

13721419
static void nfp_net_set_rx_mode(struct net_device *netdev)
@@ -2633,6 +2680,11 @@ int nfp_net_init(struct nfp_net *nn)
26332680

26342681
if (!nn->dp.netdev)
26352682
return 0;
2683+
2684+
spin_lock_init(&nn->mc_lock);
2685+
INIT_LIST_HEAD(&nn->mc_addrs);
2686+
INIT_WORK(&nn->mc_work, nfp_net_mc_addr_config);
2687+
26362688
return register_netdev(nn->dp.netdev);
26372689

26382690
err_clean_mbox:
@@ -2652,5 +2704,6 @@ void nfp_net_clean(struct nfp_net *nn)
26522704
unregister_netdev(nn->dp.netdev);
26532705
nfp_net_ipsec_clean(nn);
26542706
nfp_ccm_mbox_clean(nn);
2707+
flush_work(&nn->mc_work);
26552708
nfp_net_reconfig_wait_posted(nn);
26562709
}

0 commit comments

Comments
 (0)