Skip to content

Commit 7576bd9

Browse files
committed
Merge branch 'net-cpsw-execute-ndo_set_rx_mode-callback-in-a-work-queue'
Kevin Hao says: ==================== net: cpsw: Execute ndo_set_rx_mode callback in a work queue These two patches resolve an RTNL assertion call trace issue in both the legacy and new cpsw drivers. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 279fe48 + 0b8c878 commit 7576bd9

3 files changed

Lines changed: 65 additions & 11 deletions

File tree

drivers/net/ethernet/ti/cpsw.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -305,20 +305,27 @@ static int cpsw_purge_all_mc(struct net_device *ndev, const u8 *addr, int num)
305305
return 0;
306306
}
307307

308-
static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
308+
static void cpsw_ndo_set_rx_mode_work(struct work_struct *work)
309309
{
310-
struct cpsw_priv *priv = netdev_priv(ndev);
310+
struct cpsw_priv *priv = container_of(work, struct cpsw_priv, rx_mode_work);
311311
struct cpsw_common *cpsw = priv->cpsw;
312+
struct net_device *ndev = priv->ndev;
312313
int slave_port = -1;
313314

315+
rtnl_lock();
316+
if (!netif_running(ndev))
317+
goto unlock_rtnl;
318+
319+
netif_addr_lock_bh(ndev);
320+
314321
if (cpsw->data.dual_emac)
315322
slave_port = priv->emac_port + 1;
316323

317324
if (ndev->flags & IFF_PROMISC) {
318325
/* Enable promiscuous mode */
319326
cpsw_set_promiscious(ndev, true);
320327
cpsw_ale_set_allmulti(cpsw->ale, IFF_ALLMULTI, slave_port);
321-
return;
328+
goto unlock_addr;
322329
} else {
323330
/* Disable promiscuous mode */
324331
cpsw_set_promiscious(ndev, false);
@@ -331,6 +338,18 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
331338
/* add/remove mcast address either for real netdev or for vlan */
332339
__hw_addr_ref_sync_dev(&ndev->mc, ndev, cpsw_add_mc_addr,
333340
cpsw_del_mc_addr);
341+
342+
unlock_addr:
343+
netif_addr_unlock_bh(ndev);
344+
unlock_rtnl:
345+
rtnl_unlock();
346+
}
347+
348+
static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
349+
{
350+
struct cpsw_priv *priv = netdev_priv(ndev);
351+
352+
schedule_work(&priv->rx_mode_work);
334353
}
335354

336355
static unsigned int cpsw_rxbuf_total_len(unsigned int len)
@@ -1472,6 +1491,7 @@ static int cpsw_probe_dual_emac(struct cpsw_priv *priv)
14721491
priv_sl2->ndev = ndev;
14731492
priv_sl2->dev = &ndev->dev;
14741493
priv_sl2->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
1494+
INIT_WORK(&priv_sl2->rx_mode_work, cpsw_ndo_set_rx_mode_work);
14751495

14761496
if (is_valid_ether_addr(data->slave_data[1].mac_addr)) {
14771497
memcpy(priv_sl2->mac_addr, data->slave_data[1].mac_addr,
@@ -1653,6 +1673,7 @@ static int cpsw_probe(struct platform_device *pdev)
16531673
priv->dev = dev;
16541674
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
16551675
priv->emac_port = 0;
1676+
INIT_WORK(&priv->rx_mode_work, cpsw_ndo_set_rx_mode_work);
16561677

16571678
if (is_valid_ether_addr(data->slave_data[0].mac_addr)) {
16581679
memcpy(priv->mac_addr, data->slave_data[0].mac_addr, ETH_ALEN);
@@ -1758,6 +1779,8 @@ static int cpsw_probe(struct platform_device *pdev)
17581779
static void cpsw_remove(struct platform_device *pdev)
17591780
{
17601781
struct cpsw_common *cpsw = platform_get_drvdata(pdev);
1782+
struct net_device *ndev;
1783+
struct cpsw_priv *priv;
17611784
int i, ret;
17621785

17631786
ret = pm_runtime_resume_and_get(&pdev->dev);
@@ -1770,9 +1793,15 @@ static void cpsw_remove(struct platform_device *pdev)
17701793
return;
17711794
}
17721795

1773-
for (i = 0; i < cpsw->data.slaves; i++)
1774-
if (cpsw->slaves[i].ndev)
1775-
unregister_netdev(cpsw->slaves[i].ndev);
1796+
for (i = 0; i < cpsw->data.slaves; i++) {
1797+
ndev = cpsw->slaves[i].ndev;
1798+
if (!ndev)
1799+
continue;
1800+
1801+
priv = netdev_priv(ndev);
1802+
unregister_netdev(ndev);
1803+
disable_work_sync(&priv->rx_mode_work);
1804+
}
17761805

17771806
cpts_release(cpsw->cpts);
17781807
cpdma_ctlr_destroy(cpsw->dma);

drivers/net/ethernet/ti/cpsw_new.c

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,16 +248,22 @@ static int cpsw_purge_all_mc(struct net_device *ndev, const u8 *addr, int num)
248248
return 0;
249249
}
250250

251-
static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
251+
static void cpsw_ndo_set_rx_mode_work(struct work_struct *work)
252252
{
253-
struct cpsw_priv *priv = netdev_priv(ndev);
253+
struct cpsw_priv *priv = container_of(work, struct cpsw_priv, rx_mode_work);
254254
struct cpsw_common *cpsw = priv->cpsw;
255+
struct net_device *ndev = priv->ndev;
255256

257+
rtnl_lock();
258+
if (!netif_running(ndev))
259+
goto unlock_rtnl;
260+
261+
netif_addr_lock_bh(ndev);
256262
if (ndev->flags & IFF_PROMISC) {
257263
/* Enable promiscuous mode */
258264
cpsw_set_promiscious(ndev, true);
259265
cpsw_ale_set_allmulti(cpsw->ale, IFF_ALLMULTI, priv->emac_port);
260-
return;
266+
goto unlock_addr;
261267
}
262268

263269
/* Disable promiscuous mode */
@@ -270,6 +276,18 @@ static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
270276
/* add/remove mcast address either for real netdev or for vlan */
271277
__hw_addr_ref_sync_dev(&ndev->mc, ndev, cpsw_add_mc_addr,
272278
cpsw_del_mc_addr);
279+
280+
unlock_addr:
281+
netif_addr_unlock_bh(ndev);
282+
unlock_rtnl:
283+
rtnl_unlock();
284+
}
285+
286+
static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
287+
{
288+
struct cpsw_priv *priv = netdev_priv(ndev);
289+
290+
schedule_work(&priv->rx_mode_work);
273291
}
274292

275293
static unsigned int cpsw_rxbuf_total_len(unsigned int len)
@@ -1398,6 +1416,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
13981416
priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
13991417
priv->emac_port = i + 1;
14001418
priv->tx_packet_min = CPSW_MIN_PACKET_SIZE;
1419+
INIT_WORK(&priv->rx_mode_work, cpsw_ndo_set_rx_mode_work);
14011420

14021421
if (is_valid_ether_addr(slave_data->mac_addr)) {
14031422
ether_addr_copy(priv->mac_addr, slave_data->mac_addr);
@@ -1447,13 +1466,18 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
14471466

14481467
static void cpsw_unregister_ports(struct cpsw_common *cpsw)
14491468
{
1469+
struct net_device *ndev;
1470+
struct cpsw_priv *priv;
14501471
int i = 0;
14511472

14521473
for (i = 0; i < cpsw->data.slaves; i++) {
1453-
if (!cpsw->slaves[i].ndev)
1474+
ndev = cpsw->slaves[i].ndev;
1475+
if (!ndev)
14541476
continue;
14551477

1456-
unregister_netdev(cpsw->slaves[i].ndev);
1478+
priv = netdev_priv(ndev);
1479+
unregister_netdev(ndev);
1480+
disable_work_sync(&priv->rx_mode_work);
14571481
}
14581482
}
14591483

drivers/net/ethernet/ti/cpsw_priv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ struct cpsw_priv {
391391
u32 tx_packet_min;
392392
struct cpsw_ale_ratelimit ale_bc_ratelimit;
393393
struct cpsw_ale_ratelimit ale_mc_ratelimit;
394+
struct work_struct rx_mode_work;
394395
};
395396

396397
#define ndev_to_cpsw(ndev) (((struct cpsw_priv *)netdev_priv(ndev))->cpsw)

0 commit comments

Comments
 (0)