Create a dsa_switch_finish() which does the opposite of dsa_switch_setup().
Create a dsa_finish_dst() which does the opposite of dsa_setup_dst().

Signed-off-by: Andrew Lunn <and...@lunn.ch>
---
 net/dsa/dsa.c | 44 +++++++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 15 deletions(-)

diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 6c9d1d812873..5062ca91852d 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -462,6 +462,13 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
        return ds;
 }
 
+static void dsa_switch_finish(struct dsa_switch *ds, struct device *parent)
+{
+       dsa_switch_finish_one(ds);
+
+       devm_kfree(parent, ds);
+}
+
 #ifdef CONFIG_PM_SLEEP
 static int dsa_switch_suspend(struct dsa_switch *ds)
 {
@@ -855,6 +862,26 @@ static int dsa_setup_dst(struct dsa_switch_tree *dst, 
struct net_device *dev,
        return 0;
 }
 
+static void dsa_finish_dst(struct dsa_switch_tree *dst, struct device *parent,
+                          struct dsa_platform_data *pd)
+{
+       struct net_device *dev = dst->master_netdev;
+       int i;
+
+       dev->dsa_ptr = NULL;
+       /* Ensure no more packets get sent to the tag receive
+        * function.
+        */
+       wmb();
+
+       for (i = 0; i < pd->nr_chips; i++) {
+               struct dsa_switch *ds = dst->ds[i];
+
+               dsa_switch_finish(ds, parent);
+               dst->ds[i] = NULL;
+       }
+}
+
 static int dsa_probe(struct platform_device *pdev)
 {
        struct dsa_platform_data *pd = pdev->dev.platform_data;
@@ -920,27 +947,14 @@ out:
        return ret;
 }
 
-static void dsa_remove_dst(struct dsa_switch_tree *dst)
-{
-       int i;
-
-       for (i = 0; i < dst->pd->nr_chips; i++) {
-               struct dsa_switch *ds = dst->ds[i];
-
-               if (ds)
-                       dsa_switch_finish_one(ds);
-       }
-
-       dev_put(dst->master_netdev);
-}
-
 static int dsa_remove(struct platform_device *pdev)
 {
        struct dsa_switch_tree *dst = platform_get_drvdata(pdev);
        struct dsa_platform_data *pd = pdev->dev.platform_data;
 
-       dsa_remove_dst(dst);
+       dsa_finish_dst(dst, &pdev->dev, pd);
        dsa_of_remove(&pdev->dev, pd);
+       dev_put(dst->master_netdev);
 
        return 0;
 }
-- 
2.7.0

Reply via email to