mv88e6xxx_reg_unlock(chip);
 }
 
-static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds, int dev,
+static int mv88e6xxx_crosschip_bridge_join(struct dsa_switch *ds,
+                                          int tree_index, int sw_index,
                                           int port, struct net_device *br)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
        int err;
 
+       if (tree_index != ds->dst->index)
+               return 0;
+
        mv88e6xxx_reg_lock(chip);
-       err = mv88e6xxx_pvt_map(chip, dev, port);
+       err = mv88e6xxx_pvt_map(chip, sw_index, port);
        mv88e6xxx_reg_unlock(chip);
 
        return err;
 }
 
-static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds, int dev,
+static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds,
+                                            int tree_index, int sw_index,
                                             int port, struct net_device *br)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
 
+       if (tree_index != ds->dst->index)
+               return;
+
        mv88e6xxx_reg_lock(chip);
-       if (mv88e6xxx_pvt_map(chip, dev, port))
+       if (mv88e6xxx_pvt_map(chip, sw_index, port))
                dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
        mv88e6xxx_reg_unlock(chip);
 }
 
        /*
         * Cross-chip operations
         */
-       int     (*crosschip_bridge_join)(struct dsa_switch *ds, int sw_index,
-                                        int port, struct net_device *br);
-       void    (*crosschip_bridge_leave)(struct dsa_switch *ds, int sw_index,
-                                         int port, struct net_device *br);
+       int     (*crosschip_bridge_join)(struct dsa_switch *ds, int tree_index,
+                                        int sw_index, int port,
+                                        struct net_device *br);
+       void    (*crosschip_bridge_leave)(struct dsa_switch *ds, int tree_index,
+                                         int sw_index, int port,
+                                         struct net_device *br);
 
        /*
         * PTP functionality
 
 /* DSA_NOTIFIER_BRIDGE_* */
 struct dsa_notifier_bridge_info {
        struct net_device *br;
+       int tree_index;
        int sw_index;
        int port;
 };
 
 
 #include "dsa_priv.h"
 
+static int dsa_broadcast(unsigned long e, void *v)
+{
+       struct dsa_switch_tree *dst;
+       int err = 0;
+
+       list_for_each_entry(dst, &dsa_tree_list, list) {
+               struct raw_notifier_head *nh = &dst->nh;
+
+               err = raw_notifier_call_chain(nh, e, v);
+               err = notifier_to_errno(err);
+               if (err)
+                       break;
+       }
+
+       return err;
+}
+
 static int dsa_port_notify(const struct dsa_port *dp, unsigned long e, void *v)
 {
        struct raw_notifier_head *nh = &dp->ds->dst->nh;
 int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br)
 {
        struct dsa_notifier_bridge_info info = {
+               .tree_index = dp->ds->dst->index,
                .sw_index = dp->ds->index,
                .port = dp->index,
                .br = br,
         */
        dp->bridge_dev = br;
 
-       err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_JOIN, &info);
+       err = dsa_broadcast(DSA_NOTIFIER_BRIDGE_JOIN, &info);
 
        /* The bridging is rolled back on error */
        if (err) {
 void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
 {
        struct dsa_notifier_bridge_info info = {
+               .tree_index = dp->ds->dst->index,
                .sw_index = dp->ds->index,
                .port = dp->index,
                .br = br,
         */
        dp->bridge_dev = NULL;
 
-       err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info);
+       err = dsa_broadcast(DSA_NOTIFIER_BRIDGE_LEAVE, &info);
        if (err)
                pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
 
 
 static int dsa_switch_bridge_join(struct dsa_switch *ds,
                                  struct dsa_notifier_bridge_info *info)
 {
-       if (ds->index == info->sw_index && ds->ops->port_bridge_join)
+       struct dsa_switch_tree *dst = ds->dst;
+
+       if (dst->index == info->tree_index && ds->index == info->sw_index &&
+           ds->ops->port_bridge_join)
                return ds->ops->port_bridge_join(ds, info->port, info->br);
 
-       if (ds->index != info->sw_index && ds->ops->crosschip_bridge_join)
-               return ds->ops->crosschip_bridge_join(ds, info->sw_index,
+       if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
+           ds->ops->crosschip_bridge_join)
+               return ds->ops->crosschip_bridge_join(ds, info->tree_index,
+                                                     info->sw_index,
                                                      info->port, info->br);
 
        return 0;
                                   struct dsa_notifier_bridge_info *info)
 {
        bool unset_vlan_filtering = br_vlan_enabled(info->br);
+       struct dsa_switch_tree *dst = ds->dst;
        int err, i;
 
-       if (ds->index == info->sw_index && ds->ops->port_bridge_leave)
+       if (dst->index == info->tree_index && ds->index == info->sw_index &&
+           ds->ops->port_bridge_join)
                ds->ops->port_bridge_leave(ds, info->port, info->br);
 
-       if (ds->index != info->sw_index && ds->ops->crosschip_bridge_leave)
-               ds->ops->crosschip_bridge_leave(ds, info->sw_index, info->port,
+       if ((dst->index != info->tree_index || ds->index != info->sw_index) &&
+           ds->ops->crosschip_bridge_join)
+               ds->ops->crosschip_bridge_leave(ds, info->tree_index,
+                                               info->sw_index, info->port,
                                                info->br);
 
        /* If the bridge was vlan_filtering, the bridge core doesn't trigger an