123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- From 80d12452a5f160c39d63efc1be07df36f9d07133 Mon Sep 17 00:00:00 2001
- From: Vladimir Oltean <[email protected]>
- Date: Tue, 29 Nov 2022 16:12:20 +0200
- Subject: [PATCH 13/14] 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]>
- ---
- .../freescale/dpaa2/dpaa2-switch-ethtool.c | 32 +++++++++++++++----
- .../ethernet/freescale/dpaa2/dpaa2-switch.c | 31 ++++++++++++++++--
- .../ethernet/freescale/dpaa2/dpaa2-switch.h | 2 ++
- 3 files changed, 55 insertions(+), 10 deletions(-)
- --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
- +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch-ethtool.c
- @@ -60,11 +60,18 @@ dpaa2_switch_get_link_ksettings(struct n
- {
- struct ethsw_port_priv *port_priv = netdev_priv(netdev);
- struct dpsw_link_state state = {0};
- - int err = 0;
- + int err;
-
- - if (dpaa2_switch_port_is_type_phy(port_priv))
- - return phylink_ethtool_ksettings_get(port_priv->mac->phylink,
- - link_ksettings);
- + mutex_lock(&port_priv->mac_lock);
- +
- + if (dpaa2_switch_port_is_type_phy(port_priv)) {
- + err = phylink_ethtool_ksettings_get(port_priv->mac->phylink,
- + link_ksettings);
- + mutex_unlock(&port_priv->mac_lock);
- + return err;
- + }
- +
- + mutex_unlock(&port_priv->mac_lock);
-
- err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0,
- port_priv->ethsw_data->dpsw_handle,
- @@ -99,9 +106,16 @@ dpaa2_switch_set_link_ksettings(struct n
- bool if_running;
- int err = 0, ret;
-
- - if (dpaa2_switch_port_is_type_phy(port_priv))
- - return phylink_ethtool_ksettings_set(port_priv->mac->phylink,
- - link_ksettings);
- + mutex_lock(&port_priv->mac_lock);
- +
- + if (dpaa2_switch_port_is_type_phy(port_priv)) {
- + err = phylink_ethtool_ksettings_set(port_priv->mac->phylink,
- + link_ksettings);
- + mutex_unlock(&port_priv->mac_lock);
- + return err;
- + }
- +
- + mutex_unlock(&port_priv->mac_lock);
-
- /* Interface needs to be down to change link settings */
- if_running = netif_running(netdev);
- @@ -189,8 +203,12 @@ static void dpaa2_switch_ethtool_get_sta
- dpaa2_switch_ethtool_counters[i].name, err);
- }
-
- + mutex_lock(&port_priv->mac_lock);
- +
- if (dpaa2_switch_port_has_mac(port_priv))
- dpaa2_mac_get_ethtool_stats(port_priv->mac, data + i);
- +
- + mutex_unlock(&port_priv->mac_lock);
- }
-
- const struct ethtool_ops dpaa2_switch_port_ethtool_ops = {
- --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
- +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
- @@ -603,8 +603,11 @@ static int dpaa2_switch_port_link_state_
-
- /* When we manage the MAC/PHY using phylink there is no need
- * to manually update the netif_carrier.
- + * We can avoid locking because we are called from the "link changed"
- + * IRQ handler, which is the same as the "endpoint changed" IRQ handler
- + * (the writer to port_priv->mac), so we cannot race with it.
- */
- - if (dpaa2_switch_port_is_type_phy(port_priv))
- + if (dpaa2_mac_is_type_phy(port_priv->mac))
- return 0;
-
- /* Interrupts are received even though no one issued an 'ifconfig up'
- @@ -684,6 +687,8 @@ static int dpaa2_switch_port_open(struct
- struct ethsw_core *ethsw = port_priv->ethsw_data;
- int err;
-
- + mutex_lock(&port_priv->mac_lock);
- +
- if (!dpaa2_switch_port_is_type_phy(port_priv)) {
- /* Explicitly set carrier off, otherwise
- * netif_carrier_ok() will return true and cause 'ip link show'
- @@ -697,6 +702,7 @@ static int dpaa2_switch_port_open(struct
- port_priv->ethsw_data->dpsw_handle,
- port_priv->idx);
- if (err) {
- + mutex_unlock(&port_priv->mac_lock);
- netdev_err(netdev, "dpsw_if_enable err %d\n", err);
- return err;
- }
- @@ -706,6 +712,8 @@ static int dpaa2_switch_port_open(struct
- if (dpaa2_switch_port_is_type_phy(port_priv))
- dpaa2_mac_start(port_priv->mac);
-
- + mutex_unlock(&port_priv->mac_lock);
- +
- return 0;
- }
-
- @@ -715,6 +723,8 @@ static int dpaa2_switch_port_stop(struct
- struct ethsw_core *ethsw = port_priv->ethsw_data;
- int err;
-
- + mutex_lock(&port_priv->mac_lock);
- +
- if (dpaa2_switch_port_is_type_phy(port_priv)) {
- dpaa2_mac_stop(port_priv->mac);
- } else {
- @@ -722,6 +732,8 @@ static int dpaa2_switch_port_stop(struct
- netif_carrier_off(netdev);
- }
-
- + mutex_unlock(&port_priv->mac_lock);
- +
- err = dpsw_if_disable(port_priv->ethsw_data->mc_io, 0,
- port_priv->ethsw_data->dpsw_handle,
- port_priv->idx);
- @@ -1461,7 +1473,9 @@ static int dpaa2_switch_port_connect_mac
- }
- }
-
- + mutex_lock(&port_priv->mac_lock);
- port_priv->mac = mac;
- + mutex_unlock(&port_priv->mac_lock);
-
- return 0;
-
- @@ -1474,9 +1488,12 @@ err_free_mac:
-
- static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv)
- {
- - struct dpaa2_mac *mac = port_priv->mac;
- + struct dpaa2_mac *mac;
-
- + mutex_lock(&port_priv->mac_lock);
- + mac = port_priv->mac;
- port_priv->mac = NULL;
- + mutex_unlock(&port_priv->mac_lock);
-
- if (!mac)
- return;
- @@ -1495,6 +1512,7 @@ static irqreturn_t dpaa2_switch_irq0_han
- struct ethsw_port_priv *port_priv;
- u32 status = ~0;
- int err, if_id;
- + bool had_mac;
-
- err = dpsw_get_irq_status(ethsw->mc_io, 0, ethsw->dpsw_handle,
- DPSW_IRQ_INDEX_IF, &status);
- @@ -1513,7 +1531,12 @@ static irqreturn_t dpaa2_switch_irq0_han
-
- if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) {
- rtnl_lock();
- - if (dpaa2_switch_port_has_mac(port_priv))
- + /* We can avoid locking because the "endpoint changed" IRQ
- + * handler is the only one who changes priv->mac at runtime,
- + * so we are not racing with anyone.
- + */
- + had_mac = !!port_priv->mac;
- + if (had_mac)
- dpaa2_switch_port_disconnect_mac(port_priv);
- else
- dpaa2_switch_port_connect_mac(port_priv);
- @@ -3256,6 +3279,8 @@ static int dpaa2_switch_probe_port(struc
- port_priv->netdev = port_netdev;
- port_priv->ethsw_data = ethsw;
-
- + mutex_init(&port_priv->mac_lock);
- +
- port_priv->idx = port_idx;
- port_priv->stp_state = BR_STATE_FORWARDING;
-
- --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
- +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.h
- @@ -161,6 +161,8 @@ struct ethsw_port_priv {
-
- struct dpaa2_switch_filter_block *filter_block;
- struct dpaa2_mac *mac;
- + /* Protects against changes to port_priv->mac */
- + struct mutex mac_lock;
- };
-
- /* Switch data */
|