a4ad00ef4dcf245aa44e89b5cfc6d1db5c2debe4
[openwrt/openwrt.git] / target / linux / armsr / patches-6.1 / 701-v6.2-0012-net-dpaa2-mac-move-rtnl_lock-only-around-phylink.patch
1 From 4ea2faf5bb13d9ba9f07e996d495c4cbe34a4236 Mon Sep 17 00:00:00 2001
2 From: Vladimir Oltean <vladimir.oltean@nxp.com>
3 Date: Tue, 29 Nov 2022 16:12:21 +0200
4 Subject: [PATCH 14/14] net: dpaa2-mac: move rtnl_lock() only around
5 phylink_{,dis}connect_phy()
6
7 After the introduction of a private mac_lock that serializes access to
8 priv->mac (and port_priv->mac in the switch), the only remaining purpose
9 of rtnl_lock() is to satisfy the locking requirements of
10 phylink_fwnode_phy_connect() and phylink_disconnect_phy().
11
12 But the functions these live in, dpaa2_mac_connect() and
13 dpaa2_mac_disconnect(), have contradictory locking requirements.
14 While phylink_fwnode_phy_connect() wants rtnl_lock() to be held,
15 phylink_create() wants it to not be held.
16
17 Move the rtnl_lock() from top-level (in the dpaa2-eth and dpaa2-switch
18 drivers) to only surround the phylink calls that require it, in the
19 dpaa2-mac library code.
20
21 This is possible because dpaa2_mac_connect() and dpaa2_mac_disconnect()
22 run unlocked, and there isn't any danger of an AB/BA deadlock between
23 the rtnl_mutex and other private locks.
24
25 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
26 Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
27 Tested-by: Ioana Ciornei <ioana.ciornei@nxp.com>
28 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
29 ---
30 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 4 ----
31 drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 5 +++++
32 drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 4 ----
33 3 files changed, 5 insertions(+), 8 deletions(-)
34
35 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
36 +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
37 @@ -4527,7 +4527,6 @@ static irqreturn_t dpni_irq0_handler_thr
38 dpaa2_eth_set_mac_addr(netdev_priv(net_dev));
39 dpaa2_eth_update_tx_fqids(priv);
40
41 - rtnl_lock();
42 /* We can avoid locking because the "endpoint changed" IRQ
43 * handler is the only one who changes priv->mac at runtime,
44 * so we are not racing with anyone.
45 @@ -4537,7 +4536,6 @@ static irqreturn_t dpni_irq0_handler_thr
46 dpaa2_eth_disconnect_mac(priv);
47 else
48 dpaa2_eth_connect_mac(priv);
49 - rtnl_unlock();
50 }
51
52 return IRQ_HANDLED;
53 @@ -4856,9 +4854,7 @@ static int dpaa2_eth_remove(struct fsl_m
54 else
55 fsl_mc_free_irqs(ls_dev);
56
57 - rtnl_lock();
58 dpaa2_eth_disconnect_mac(priv);
59 - rtnl_unlock();
60 dpaa2_eth_free_rings(priv);
61 free_percpu(priv->fd);
62 free_percpu(priv->sgt_cache);
63 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
64 +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
65 @@ -428,7 +428,9 @@ int dpaa2_mac_connect(struct dpaa2_mac *
66 }
67 mac->phylink = phylink;
68
69 + rtnl_lock();
70 err = phylink_fwnode_phy_connect(mac->phylink, dpmac_node, 0);
71 + rtnl_unlock();
72 if (err) {
73 netdev_err(net_dev, "phylink_fwnode_phy_connect() = %d\n", err);
74 goto err_phylink_destroy;
75 @@ -446,7 +448,10 @@ err_pcs_destroy:
76
77 void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
78 {
79 + rtnl_lock();
80 phylink_disconnect_phy(mac->phylink);
81 + rtnl_unlock();
82 +
83 phylink_destroy(mac->phylink);
84 dpaa2_pcs_destroy(mac);
85 of_phy_put(mac->serdes_phy);
86 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
87 +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
88 @@ -1530,7 +1530,6 @@ static irqreturn_t dpaa2_switch_irq0_han
89 }
90
91 if (status & DPSW_IRQ_EVENT_ENDPOINT_CHANGED) {
92 - rtnl_lock();
93 /* We can avoid locking because the "endpoint changed" IRQ
94 * handler is the only one who changes priv->mac at runtime,
95 * so we are not racing with anyone.
96 @@ -1540,7 +1539,6 @@ static irqreturn_t dpaa2_switch_irq0_han
97 dpaa2_switch_port_disconnect_mac(port_priv);
98 else
99 dpaa2_switch_port_connect_mac(port_priv);
100 - rtnl_unlock();
101 }
102
103 out:
104 @@ -2958,9 +2956,7 @@ static void dpaa2_switch_remove_port(str
105 {
106 struct ethsw_port_priv *port_priv = ethsw->ports[port_idx];
107
108 - rtnl_lock();
109 dpaa2_switch_port_disconnect_mac(port_priv);
110 - rtnl_unlock();
111 free_netdev(port_priv->netdev);
112 ethsw->ports[port_idx] = NULL;
113 }