#include <linux/of.h>
 #include <linux/of_net.h>
 #include <net/devlink.h>
+#include <net/sch_generic.h>
 
 #include "dsa_priv.h"
 
 
        list_for_each_entry(dp, &dst->ports, list) {
                if (dsa_port_is_cpu(dp)) {
-                       err = dsa_master_setup(dp->master, dp);
+                       struct net_device *master = dp->master;
+                       bool admin_up = (master->flags & IFF_UP) &&
+                                       !qdisc_tx_is_noop(master);
+
+                       err = dsa_master_setup(master, dp);
                        if (err)
                                return err;
+
+                       /* Replay master state event */
+                       dsa_tree_master_admin_state_change(dst, master, admin_up);
+                       dsa_tree_master_oper_state_change(dst, master,
+                                                         netif_oper_up(master));
                }
        }
 
 
        rtnl_lock();
 
-       list_for_each_entry(dp, &dst->ports, list)
-               if (dsa_port_is_cpu(dp))
-                       dsa_master_teardown(dp->master);
+       list_for_each_entry(dp, &dst->ports, list) {
+               if (dsa_port_is_cpu(dp)) {
+                       struct net_device *master = dp->master;
+
+                       /* Synthesizing an "admin down" state is sufficient for
+                        * the switches to get a notification if the master is
+                        * currently up and running.
+                        */
+                       dsa_tree_master_admin_state_change(dst, master, false);
+
+                       dsa_master_teardown(master);
+               }
+       }
 
        rtnl_unlock();
 }