Skip to content

Commit 3c7f44f

Browse files
vladimirolteanPaolo Abeni
authored andcommitted
net: dpaa2-switch: serialize changes to priv->mac with a mutex
The dpaa2-switch driver uses a DPMAC in the same way as the dpaa2-eth driver, so we need to duplicate the locking solution established by the previous change to the switch driver as well. Signed-off-by: Vladimir Oltean <[email protected]> Reviewed-by: Ioana Ciornei <[email protected]> Tested-by: Ioana Ciornei <[email protected]> Signed-off-by: Paolo Abeni <[email protected]>
1 parent 2291982 commit 3c7f44f

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,18 @@ dpaa2_switch_get_link_ksettings(struct net_device *netdev,
6060
{
6161
struct ethsw_port_priv *port_priv = netdev_priv(netdev);
6262
struct dpsw_link_state state = {0};
63-
int err = 0;
63+
int err;
64+
65+
mutex_lock(&port_priv->mac_lock);
6466

65-
if (dpaa2_switch_port_is_type_phy(port_priv))
66-
return phylink_ethtool_ksettings_get(port_priv->mac->phylink,
67-
link_ksettings);
67+
if (dpaa2_switch_port_is_type_phy(port_priv)) {
68+
err = phylink_ethtool_ksettings_get(port_priv->mac->phylink,
69+
link_ksettings);
70+
mutex_unlock(&port_priv->mac_lock);
71+
return err;
72+
}
73+
74+
mutex_unlock(&port_priv->mac_lock);
6875

6976
err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0,
7077
port_priv->ethsw_data->dpsw_handle,
@@ -99,9 +106,16 @@ dpaa2_switch_set_link_ksettings(struct net_device *netdev,
99106
bool if_running;
100107
int err = 0, ret;
101108

102-
if (dpaa2_switch_port_is_type_phy(port_priv))
103-
return phylink_ethtool_ksettings_set(port_priv->mac->phylink,
104-
link_ksettings);
109+
mutex_lock(&port_priv->mac_lock);
110+
111+
if (dpaa2_switch_port_is_type_phy(port_priv)) {
112+
err = phylink_ethtool_ksettings_set(port_priv->mac->phylink,
113+
link_ksettings);
114+
mutex_unlock(&port_priv->mac_lock);
115+
return err;
116+
}
117+
118+
mutex_unlock(&port_priv->mac_lock);
105119

106120
/* Interface needs to be down to change link settings */
107121
if_running = netif_running(netdev);
@@ -189,8 +203,12 @@ static void dpaa2_switch_ethtool_get_stats(struct net_device *netdev,
189203
dpaa2_switch_ethtool_counters[i].name, err);
190204
}
191205

206+
mutex_lock(&port_priv->mac_lock);
207+
192208
if (dpaa2_switch_port_has_mac(port_priv))
193209
dpaa2_mac_get_ethtool_stats(port_priv->mac, data + i);
210+
211+
mutex_unlock(&port_priv->mac_lock);
194212
}
195213

196214
const struct ethtool_ops dpaa2_switch_port_ethtool_ops = {

drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,8 +602,11 @@ static int dpaa2_switch_port_link_state_update(struct net_device *netdev)
602602

603603
/* When we manage the MAC/PHY using phylink there is no need
604604
* 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.
605608
*/
606-
if (dpaa2_switch_port_is_type_phy(port_priv))
609+
if (dpaa2_mac_is_type_phy(port_priv->mac))
607610
return 0;
608611

609612
/* 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)
683686
struct ethsw_core *ethsw = port_priv->ethsw_data;
684687
int err;
685688

689+
mutex_lock(&port_priv->mac_lock);
690+
686691
if (!dpaa2_switch_port_is_type_phy(port_priv)) {
687692
/* Explicitly set carrier off, otherwise
688693
* 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)
696701
port_priv->ethsw_data->dpsw_handle,
697702
port_priv->idx);
698703
if (err) {
704+
mutex_unlock(&port_priv->mac_lock);
699705
netdev_err(netdev, "dpsw_if_enable err %d\n", err);
700706
return err;
701707
}
@@ -705,6 +711,8 @@ static int dpaa2_switch_port_open(struct net_device *netdev)
705711
if (dpaa2_switch_port_is_type_phy(port_priv))
706712
dpaa2_mac_start(port_priv->mac);
707713

714+
mutex_unlock(&port_priv->mac_lock);
715+
708716
return 0;
709717
}
710718

@@ -714,13 +722,17 @@ static int dpaa2_switch_port_stop(struct net_device *netdev)
714722
struct ethsw_core *ethsw = port_priv->ethsw_data;
715723
int err;
716724

725+
mutex_lock(&port_priv->mac_lock);
726+
717727
if (dpaa2_switch_port_is_type_phy(port_priv)) {
718728
dpaa2_mac_stop(port_priv->mac);
719729
} else {
720730
netif_tx_stop_all_queues(netdev);
721731
netif_carrier_off(netdev);
722732
}
723733

734+
mutex_unlock(&port_priv->mac_lock);
735+
724736
err = dpsw_if_disable(port_priv->ethsw_data->mc_io, 0,
725737
port_priv->ethsw_data->dpsw_handle,
726738
port_priv->idx);
@@ -1460,7 +1472,9 @@ static int dpaa2_switch_port_connect_mac(struct ethsw_port_priv *port_priv)
14601472
}
14611473
}
14621474

1475+
mutex_lock(&port_priv->mac_lock);
14631476
port_priv->mac = mac;
1477+
mutex_unlock(&port_priv->mac_lock);
14641478

14651479
return 0;
14661480

@@ -1473,9 +1487,12 @@ static int dpaa2_switch_port_connect_mac(struct ethsw_port_priv *port_priv)
14731487

14741488
static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv)
14751489
{
1476-
struct dpaa2_mac *mac = port_priv->mac;
1490+
struct dpaa2_mac *mac;
14771491

1492+
mutex_lock(&port_priv->mac_lock);
1493+
mac = port_priv->mac;
14781494
port_priv->mac = NULL;
1495+
mutex_unlock(&port_priv->mac_lock);
14791496

14801497
if (!mac)
14811498
return;
@@ -1494,6 +1511,7 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
14941511
struct ethsw_port_priv *port_priv;
14951512
u32 status = ~0;
14961513
int err, if_id;
1514+
bool had_mac;
14971515

14981516
err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
14991517
DPSW_IRQ_INDEX_IF, &status);
@@ -1512,7 +1530,12 @@ static irqreturn_t dpaa2_switch_irq0_handler_thread(int irq_num, void *arg)
15121530

15131531
if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) {
15141532
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)
15161539
dpaa2_switch_port_disconnect_mac(port_priv);
15171540
else
15181541
dpaa2_switch_port_connect_mac(port_priv);
@@ -3255,6 +3278,8 @@ static int dpaa2_switch_probe_port(struct ethsw_core *ethsw,
32553278
port_priv->netdev = port_netdev;
32563279
port_priv->ethsw_data = ethsw;
32573280

3281+
mutex_init(&port_priv->mac_lock);
3282+
32583283
port_priv->idx = port_idx;
32593284
port_priv->stp_state = BR_STATE_FORWARDING;
32603285

drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ struct ethsw_port_priv {
161161

162162
struct dpaa2_switch_filter_block *filter_block;
163163
struct dpaa2_mac *mac;
164+
/* Protects against changes to port_priv->mac */
165+
struct mutex mac_lock;
164166
};
165167

166168
/* Switch data */

0 commit comments

Comments
 (0)