diff options
Diffstat (limited to 'target/linux/armsr/patches-6.1/701-v6.2-0011-net-dpaa2-switch-serialize-changes-to-priv-mac-with.patch')
1 files changed, 203 insertions, 0 deletions
diff --git a/target/linux/armsr/patches-6.1/701-v6.2-0011-net-dpaa2-switch-serialize-changes-to-priv-mac-with.patch b/target/linux/armsr/patches-6.1/701-v6.2-0011-net-dpaa2-switch-serialize-changes-to-priv-mac-with.patch new file mode 100644 index 0000000000..9d6f5c52dc --- /dev/null +++ b/target/linux/armsr/patches-6.1/701-v6.2-0011-net-dpaa2-switch-serialize-changes-to-priv-mac-with.patch @@ -0,0 +1,203 @@ +From 80d12452a5f160c39d63efc1be07df36f9d07133 Mon Sep 17 00:00:00 2001 +From: Vladimir Oltean <vladimir.oltean@nxp.com> +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 <vladimir.oltean@nxp.com> +Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com> +Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com> +Signed-off-by: Paolo Abeni <pabeni@redhat.com> +--- + .../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); +@@ -3249,6 +3272,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 */ |