diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c index 65486a90b526..004c42274e48 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c @@ -438,16 +438,6 @@ static int mlxsw_sp_fid_vni_op(struct mlxsw_sp *mlxsw_sp, u16 fid_index, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl); } -static int mlxsw_sp_fid_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index, - u16 vid, bool valid) -{ - enum mlxsw_reg_svfa_mt mt = MLXSW_REG_SVFA_MT_VID_TO_FID; - char svfa_pl[MLXSW_REG_SVFA_LEN]; - - mlxsw_reg_svfa_pack(svfa_pl, 0, mt, valid, fid_index, vid); - return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); -} - static int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index, u8 local_port, u16 vid, bool valid) { @@ -458,140 +448,6 @@ static int __mlxsw_sp_fid_port_vid_map(struct mlxsw_sp *mlxsw_sp, u16 fid_index, return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(svfa), svfa_pl); } -static int mlxsw_sp_fid_8021q_configure(struct mlxsw_sp_fid *fid) -{ - struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; - struct mlxsw_sp_fid_8021q *fid_8021q; - int err; - - err = mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, fid->fid_index, true); - if (err) - return err; - - fid_8021q = mlxsw_sp_fid_8021q_fid(fid); - err = mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid, - true); - if (err) - goto err_fid_map; - - return 0; - -err_fid_map: - mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false); - return err; -} - -static void mlxsw_sp_fid_8021q_deconfigure(struct mlxsw_sp_fid *fid) -{ - struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp; - struct mlxsw_sp_fid_8021q *fid_8021q; - - fid_8021q = mlxsw_sp_fid_8021q_fid(fid); - mlxsw_sp_fid_vid_map(mlxsw_sp, fid->fid_index, fid_8021q->vid, false); - mlxsw_sp_fid_op(mlxsw_sp, fid->fid_index, 0, false); -} - -static int mlxsw_sp_fid_8021q_index_alloc(struct mlxsw_sp_fid *fid, - const void *arg, u16 *p_fid_index) -{ - struct mlxsw_sp_fid_family *fid_family = fid->fid_family; - u16 vid = *(u16 *) arg; - - /* Use 1:1 mapping for simplicity although not a must */ - if (vid < fid_family->start_index || vid > fid_family->end_index) - return -EINVAL; - *p_fid_index = vid; - - return 0; -} - -static bool -mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) -{ - u16 vid = *(u16 *) arg; - - return mlxsw_sp_fid_8021q_fid(fid)->vid == vid; -} - -static u16 mlxsw_sp_fid_8021q_flood_index(const struct mlxsw_sp_fid *fid) -{ - return fid->fid_index; -} - -static int mlxsw_sp_fid_8021q_port_vid_map(struct mlxsw_sp_fid *fid, - struct mlxsw_sp_port *mlxsw_sp_port, - u16 vid) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u8 local_port = mlxsw_sp_port->local_port; - - /* In case there are no {Port, VID} => FID mappings on the port, - * we can use the global VID => FID mapping we created when the - * FID was configured. - */ - if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0) - return 0; - return __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port, - vid, true); -} - -static void -mlxsw_sp_fid_8021q_port_vid_unmap(struct mlxsw_sp_fid *fid, - struct mlxsw_sp_port *mlxsw_sp_port, u16 vid) -{ - struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - u8 local_port = mlxsw_sp_port->local_port; - - if (mlxsw_sp->fid_core->port_fid_mappings[local_port] == 0) - return; - __mlxsw_sp_fid_port_vid_map(mlxsw_sp, fid->fid_index, local_port, vid, - false); -} - -static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_ops = { - .setup = mlxsw_sp_fid_8021q_setup, - .configure = mlxsw_sp_fid_8021q_configure, - .deconfigure = mlxsw_sp_fid_8021q_deconfigure, - .index_alloc = mlxsw_sp_fid_8021q_index_alloc, - .compare = mlxsw_sp_fid_8021q_compare, - .flood_index = mlxsw_sp_fid_8021q_flood_index, - .port_vid_map = mlxsw_sp_fid_8021q_port_vid_map, - .port_vid_unmap = mlxsw_sp_fid_8021q_port_vid_unmap, -}; - -static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021q_flood_tables[] = { - { - .packet_type = MLXSW_SP_FLOOD_TYPE_UC, - .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, - .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, - .table_index = 0, - }, - { - .packet_type = MLXSW_SP_FLOOD_TYPE_MC, - .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, - .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, - .table_index = 1, - }, - { - .packet_type = MLXSW_SP_FLOOD_TYPE_BC, - .bridge_type = MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID, - .table_type = MLXSW_REG_SFGC_TABLE_TYPE_FID_OFFSET, - .table_index = 2, - }, -}; - -/* Range and flood configuration must match mlxsw_config_profile */ -static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_family = { - .type = MLXSW_SP_FID_TYPE_8021Q, - .fid_size = sizeof(struct mlxsw_sp_fid_8021q), - .start_index = 1, - .end_index = VLAN_VID_MASK, - .flood_tables = mlxsw_sp_fid_8021q_flood_tables, - .nr_flood_tables = ARRAY_SIZE(mlxsw_sp_fid_8021q_flood_tables), - .rif_type = MLXSW_SP_RIF_TYPE_VLAN, - .ops = &mlxsw_sp_fid_8021q_ops, -}; - static struct mlxsw_sp_fid_8021d * mlxsw_sp_fid_8021d_fid(const struct mlxsw_sp_fid *fid) { @@ -846,6 +702,14 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = { .lag_vid_valid = 1, }; +static bool +mlxsw_sp_fid_8021q_compare(const struct mlxsw_sp_fid *fid, const void *arg) +{ + u16 vid = *(u16 *) arg; + + return mlxsw_sp_fid_8021q_fid(fid)->vid == vid; +} + static void mlxsw_sp_fid_8021q_fdb_clear_offload(const struct mlxsw_sp_fid *fid, const struct net_device *nve_dev) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 85f80cac5fe0..97b7e6ebd9fa 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -7475,113 +7475,6 @@ u8 mlxsw_sp_router_port(const struct mlxsw_sp *mlxsw_sp) return mlxsw_core_max_ports(mlxsw_sp->core) + 1; } -static int mlxsw_sp_rif_vlan_configure(struct mlxsw_sp_rif *rif) -{ - struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; - u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); - int err; - - err = mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, true); - if (err) - return err; - - err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, - mlxsw_sp_router_port(mlxsw_sp), true); - if (err) - goto err_fid_mc_flood_set; - - err = mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, - mlxsw_sp_router_port(mlxsw_sp), true); - if (err) - goto err_fid_bc_flood_set; - - err = mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, - mlxsw_sp_fid_index(rif->fid), true); - if (err) - goto err_rif_fdb_op; - - mlxsw_sp_fid_rif_set(rif->fid, rif); - return 0; - -err_rif_fdb_op: - mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, - mlxsw_sp_router_port(mlxsw_sp), false); -err_fid_bc_flood_set: - mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, - mlxsw_sp_router_port(mlxsw_sp), false); -err_fid_mc_flood_set: - mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false); - return err; -} - -static void mlxsw_sp_rif_vlan_deconfigure(struct mlxsw_sp_rif *rif) -{ - u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); - struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; - struct mlxsw_sp_fid *fid = rif->fid; - - mlxsw_sp_fid_rif_set(fid, NULL); - mlxsw_sp_rif_fdb_op(rif->mlxsw_sp, rif->dev->dev_addr, - mlxsw_sp_fid_index(fid), false); - mlxsw_sp_rif_macvlan_flush(rif); - mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_BC, - mlxsw_sp_router_port(mlxsw_sp), false); - mlxsw_sp_fid_flood_set(rif->fid, MLXSW_SP_FLOOD_TYPE_MC, - mlxsw_sp_router_port(mlxsw_sp), false); - mlxsw_sp_rif_vlan_fid_op(rif, MLXSW_REG_RITR_VLAN_IF, vid, false); -} - -static struct mlxsw_sp_fid * -mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, - struct netlink_ext_ack *extack) -{ - struct net_device *br_dev = rif->dev; - u16 vid; - int err; - - if (is_vlan_dev(rif->dev)) { - vid = vlan_dev_vlan_id(rif->dev); - br_dev = vlan_dev_real_dev(rif->dev); - if (WARN_ON(!netif_is_bridge_master(br_dev))) - return ERR_PTR(-EINVAL); - } else { - err = br_vlan_get_pvid(rif->dev, &vid); - if (err < 0 || !vid) { - NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID"); - return ERR_PTR(-EINVAL); - } - } - - return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid); -} - -static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) -{ - u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); - struct switchdev_notifier_fdb_info info; - struct net_device *br_dev; - struct net_device *dev; - - br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev; - dev = br_fdb_find_port(br_dev, mac, vid); - if (!dev) - return; - - info.addr = mac; - info.vid = vid; - call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info, - NULL); -} - -static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_ops = { - .type = MLXSW_SP_RIF_TYPE_VLAN, - .rif_size = sizeof(struct mlxsw_sp_rif), - .configure = mlxsw_sp_rif_vlan_configure, - .deconfigure = mlxsw_sp_rif_vlan_deconfigure, - .fid_get = mlxsw_sp_rif_vlan_fid_get, - .fdb_del = mlxsw_sp_rif_vlan_fdb_del, -}; - static int mlxsw_sp_rif_fid_configure(struct mlxsw_sp_rif *rif) { struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; @@ -7670,6 +7563,48 @@ static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = { .fdb_del = mlxsw_sp_rif_fid_fdb_del, }; +static struct mlxsw_sp_fid * +mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif, + struct netlink_ext_ack *extack) +{ + struct net_device *br_dev = rif->dev; + u16 vid; + int err; + + if (is_vlan_dev(rif->dev)) { + vid = vlan_dev_vlan_id(rif->dev); + br_dev = vlan_dev_real_dev(rif->dev); + if (WARN_ON(!netif_is_bridge_master(br_dev))) + return ERR_PTR(-EINVAL); + } else { + err = br_vlan_get_pvid(rif->dev, &vid); + if (err < 0 || !vid) { + NL_SET_ERR_MSG_MOD(extack, "Couldn't determine bridge PVID"); + return ERR_PTR(-EINVAL); + } + } + + return mlxsw_sp_fid_8021q_get(rif->mlxsw_sp, vid); +} + +static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac) +{ + u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid); + struct switchdev_notifier_fdb_info info; + struct net_device *br_dev; + struct net_device *dev; + + br_dev = is_vlan_dev(rif->dev) ? vlan_dev_real_dev(rif->dev) : rif->dev; + dev = br_fdb_find_port(br_dev, mac, vid); + if (!dev) + return; + + info.addr = mac; + info.vid = vid; + call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE, dev, &info.info, + NULL); +} + static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_vlan_emu_ops = { .type = MLXSW_SP_RIF_TYPE_VLAN, .rif_size = sizeof(struct mlxsw_sp_rif),