@@ -1889,6 +1889,9 @@ static int dpaa2_switch_port_attr_set_event(struct net_device *netdev,
return notifier_from_errno(err);
}
+static struct notifier_block dpaa2_switch_port_switchdev_nb;
+static struct notifier_block dpaa2_switch_port_switchdev_blocking_nb;
+
static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
struct net_device *upper_dev,
struct netlink_ext_ack *extack)
@@ -1930,7 +1933,10 @@ static int dpaa2_switch_port_bridge_join(struct net_device *netdev,
if (err)
goto err_egress_flood;
- return switchdev_bridge_port_offload(netdev, netdev, extack);
+ return switchdev_bridge_port_offload(netdev, netdev, NULL,
+ &dpaa2_switch_port_switchdev_nb,
+ &dpaa2_switch_port_switchdev_blocking_nb,
+ extack);
err_egress_flood:
dpaa2_switch_port_set_fdb(port_priv, NULL);
@@ -1961,7 +1967,10 @@ static int dpaa2_switch_port_pre_bridge_leave(struct net_device *netdev,
struct net_device *upper_dev,
struct netlink_ext_ack *extack)
{
- return switchdev_bridge_port_unoffload(netdev, netdev, extack);
+ return switchdev_bridge_port_unoffload(netdev, netdev, NULL,
+ &dpaa2_switch_port_switchdev_nb,
+ &dpaa2_switch_port_switchdev_blocking_nb,
+ extack);
}
static int dpaa2_switch_port_bridge_leave(struct net_device *netdev)
@@ -501,7 +501,10 @@ int prestera_bridge_port_join(struct net_device *br_dev,
goto err_brport_create;
}
- err = switchdev_bridge_port_offload(br_port->dev, port->dev, extack);
+ err = switchdev_bridge_port_offload(br_port->dev, port->dev, port,
+ &swdev->swdev_nb,
+ &swdev->swdev_nb_blk,
+ extack);
if (err)
goto err_brport_offload;
@@ -515,7 +518,9 @@ int prestera_bridge_port_join(struct net_device *br_dev,
return 0;
err_port_join:
- switchdev_bridge_port_unoffload(br_port->dev, port->dev, extack);
+ switchdev_bridge_port_unoffload(br_port->dev, port->dev, port,
+ &swdev->swdev_nb, &swdev->swdev_nb_blk,
+ extack);
err_brport_offload:
prestera_bridge_port_put(br_port);
err_brport_create:
@@ -539,7 +544,9 @@ int prestera_pre_bridge_port_leave(struct net_device *br_dev,
if (!br_port)
return -ENODEV;
- return switchdev_bridge_port_unoffload(br_port->dev, port->dev,
+ return switchdev_bridge_port_unoffload(br_port->dev, port->dev, port,
+ &swdev->swdev_nb,
+ &swdev->swdev_nb_blk,
extack);
}
@@ -2360,6 +2360,9 @@ static const struct mlxsw_sp_bridge_ops mlxsw_sp2_bridge_8021ad_ops = {
.fid_vid = mlxsw_sp_bridge_8021q_fid_vid,
};
+static struct notifier_block mlxsw_sp_switchdev_blocking_notifier;
+struct notifier_block mlxsw_sp_switchdev_notifier;
+
int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *brport_dev,
struct net_device *br_dev,
@@ -2382,7 +2385,10 @@ int mlxsw_sp_port_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
if (err)
goto err_port_join;
- return switchdev_bridge_port_offload(brport_dev, dev, extack);
+ return switchdev_bridge_port_offload(brport_dev, dev, mlxsw_sp_port,
+ &mlxsw_sp_switchdev_notifier,
+ &mlxsw_sp_switchdev_blocking_notifier,
+ extack);
err_port_join:
mlxsw_sp_bridge_port_put(mlxsw_sp->bridge, bridge_port);
@@ -2396,7 +2402,10 @@ int mlxsw_sp_port_pre_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
{
struct net_device *dev = mlxsw_sp_port->dev;
- return switchdev_bridge_port_unoffload(brport_dev, dev, extack);
+ return switchdev_bridge_port_unoffload(brport_dev, dev, mlxsw_sp_port,
+ &mlxsw_sp_switchdev_notifier,
+ &mlxsw_sp_switchdev_blocking_notifier,
+ extack);
}
void mlxsw_sp_port_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
@@ -116,15 +116,22 @@ static int sparx5_port_bridge_join(struct sparx5_port *port,
*/
__dev_mc_unsync(ndev, sparx5_mc_unsync);
- return switchdev_bridge_port_offload(ndev, ndev, extack);
+ return switchdev_bridge_port_offload(ndev, ndev, NULL,
+ &sparx5->switchdev_nb,
+ &sparx5->switchdev_blocking_nb,
+ extack);
}
static int sparx5_port_pre_bridge_leave(struct sparx5_port *port,
struct netlink_ext_ack *extack)
{
+ struct sparx5 *sparx5 = port->sparx5;
struct net_device *ndev = port->ndev;
- return switchdev_bridge_port_unoffload(ndev, ndev, extack);
+ return switchdev_bridge_port_unoffload(ndev, ndev, NULL,
+ &sparx5->switchdev_nb,
+ &sparx5->switchdev_blocking_nb,
+ extack);
}
static void sparx5_port_bridge_leave(struct sparx5_port *port,
@@ -1154,38 +1154,19 @@ static int ocelot_switchdev_sync(struct ocelot *ocelot, int port,
struct net_device *bridge_dev,
struct netlink_ext_ack *extack)
{
- struct ocelot_port *ocelot_port = ocelot->ports[port];
- struct ocelot_port_private *priv;
clock_t ageing_time;
u8 stp_state;
- int err;
-
- priv = container_of(ocelot_port, struct ocelot_port_private, port);
ocelot_inherit_brport_flags(ocelot, port, brport_dev);
stp_state = br_port_get_stp_state(brport_dev);
ocelot_bridge_stp_state_set(ocelot, port, stp_state);
- err = ocelot_port_vlan_filtering(ocelot, port,
- br_vlan_enabled(bridge_dev));
- if (err)
- return err;
-
ageing_time = br_get_ageing_time(bridge_dev);
ocelot_port_attr_ageing_set(ocelot, port, ageing_time);
- err = br_mdb_replay(bridge_dev, brport_dev, priv, true,
- &ocelot_switchdev_blocking_nb, extack);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- err = br_vlan_replay(bridge_dev, brport_dev, priv, true,
- &ocelot_switchdev_blocking_nb, extack);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- return 0;
+ return ocelot_port_vlan_filtering(ocelot, port,
+ br_vlan_enabled(bridge_dev));
}
static int ocelot_switchdev_unsync(struct ocelot *ocelot, int port)
@@ -1216,7 +1197,10 @@ static int ocelot_netdevice_bridge_join(struct net_device *dev,
ocelot_port_bridge_join(ocelot, port, bridge);
- err = switchdev_bridge_port_offload(brport_dev, dev, extack);
+ err = switchdev_bridge_port_offload(brport_dev, dev, priv,
+ &ocelot_netdevice_nb,
+ &ocelot_switchdev_blocking_nb,
+ extack);
if (err)
goto err_switchdev_offload;
@@ -1227,7 +1211,10 @@ static int ocelot_netdevice_bridge_join(struct net_device *dev,
return 0;
err_switchdev_sync:
- switchdev_bridge_port_unoffload(brport_dev, dev, extack);
+ switchdev_bridge_port_unoffload(brport_dev, dev, priv,
+ &ocelot_netdevice_nb,
+ &ocelot_switchdev_blocking_nb,
+ extack);
err_switchdev_offload:
ocelot_port_bridge_leave(ocelot, port, bridge);
return err;
@@ -1237,7 +1224,12 @@ static int ocelot_netdevice_pre_bridge_leave(struct net_device *dev,
struct net_device *brport_dev,
struct netlink_ext_ack *extack)
{
- return switchdev_bridge_port_unoffload(brport_dev, dev, extack);
+ struct ocelot_port_private *priv = netdev_priv(dev);
+
+ return switchdev_bridge_port_unoffload(brport_dev, dev, priv,
+ &ocelot_netdevice_nb,
+ &ocelot_switchdev_blocking_nb,
+ extack);
}
static int ocelot_netdevice_bridge_leave(struct net_device *dev,
@@ -142,4 +142,7 @@ struct rocker_world_ops {
extern struct rocker_world_ops rocker_ofdpa_ops;
+extern struct notifier_block rocker_switchdev_notifier;
+extern struct notifier_block rocker_switchdev_blocking_notifier;
+
#endif
@@ -2861,11 +2861,11 @@ static int rocker_switchdev_blocking_event(struct notifier_block *unused,
return NOTIFY_DONE;
}
-static struct notifier_block rocker_switchdev_notifier = {
+struct notifier_block rocker_switchdev_notifier = {
.notifier_call = rocker_switchdev_event,
};
-static struct notifier_block rocker_switchdev_blocking_notifier = {
+struct notifier_block rocker_switchdev_blocking_notifier = {
.notifier_call = rocker_switchdev_blocking_event,
};
@@ -2598,7 +2598,10 @@ static int ofdpa_port_bridge_join(struct ofdpa_port *ofdpa_port,
if (err)
return err;
- return switchdev_bridge_port_offload(dev, dev, extack);
+ return switchdev_bridge_port_offload(dev, dev, NULL,
+ &rocker_switchdev_notifier,
+ &rocker_switchdev_blocking_notifier,
+ extack);
}
static int ofdpa_port_pre_bridge_leave(struct ofdpa_port *ofdpa_port,
@@ -2606,7 +2609,10 @@ static int ofdpa_port_pre_bridge_leave(struct ofdpa_port *ofdpa_port,
{
struct net_device *dev = ofdpa_port->dev;
- return switchdev_bridge_port_unoffload(dev, dev, extack);
+ return switchdev_bridge_port_unoffload(dev, dev, NULL,
+ &rocker_switchdev_notifier,
+ &rocker_switchdev_blocking_notifier,
+ extack);
}
static int ofdpa_port_bridge_leave(struct ofdpa_port *ofdpa_port)
@@ -2096,7 +2096,10 @@ static int am65_cpsw_netdevice_port_link(struct net_device *ndev,
return -EOPNOTSUPP;
}
- err = switchdev_bridge_port_offload(ndev, ndev, extack);
+ err = switchdev_bridge_port_offload(ndev, ndev, NULL,
+ &am65_cpsw_switchdev_notifier,
+ &am65_cpsw_switchdev_bl_notifier,
+ extack);
if (err)
return err;
@@ -2110,7 +2113,10 @@ static int am65_cpsw_netdevice_port_link(struct net_device *ndev,
static int am65_cpsw_netdevice_port_pre_unlink(struct net_device *ndev,
struct netlink_ext_ack *extack)
{
- return switchdev_bridge_port_unoffload(ndev, ndev, extack);
+ return switchdev_bridge_port_unoffload(ndev, ndev, NULL,
+ &am65_cpsw_switchdev_notifier,
+ &am65_cpsw_switchdev_bl_notifier,
+ extack);
}
static void am65_cpsw_netdevice_port_unlink(struct net_device *ndev)
@@ -473,7 +473,7 @@ static int am65_cpsw_switchdev_event(struct notifier_block *unused,
return NOTIFY_BAD;
}
-static struct notifier_block cpsw_switchdev_notifier = {
+struct notifier_block am65_cpsw_switchdev_notifier = {
.notifier_call = am65_cpsw_switchdev_event,
};
@@ -506,7 +506,7 @@ static int am65_cpsw_switchdev_blocking_event(struct notifier_block *unused,
return NOTIFY_DONE;
}
-static struct notifier_block cpsw_switchdev_bl_notifier = {
+struct notifier_block am65_cpsw_switchdev_bl_notifier = {
.notifier_call = am65_cpsw_switchdev_blocking_event,
};
@@ -514,18 +514,18 @@ int am65_cpsw_switchdev_register_notifiers(struct am65_cpsw_common *cpsw)
{
int ret = 0;
- ret = register_switchdev_notifier(&cpsw_switchdev_notifier);
+ ret = register_switchdev_notifier(&am65_cpsw_switchdev_notifier);
if (ret) {
dev_err(cpsw->dev, "register switchdev notifier fail ret:%d\n",
ret);
return ret;
}
- ret = register_switchdev_blocking_notifier(&cpsw_switchdev_bl_notifier);
+ ret = register_switchdev_blocking_notifier(&am65_cpsw_switchdev_bl_notifier);
if (ret) {
dev_err(cpsw->dev, "register switchdev blocking notifier ret:%d\n",
ret);
- unregister_switchdev_notifier(&cpsw_switchdev_notifier);
+ unregister_switchdev_notifier(&am65_cpsw_switchdev_notifier);
}
return ret;
@@ -533,6 +533,6 @@ int am65_cpsw_switchdev_register_notifiers(struct am65_cpsw_common *cpsw)
void am65_cpsw_switchdev_unregister_notifiers(struct am65_cpsw_common *cpsw)
{
- unregister_switchdev_blocking_notifier(&cpsw_switchdev_bl_notifier);
- unregister_switchdev_notifier(&cpsw_switchdev_notifier);
+ unregister_switchdev_blocking_notifier(&am65_cpsw_switchdev_bl_notifier);
+ unregister_switchdev_notifier(&am65_cpsw_switchdev_notifier);
}
@@ -7,6 +7,9 @@
#include <linux/skbuff.h>
+extern struct notifier_block am65_cpsw_switchdev_notifier;
+extern struct notifier_block am65_cpsw_switchdev_bl_notifier;
+
#if IS_ENABLED(CONFIG_TI_K3_AM65_CPSW_SWITCHDEV)
static inline void am65_cpsw_nuss_set_offload_fwd_mark(struct sk_buff *skb, bool val)
{
@@ -1517,7 +1517,10 @@ static int cpsw_netdevice_port_link(struct net_device *ndev,
return -EOPNOTSUPP;
}
- err = switchdev_bridge_port_offload(ndev, ndev, extack);
+ err = switchdev_bridge_port_offload(ndev, ndev, NULL,
+ &cpsw_switchdev_notifier,
+ &cpsw_switchdev_bl_notifier,
+ extack);
if (err)
return err;
@@ -1531,7 +1534,10 @@ static int cpsw_netdevice_port_link(struct net_device *ndev,
static int cpsw_netdevice_port_pre_unlink(struct net_device *ndev,
struct netlink_ext_ack *extack)
{
- return switchdev_bridge_port_unoffload(ndev, ndev, extack);
+ return switchdev_bridge_port_unoffload(ndev, ndev, NULL,
+ &cpsw_switchdev_notifier,
+ &cpsw_switchdev_bl_notifier,
+ extack);
}
static void cpsw_netdevice_port_unlink(struct net_device *ndev)
@@ -483,7 +483,7 @@ static int cpsw_switchdev_event(struct notifier_block *unused,
return NOTIFY_BAD;
}
-static struct notifier_block cpsw_switchdev_notifier = {
+struct notifier_block cpsw_switchdev_notifier = {
.notifier_call = cpsw_switchdev_event,
};
@@ -516,7 +516,7 @@ static int cpsw_switchdev_blocking_event(struct notifier_block *unused,
return NOTIFY_DONE;
}
-static struct notifier_block cpsw_switchdev_bl_notifier = {
+struct notifier_block cpsw_switchdev_bl_notifier = {
.notifier_call = cpsw_switchdev_blocking_event,
};
@@ -12,4 +12,7 @@ bool cpsw_port_dev_check(const struct net_device *dev);
int cpsw_switchdev_register_notifiers(struct cpsw_common *cpsw);
void cpsw_switchdev_unregister_notifiers(struct cpsw_common *cpsw);
+extern struct notifier_block cpsw_switchdev_notifier;
+extern struct notifier_block cpsw_switchdev_bl_notifier;
+
#endif /* DRIVERS_NET_ETHERNET_TI_CPSW_SWITCHDEV_H_ */
@@ -70,9 +70,6 @@ bool br_multicast_has_querier_adjacent(struct net_device *dev, int proto);
bool br_multicast_has_router_adjacent(struct net_device *dev, int proto);
bool br_multicast_enabled(const struct net_device *dev);
bool br_multicast_router(const struct net_device *dev);
-int br_mdb_replay(struct net_device *br_dev, struct net_device *dev,
- const void *ctx, bool adding, struct notifier_block *nb,
- struct netlink_ext_ack *extack);
#else
static inline int br_multicast_list_adjacent(struct net_device *dev,
struct list_head *br_ip_list)
@@ -104,13 +101,6 @@ static inline bool br_multicast_router(const struct net_device *dev)
{
return false;
}
-static inline int br_mdb_replay(const struct net_device *br_dev,
- const struct net_device *dev, const void *ctx,
- bool adding, struct notifier_block *nb,
- struct netlink_ext_ack *extack)
-{
- return -EOPNOTSUPP;
-}
#endif
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_BRIDGE_VLAN_FILTERING)
@@ -120,9 +110,6 @@ int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid);
int br_vlan_get_proto(const struct net_device *dev, u16 *p_proto);
int br_vlan_get_info(const struct net_device *dev, u16 vid,
struct bridge_vlan_info *p_vinfo);
-int br_vlan_replay(struct net_device *br_dev, struct net_device *dev,
- const void *ctx, bool adding, struct notifier_block *nb,
- struct netlink_ext_ack *extack);
#else
static inline bool br_vlan_enabled(const struct net_device *dev)
{
@@ -149,14 +136,6 @@ static inline int br_vlan_get_info(const struct net_device *dev, u16 vid,
{
return -EINVAL;
}
-
-static inline int br_vlan_replay(struct net_device *br_dev,
- struct net_device *dev, const void *ctx,
- bool adding, struct notifier_block *nb,
- struct netlink_ext_ack *extack)
-{
- return -EOPNOTSUPP;
-}
#endif
#if IS_ENABLED(CONFIG_BRIDGE)
@@ -167,8 +146,6 @@ void br_fdb_clear_offload(const struct net_device *dev, u16 vid);
bool br_port_flag_is_set(const struct net_device *dev, unsigned long flag);
u8 br_port_get_stp_state(const struct net_device *dev);
clock_t br_get_ageing_time(const struct net_device *br_dev);
-int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
- const void *ctx, bool adding, struct notifier_block *nb);
#else
static inline struct net_device *
br_fdb_find_port(const struct net_device *br_dev,
@@ -197,36 +174,39 @@ static inline clock_t br_get_ageing_time(const struct net_device *br_dev)
{
return 0;
}
-
-static inline int br_fdb_replay(const struct net_device *br_dev,
- const struct net_device *dev, const void *ctx,
- bool adding, struct notifier_block *nb)
-{
- return -EOPNOTSUPP;
-}
#endif
#if IS_ENABLED(CONFIG_BRIDGE) && IS_ENABLED(CONFIG_NET_SWITCHDEV)
int switchdev_bridge_port_offload(struct net_device *brport_dev,
- struct net_device *dev,
+ struct net_device *dev, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
struct netlink_ext_ack *extack);
int switchdev_bridge_port_unoffload(struct net_device *brport_dev,
- struct net_device *dev,
+ struct net_device *dev, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
struct netlink_ext_ack *extack);
#else
-static inline int switchdev_bridge_port_offload(struct net_device *brport_dev,
- struct net_device *dev,
- struct netlink_ext_ack *extack)
+static inline int
+switchdev_bridge_port_offload(struct net_device *brport_dev,
+ struct net_device *dev, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
+ struct netlink_ext_ack *extack)
{
return -EINVAL;
}
-static inline int switchdev_bridge_port_unoffload(struct net_device *brport_dev,
- struct net_device *dev,
- struct netlink_ext_ack *extack)
+static inline int
+switchdev_bridge_port_unoffload(struct net_device *brport_dev,
+ struct net_device *dev, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
+ struct netlink_ext_ack *extack)
{
return -EINVAL;
}
@@ -792,7 +792,6 @@ int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
return err;
}
-EXPORT_SYMBOL_GPL(br_fdb_replay);
static void fdb_notify(struct net_bridge *br,
const struct net_bridge_fdb_entry *fdb, int type,
@@ -686,7 +686,6 @@ int br_mdb_replay(struct net_device *br_dev, struct net_device *dev,
return err;
}
-EXPORT_SYMBOL_GPL(br_mdb_replay);
static void br_mdb_switchdev_host_port(struct net_device *dev,
struct net_device *lower_dev,
@@ -735,6 +735,8 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
bool swdev_notify);
void br_fdb_offloaded_set(struct net_bridge *br, struct net_bridge_port *p,
const unsigned char *addr, u16 vid, bool offloaded);
+int br_fdb_replay(const struct net_device *br_dev, const struct net_device *dev,
+ const void *ctx, bool adding, struct notifier_block *nb);
/* br_forward.c */
enum br_pkt_type {
@@ -877,6 +879,10 @@ br_multicast_find_group_src(struct net_bridge_port_group *pg, struct br_ip *ip);
void br_multicast_del_group_src(struct net_bridge_group_src *src,
bool fastleave);
+int br_mdb_replay(struct net_device *br_dev, struct net_device *dev,
+ const void *ctx, bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack);
+
static inline bool br_group_is_l2(const struct br_ip *group)
{
return group->proto == 0;
@@ -1135,6 +1141,15 @@ static inline int br_multicast_igmp_type(const struct sk_buff *skb)
{
return 0;
}
+
+static inline int br_mdb_replay(struct net_device *br_dev,
+ struct net_device *dev, const void *ctx,
+ bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack)
+{
+ return -EOPNOTSUPP;
+}
+
#endif
/* br_vlan.c */
@@ -1185,6 +1200,9 @@ void br_vlan_notify(const struct net_bridge *br,
const struct net_bridge_port *p,
u16 vid, u16 vid_range,
int cmd);
+int br_vlan_replay(struct net_device *br_dev, struct net_device *dev,
+ const void *ctx, bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack);
bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
const struct net_bridge_vlan *range_end);
@@ -1427,6 +1445,14 @@ static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
{
return true;
}
+
+static inline int br_vlan_replay(struct net_device *br_dev,
+ struct net_device *dev, const void *ctx,
+ bool adding, struct notifier_block *nb,
+ struct netlink_ext_ack *extack)
+{
+ return -EOPNOTSUPP;
+}
#endif
/* br_vlan_options.c */
@@ -212,11 +212,74 @@ static void nbp_switchdev_del(struct net_bridge_port *p,
nbp_switchdev_hwdom_put(p);
}
+static int nbp_switchdev_sync_objs(struct net_bridge_port *p, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
+ struct netlink_ext_ack *extack)
+{
+ struct net_device *br_dev = p->br->dev;
+ struct net_device *dev = p->dev;
+ int err;
+
+ err = br_vlan_replay(br_dev, dev, ctx, true, blocking_nb, extack);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ err = br_mdb_replay(br_dev, dev, ctx, true, blocking_nb, extack);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ /* Forwarding and termination FDB entries on the port */
+ err = br_fdb_replay(br_dev, dev, ctx, true, atomic_nb);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ /* Termination FDB entries on the bridge itself */
+ err = br_fdb_replay(br_dev, br_dev, ctx, true, atomic_nb);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ return 0;
+}
+
+static int nbp_switchdev_unsync_objs(struct net_bridge_port *p,
+ const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
+ struct netlink_ext_ack *extack)
+{
+ struct net_device *br_dev = p->br->dev;
+ struct net_device *dev = p->dev;
+ int err;
+
+ err = br_vlan_replay(br_dev, dev, ctx, false, blocking_nb, extack);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ err = br_mdb_replay(br_dev, dev, ctx, false, blocking_nb, extack);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ /* Forwarding and termination FDB entries on the port */
+ err = br_fdb_replay(br_dev, dev, ctx, false, atomic_nb);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ /* Termination FDB entries on the bridge itself */
+ err = br_fdb_replay(br_dev, br_dev, ctx, false, atomic_nb);
+ if (err && err != -EOPNOTSUPP)
+ return err;
+
+ return 0;
+}
+
/* Let the bridge know that this port is offloaded, so that it can assign a
* switchdev hardware domain to it.
*/
int switchdev_bridge_port_offload(struct net_device *brport_dev,
- struct net_device *dev,
+ struct net_device *dev, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
struct netlink_ext_ack *extack)
{
struct netdev_phys_item_id ppid;
@@ -233,12 +296,27 @@ int switchdev_bridge_port_offload(struct net_device *brport_dev,
if (err)
return err;
- return nbp_switchdev_add(p, ppid, extack);
+ err = nbp_switchdev_add(p, ppid, extack);
+ if (err)
+ return err;
+
+ err = nbp_switchdev_sync_objs(p, ctx, atomic_nb, blocking_nb, extack);
+ if (err)
+ goto out_switchdev_del;
+
+ return 0;
+
+out_switchdev_del:
+ nbp_switchdev_del(p, ppid);
+
+ return err;
}
EXPORT_SYMBOL_GPL(switchdev_bridge_port_offload);
int switchdev_bridge_port_unoffload(struct net_device *brport_dev,
- struct net_device *dev,
+ struct net_device *dev, const void *ctx,
+ struct notifier_block *atomic_nb,
+ struct notifier_block *blocking_nb,
struct netlink_ext_ack *extack)
{
struct netdev_phys_item_id ppid;
@@ -255,6 +333,8 @@ int switchdev_bridge_port_unoffload(struct net_device *brport_dev,
if (err)
return err;
+ nbp_switchdev_unsync_objs(p, ctx, atomic_nb, blocking_nb, extack);
+
nbp_switchdev_del(p, ppid);
return 0;
@@ -1884,7 +1884,6 @@ int br_vlan_replay(struct net_device *br_dev, struct net_device *dev,
return err;
}
-EXPORT_SYMBOL_GPL(br_vlan_replay);
/* check if v_curr can enter a range ending in range_end */
bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
@@ -167,8 +167,8 @@ static void dsa_port_clear_brport_flags(struct dsa_port *dp)
}
}
-static int dsa_port_switchdev_sync(struct dsa_port *dp,
- struct netlink_ext_ack *extack)
+static int dsa_port_switchdev_sync_attrs(struct dsa_port *dp,
+ struct netlink_ext_ack *extack)
{
struct net_device *brport_dev = dsa_port_to_bridge_port(dp);
struct net_device *br = dp->bridge_dev;
@@ -194,59 +194,6 @@ static int dsa_port_switchdev_sync(struct dsa_port *dp,
if (err && err != -EOPNOTSUPP)
return err;
- err = br_mdb_replay(br, brport_dev, dp, true,
- &dsa_slave_switchdev_blocking_notifier, extack);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- /* Forwarding and termination FDB entries on the port */
- err = br_fdb_replay(br, brport_dev, dp, true,
- &dsa_slave_switchdev_notifier);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- /* Termination FDB entries on the bridge itself */
- err = br_fdb_replay(br, br, dp, true, &dsa_slave_switchdev_notifier);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- err = br_vlan_replay(br, brport_dev, dp, true,
- &dsa_slave_switchdev_blocking_notifier, extack);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- return 0;
-}
-
-static int dsa_port_switchdev_unsync_objs(struct dsa_port *dp,
- struct net_device *br,
- struct netlink_ext_ack *extack)
-{
- struct net_device *brport_dev = dsa_port_to_bridge_port(dp);
- int err;
-
- /* Delete the switchdev objects left on this port */
- err = br_mdb_replay(br, brport_dev, dp, false,
- &dsa_slave_switchdev_blocking_notifier, extack);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- /* Forwarding and termination FDB entries on the port */
- err = br_fdb_replay(br, brport_dev, dp, false,
- &dsa_slave_switchdev_notifier);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- /* Termination FDB entries on the bridge itself */
- err = br_fdb_replay(br, br, dp, false, &dsa_slave_switchdev_notifier);
- if (err && err != -EOPNOTSUPP)
- return err;
-
- err = br_vlan_replay(br, brport_dev, dp, false,
- &dsa_slave_switchdev_blocking_notifier, extack);
- if (err && err != -EOPNOTSUPP)
- return err;
-
return 0;
}
@@ -307,18 +254,24 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
if (err)
goto out_rollback;
- err = switchdev_bridge_port_offload(brport_dev, dev, extack);
+ err = switchdev_bridge_port_offload(brport_dev, dev, dp,
+ &dsa_slave_switchdev_notifier,
+ &dsa_slave_switchdev_blocking_notifier,
+ extack);
if (err)
goto out_rollback_unbridge;
- err = dsa_port_switchdev_sync(dp, extack);
+ err = dsa_port_switchdev_sync_attrs(dp, extack);
if (err)
goto out_rollback_unoffload;
return 0;
out_rollback_unoffload:
- switchdev_bridge_port_unoffload(brport_dev, dev, extack);
+ switchdev_bridge_port_unoffload(brport_dev, dev, dp,
+ &dsa_slave_switchdev_notifier,
+ &dsa_slave_switchdev_blocking_notifier,
+ extack);
out_rollback_unbridge:
dsa_broadcast(DSA_NOTIFIER_BRIDGE_LEAVE, &info);
out_rollback:
@@ -331,13 +284,11 @@ int dsa_port_pre_bridge_leave(struct dsa_port *dp, struct net_device *br,
{
struct net_device *brport_dev = dsa_port_to_bridge_port(dp);
struct net_device *dev = dp->slave;
- int err;
-
- err = switchdev_bridge_port_unoffload(brport_dev, dev, extack);
- if (err)
- return err;
- return dsa_port_switchdev_unsync_objs(dp, br, extack);
+ return switchdev_bridge_port_unoffload(brport_dev, dev, dp,
+ &dsa_slave_switchdev_notifier,
+ &dsa_slave_switchdev_blocking_notifier,
+ extack);
}
void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)