--- /dev/null
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -552,8 +552,14 @@ struct dsa_switch_ops {
+ void (*port_stp_state_set)(struct dsa_switch *ds, int port,
+ u8 state);
+ void (*port_fast_age)(struct dsa_switch *ds, int port);
+- int (*port_egress_floods)(struct dsa_switch *ds, int port,
+- bool unicast, bool multicast);
++ int (*port_pre_bridge_flags)(struct dsa_switch *ds, int port,
++ unsigned long flags,
++ struct netlink_ext_ack *extack);
++ int (*port_bridge_flags)(struct dsa_switch *ds, int port,
++ unsigned long flags,
++ struct netlink_ext_ack *extack);
++ int (*port_set_mrouter)(struct dsa_switch *ds, int port, bool mrouter,
++ struct netlink_ext_ack *extack);
+
+ /*
+ * VLAN support
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -167,11 +167,11 @@ int dsa_port_mdb_add(const struct dsa_po
+ int dsa_port_mdb_del(const struct dsa_port *dp,
+ const struct switchdev_obj_port_mdb *mdb);
+ int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
+- struct switchdev_trans *trans);
++ struct switchdev_trans *trans, struct netlink_ext_ack *extack);
+ int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
+- struct switchdev_trans *trans);
++ struct switchdev_trans *trans, struct netlink_ext_ack *extack);
+ int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
+- struct switchdev_trans *trans);
++ struct switchdev_trans *trans, struct netlink_ext_ack *extack);
+ int dsa_port_vlan_add(struct dsa_port *dp,
+ const struct switchdev_obj_port_vlan *vlan,
+ struct switchdev_trans *trans);
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -145,7 +145,7 @@ int dsa_port_bridge_join(struct dsa_port
+ int err;
+
+ /* Set the flooding mode before joining the port in the switch */
+- err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL);
++ err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL, NULL);
+ if (err)
+ return err;
+
+@@ -158,7 +158,7 @@ int dsa_port_bridge_join(struct dsa_port
+
+ /* The bridging is rolled back on error */
+ if (err) {
+- dsa_port_bridge_flags(dp, 0, NULL);
++ dsa_port_bridge_flags(dp, 0, NULL, NULL);
+ dp->bridge_dev = NULL;
+ }
+
+@@ -185,7 +185,7 @@ void dsa_port_bridge_leave(struct dsa_po
+ pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
+
+ /* Port is leaving the bridge, disable flooding */
+- dsa_port_bridge_flags(dp, 0, NULL);
++ dsa_port_bridge_flags(dp, 0, NULL, NULL);
+
+ /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
+ * so allow it to be in BR_STATE_FORWARDING to be kept functional
+@@ -333,44 +333,44 @@ int dsa_port_ageing_time(struct dsa_port
+ }
+
+ int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
+- struct switchdev_trans *trans)
++ struct switchdev_trans *trans, struct netlink_ext_ack *extack)
+ {
+ struct dsa_switch *ds = dp->ds;
+
+- if (!ds->ops->port_egress_floods ||
+- (flags & ~(BR_FLOOD | BR_MCAST_FLOOD)))
++ if (!ds->ops->port_pre_bridge_flags)
+ return -EINVAL;
+
+- return 0;
++ return ds->ops->port_pre_bridge_flags(ds, dp->index, flags, extack);
+ }
+
+ int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
+- struct switchdev_trans *trans)
++ struct switchdev_trans *trans, struct netlink_ext_ack *extack)
+ {
+ struct dsa_switch *ds = dp->ds;
+- int port = dp->index;
+- int err = 0;
+
+ if (switchdev_trans_ph_prepare(trans))
+ return 0;
+
+- if (ds->ops->port_egress_floods)
+- err = ds->ops->port_egress_floods(ds, port, flags & BR_FLOOD,
+- flags & BR_MCAST_FLOOD);
++ if (!ds->ops->port_bridge_flags)
++ return -EINVAL;
++
++ return ds->ops->port_bridge_flags(ds, dp->index, flags, extack);
+
+- return err;
+ }
+
+ int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
+- struct switchdev_trans *trans)
++ struct switchdev_trans *trans,
++ struct netlink_ext_ack *extack)
+ {
+ struct dsa_switch *ds = dp->ds;
+- int port = dp->index;
+
+ if (switchdev_trans_ph_prepare(trans))
+- return ds->ops->port_egress_floods ? 0 : -EOPNOTSUPP;
++ return ds->ops->port_set_mrouter ? 0 : -EOPNOTSUPP;
++
++ if (!ds->ops->port_set_mrouter)
++ return -EOPNOTSUPP;
+
+- return ds->ops->port_egress_floods(ds, port, true, mrouter);
++ return ds->ops->port_set_mrouter(ds, dp->index, mrouter, extack);
+ }
+
+ int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -290,13 +290,13 @@ static int dsa_slave_port_attr_set(struc
+ break;
+ case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
+ ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags,
+- trans);
++ trans, NULL);
+ break;
+ case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
+- ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, trans);
++ ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, trans, NULL);
+ break;
+ case SWITCHDEV_ATTR_ID_BRIDGE_MROUTER:
+- ret = dsa_port_mrouter(dp->cpu_dp, attr->u.mrouter, trans);
++ ret = dsa_port_mrouter(dp->cpu_dp, attr->u.mrouter, trans, NULL);
+ break;
+ default:
+ ret = -EOPNOTSUPP;