diff mbox

[net-next,4/8] net: dsa: cleanup resources upon module removal

Message ID 1421099866-3184-5-git-send-email-f.fainelli@gmail.com
State Changes Requested, archived
Delegated to: David Miller
Headers show

Commit Message

Florian Fainelli Jan. 12, 2015, 9:57 p.m. UTC
We were not doing anything while removing the dsa module, which means
that we were leaving dangling network devices without any sort of driver
backing them, leading to all sorts of crashes. Make sure that we do
cleanup the slave network devices, slave MII bus we created, and
unassign the master_netdev dsa_ptr to make the packet processing go
through the regulard Ethernet receive path.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
 net/dsa/dsa.c      | 19 +++++++++++++++++++
 net/dsa/dsa_priv.h |  1 +
 net/dsa/slave.c    | 14 ++++++++++++++
 3 files changed, 34 insertions(+)

Comments

Sergei Shtylyov Jan. 13, 2015, 1:31 p.m. UTC | #1
Hello.

On 1/13/2015 12:57 AM, Florian Fainelli wrote:

> We were not doing anything while removing the dsa module, which means
> that we were leaving dangling network devices without any sort of driver
> backing them, leading to all sorts of crashes. Make sure that we do
> cleanup the slave network devices, slave MII bus we created, and
> unassign the master_netdev dsa_ptr to make the packet processing go
> through the regulard Ethernet receive path.

    Regular. :-)

> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
[...]

> diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
> index de77c83cfd9a..df7ec066ac64 100644
> --- a/net/dsa/dsa.c
> +++ b/net/dsa/dsa.c
> @@ -316,10 +316,22 @@ out:
>
>   static void dsa_switch_destroy(struct dsa_switch *ds)
>   {
> +	int i;

    Need empty line here.

>   #ifdef CONFIG_NET_DSA_HWMON
>   	if (ds->hwmon_dev)
>   		hwmon_device_unregister(ds->hwmon_dev);
>   #endif

[...]

WBR, Sergei

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index de77c83cfd9a..df7ec066ac64 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -316,10 +316,22 @@  out:
 
 static void dsa_switch_destroy(struct dsa_switch *ds)
 {
+	int i;
 #ifdef CONFIG_NET_DSA_HWMON
 	if (ds->hwmon_dev)
 		hwmon_device_unregister(ds->hwmon_dev);
 #endif
+
+	for (i = 0; i < DSA_MAX_PORTS; i++) {
+		if (!(ds->phys_port_mask & (1 << i)))
+			continue;
+
+		dsa_slave_destroy(ds->ports[i]);
+	}
+
+	mdiobus_unregister(ds->slave_mii_bus);
+	mdiobus_free(ds->slave_mii_bus);
+	kfree(ds);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -754,6 +766,13 @@  static int dsa_remove(struct platform_device *pdev)
 			dsa_switch_destroy(ds);
 	}
 
+	dst->master_netdev->dsa_ptr = NULL;
+	/* If we used a tagging format that doesn't have an ethertype
+	 * field, make sure that all packets from this point get sent
+	 * without the tag and go through the regular receive path.
+	 */
+	wmb();
+
 	dsa_of_remove(pdev);
 
 	return 0;
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 1397b2894c1f..1773b2a20d90 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -61,6 +61,7 @@  void dsa_slave_mii_bus_init(struct dsa_switch *ds);
 struct net_device *dsa_slave_create(struct dsa_switch *ds,
 				    struct device *parent,
 				    int port, char *name);
+void dsa_slave_destroy(struct net_device *slave_dev);
 int dsa_slave_suspend(struct net_device *slave_dev);
 int dsa_slave_resume(struct net_device *slave_dev);
 
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 515569ffde8a..043cffcb1a3a 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -690,3 +690,17 @@  dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 
 	return slave_dev;
 }
+
+void dsa_slave_destroy(struct net_device *slave_dev)
+{
+	struct dsa_slave_priv *p = netdev_priv(slave_dev);
+
+	if (p->phy) {
+		/* Prevent further updates */
+		fixed_phy_set_link_update(p->phy, NULL);
+		phy_disconnect(p->phy);
+	}
+
+	unregister_netdev(slave_dev);
+	free_netdev(slave_dev);
+}