@@ -602,8 +602,11 @@ static int dpaa2_switch_port_link_state_update(struct net_device *netdev)
602
602
603
603
/* When we manage the MAC/PHY using phylink there is no need
604
604
* to manually update the netif_carrier.
605
+ * We can avoid locking because we are called from the "link changed"
606
+ * IRQ handler, which is the same as the "endpoint changed" IRQ handler
607
+ * (the writer to port_priv->mac), so we cannot race with it.
605
608
*/
606
- if (dpaa2_switch_port_is_type_phy (port_priv ))
609
+ if (dpaa2_mac_is_type_phy (port_priv -> mac ))
607
610
return 0 ;
608
611
609
612
/* Interrupts are received even though no one issued an 'ifconfig up'
@@ -683,6 +686,8 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
683
686
struct ethsw_core * ethsw = port_priv -> ethsw_data ;
684
687
int err ;
685
688
689
+ mutex_lock (& port_priv -> mac_lock );
690
+
686
691
if (!dpaa2_switch_port_is_type_phy (port_priv )) {
687
692
/* Explicitly set carrier off, otherwise
688
693
* netif_carrier_ok() will return true and cause 'ip link show'
@@ -696,6 +701,7 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
696
701
port_priv -> ethsw_data -> dpsw_handle ,
697
702
port_priv -> idx );
698
703
if (err ) {
704
+ mutex_unlock (& port_priv -> mac_lock );
699
705
netdev_err (netdev , "dpsw_if_enable err %d\n" , err );
700
706
return err ;
701
707
}
@@ -705,6 +711,8 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
705
711
if (dpaa2_switch_port_is_type_phy (port_priv ))
706
712
dpaa2_mac_start (port_priv -> mac );
707
713
714
+ mutex_unlock (& port_priv -> mac_lock );
715
+
708
716
return 0 ;
709
717
}
710
718
@@ -714,13 +722,17 @@ static int dpaa2_switch_port_stop(struct net_device *netdev)
714
722
struct ethsw_core * ethsw = port_priv -> ethsw_data ;
715
723
int err ;
716
724
725
+ mutex_lock (& port_priv -> mac_lock );
726
+
717
727
if (dpaa2_switch_port_is_type_phy (port_priv )) {
718
728
dpaa2_mac_stop (port_priv -> mac );
719
729
} else {
720
730
netif_tx_stop_all_queues (netdev );
721
731
netif_carrier_off (netdev );
722
732
}
723
733
734
+ mutex_unlock (& port_priv -> mac_lock );
735
+
724
736
err = dpsw_if_disable (port_priv -> ethsw_data -> mc_io , 0 ,
725
737
port_priv -> ethsw_data -> dpsw_handle ,
726
738
port_priv -> idx );
@@ -1460,7 +1472,9 @@ static int dpaa2_switch_port_connect_mac(struct ethsw_port_priv *port_priv)
1460
1472
}
1461
1473
}
1462
1474
1475
+ mutex_lock (& port_priv -> mac_lock );
1463
1476
port_priv -> mac = mac ;
1477
+ mutex_unlock (& port_priv -> mac_lock );
1464
1478
1465
1479
return 0 ;
1466
1480
@@ -1473,9 +1487,12 @@ static int dpaa2_switch_port_connect_mac(struct ethsw_port_priv *port_priv)
1473
1487
1474
1488
static void dpaa2_switch_port_disconnect_mac (struct ethsw_port_priv * port_priv )
1475
1489
{
1476
- struct dpaa2_mac * mac = port_priv -> mac ;
1490
+ struct dpaa2_mac * mac ;
1477
1491
1492
+ mutex_lock (& port_priv -> mac_lock );
1493
+ mac = port_priv -> mac ;
1478
1494
port_priv -> mac = NULL ;
1495
+ mutex_unlock (& port_priv -> mac_lock );
1479
1496
1480
1497
if (!mac )
1481
1498
return ;
@@ -1494,6 +1511,7 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
1494
1511
struct ethsw_port_priv * port_priv ;
1495
1512
u32 status = ~0 ;
1496
1513
int err , if_id ;
1514
+ bool had_mac ;
1497
1515
1498
1516
err = dpsw_get_irq_status (ethsw -> mc_io , 0 , ethsw -> dpsw_handle ,
1499
1517
DPSW_IRQ_INDEX_IF , & status );
@@ -1512,7 +1530,12 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
1512
1530
1513
1531
if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED ) {
1514
1532
rtnl_lock ();
1515
- if (dpaa2_switch_port_has_mac (port_priv ))
1533
+ /* We can avoid locking because the "endpoint changed" IRQ
1534
+ * handler is the only one who changes priv->mac at runtime,
1535
+ * so we are not racing with anyone.
1536
+ */
1537
+ had_mac = !!port_priv -> mac ;
1538
+ if (had_mac )
1516
1539
dpaa2_switch_port_disconnect_mac (port_priv );
1517
1540
else
1518
1541
dpaa2_switch_port_connect_mac (port_priv );
@@ -3255,6 +3278,8 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
3255
3278
port_priv -> netdev = port_netdev ;
3256
3279
port_priv -> ethsw_data = ethsw ;
3257
3280
3281
+ mutex_init (& port_priv -> mac_lock );
3282
+
3258
3283
port_priv -> idx = port_idx ;
3259
3284
port_priv -> stp_state = BR_STATE_FORWARDING ;
3260
3285
0 commit comments