net: dsa: complete dsa_switch_destroy
Subsystems (3)
PATCH v2 3/5 net: dsa: complete dsa_switch_destroy
When unbinding dsa, complete the dsa_switch_destroy to unregister the fixed link phy then cleanly unregister and destroy the net devices.
--- net/dsa/dsa.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
net/dsa/dsa.c +36 -0
@@ -22,6 +22,7 @@#include <linux/of_platform.h> #include <linux/of_net.h> #include <linux/sysfs.h> +#include <linux/phy_fixed.h> #include "dsa_priv.h" char dsa_driver_version[] ="0.1" ;
@@ -420,10 +421,45 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,static void dsa_switch_destroy (struct dsa_switch *ds) { +struct device_node *port_dn; +struct phy_device *phydev; +struct dsa_chip_data *cd = ds->pd; +int port; +#ifdef CONFIG_NET_DSA_HWMON if (ds->hwmon_dev)hwmon_device_unregister (ds->hwmon_dev);#endif + +/* Disable configuration of the CPU and DSA ports */ +for (port =0 ; port <DSA_MAX_PORTS ; port++) { +if (!(dsa_is_cpu_port (ds, port) ||dsa_is_dsa_port (ds, port))) +continue ; + + port_dn = cd->port_dn[port]; +if (of_phy_is_fixed_link (port_dn)) { + phydev =of_phy_find_device (port_dn); +if (phydev) { +int addr = phydev->addr; +phy_device_free (phydev); +of_node_put (port_dn); +fixed_phy_del (addr); + } + } + } + +/* Destroy network devices for physical switch ports. */ +for (port =0 ; port <DSA_MAX_PORTS ; port++) { +if (!(ds->phys_port_mask & (1 << port))) +continue ; + +if (!ds->ports[port]) +continue ; + +unregister_netdev (ds->ports[port]); +free_netdev (ds->ports[port]); + } +mdiobus_unregister (ds->slave_mii_bus);mdiobus_free (ds->slave_mii_bus); }
Signature · 1 line
1.9.1
Quoted 5 lines · Neil Armstrong
When unbinding dsa, complete the
dsa_switch_destroyto unregister the fixed link phy then cleanly unregister and destroy the net devices.Signed-off-by Neil Armstrong <[email protected]>---
[snip]
net/dsa/dsa.c dsa_switch_setup(struct dsa_switch_tree *dst, int index, · line 446
Quoted 8 lines
net/dsa/dsa.c +8
-0+ port_dn = cd->port_dn[port]; +if (of_phy_is_fixed_link (port_dn)) { + phydev =of_phy_find_device (port_dn); +if (phydev) { +int addr = phydev->addr; +phy_device_free (phydev); +of_node_put (port_dn); +fixed_phy_del (addr);
fixed_phy_del() removes the fixed PHY from the platform fixed MDIO bus list of PHYs, so we should be okay even with switch drivers which register a link_update callback via fixed_phy_set_link_update(), but I have not checked that. The sequence of call looks (phy_device_free then fixed_phy_del) looks sane though.
Eventually this logic might be better moved into net/dsa/slave.c such that it is easy to see how it balances dsa_slave_phy_setup().
Signature · 1 line
Florian
Quoted 9 lines · Florian Fainelli
Quoted 5 lines · Neil Armstrong
When unbinding dsa, complete the
dsa_switch_destroyto unregister the fixed link phy then cleanly unregister and destroy the net devices.Signed-off-by Neil Armstrong <[email protected]>---
[snip]
Quoted 14 lines
net/dsa/dsa.c dsa_switch_setup(struct dsa_switch_tree *dst, int index, · line 446
Quoted 8 lines
net/dsa/dsa.c +8
-0+ port_dn = cd->port_dn[port]; +if (of_phy_is_fixed_link (port_dn)) { + phydev =of_phy_find_device (port_dn); +if (phydev) { +int addr = phydev->addr; +phy_device_free (phydev); +of_node_put (port_dn); +fixed_phy_del (addr);
fixed_phy_del()removes the fixed PHY from the platform fixed MDIO bus list of PHYs, so we should be okay even with switch drivers which register alink_updatecallback viafixed_phy_set_link_update(), but I have not checked that. The sequence of call looks (phy_device_freethenfixed_phy_del) looks sane though.
Actually I copied the exact sequence from the fixed link module, eventually this should be done in this module with a proper fixed_link_remove function.
Quoted 6 lines
Eventually this logic might be better moved into
net/dsa/slave.csuch that it is easy to see how it balancesdsa_slave_phy_setup().Reviewed-by Florian Fainelli <[email protected]>
Thanks for the review,
Neil