|
@@ -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,46 @@ 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);
|
|
|
}
|