提交 73b433e8 编写于 作者: N Nogah Frankel 提交者: David S. Miller

mlxsw: spectrum_switchdev: Attach mid id allocation to HW write

Attach mid getting and releasing mid id to the HW write / remove, and add
a flag to indicate whether the mid is in the HW. It is done because mid id
is also HW index to this mid.
This change allows adding in the following patches the ability to have a
mid in the mdb cache but not in the HW. It will be useful for being able
to disable the multicast.
It means that the mdb is being written / delete to the HW in the mid
allocation / removing function, not after them.
Signed-off-by: NNogah Frankel <nogahf@mellanox.com>
Signed-off-by: NJiri Pirko <jiri@mellanox.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 5f9abc59
...@@ -94,6 +94,7 @@ struct mlxsw_sp_mid { ...@@ -94,6 +94,7 @@ struct mlxsw_sp_mid {
unsigned char addr[ETH_ALEN]; unsigned char addr[ETH_ALEN];
u16 fid; u16 fid;
u16 mid; u16 mid;
bool in_hw;
unsigned long *ports_in_mid; /* bits array */ unsigned long *ports_in_mid; /* bits array */
}; };
......
...@@ -1260,6 +1260,42 @@ mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device, ...@@ -1260,6 +1260,42 @@ mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
return NULL; return NULL;
} }
static bool
mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mid *mid)
{
u16 mid_idx;
int err;
mid_idx = find_first_zero_bit(mlxsw_sp->bridge->mids_bitmap,
MLXSW_SP_MID_MAX);
if (mid_idx == MLXSW_SP_MID_MAX)
return false;
mid->mid = mid_idx;
err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx);
if (err)
return false;
err = mlxsw_sp_port_mdb_op(mlxsw_sp, mid->addr, mid->fid, mid_idx,
true);
if (err)
return false;
set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
mid->in_hw = true;
return true;
}
static int mlxsw_sp_mc_remove_mdb_entry(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mid *mid)
{
clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
mid->in_hw = false;
return mlxsw_sp_port_mdb_op(mlxsw_sp, mid->addr, mid->fid, mid->mid,
false);
}
static struct static struct
mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_bridge_device *bridge_device, struct mlxsw_sp_bridge_device *bridge_device,
...@@ -1268,12 +1304,6 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, ...@@ -1268,12 +1304,6 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_mid *mid; struct mlxsw_sp_mid *mid;
size_t alloc_size; size_t alloc_size;
u16 mid_idx;
mid_idx = find_first_zero_bit(mlxsw_sp->bridge->mids_bitmap,
MLXSW_SP_MID_MAX);
if (mid_idx == MLXSW_SP_MID_MAX)
return NULL;
mid = kzalloc(sizeof(*mid), GFP_KERNEL); mid = kzalloc(sizeof(*mid), GFP_KERNEL);
if (!mid) if (!mid)
...@@ -1281,36 +1311,43 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp, ...@@ -1281,36 +1311,43 @@ mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
alloc_size = sizeof(unsigned long) * alloc_size = sizeof(unsigned long) *
BITS_TO_LONGS(mlxsw_core_max_ports(mlxsw_sp->core)); BITS_TO_LONGS(mlxsw_core_max_ports(mlxsw_sp->core));
mid->ports_in_mid = kzalloc(alloc_size, GFP_KERNEL); mid->ports_in_mid = kzalloc(alloc_size, GFP_KERNEL);
if (!mid->ports_in_mid) { if (!mid->ports_in_mid)
kfree(mid); goto err_ports_in_mid_alloc;
return NULL;
}
set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
ether_addr_copy(mid->addr, addr); ether_addr_copy(mid->addr, addr);
mid->fid = fid; mid->fid = fid;
mid->mid = mid_idx; mid->in_hw = false;
if (!mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid))
goto err_write_mdb_entry;
list_add_tail(&mid->list, &bridge_device->mids_list); list_add_tail(&mid->list, &bridge_device->mids_list);
return mid; return mid;
err_write_mdb_entry:
kfree(mid->ports_in_mid);
err_ports_in_mid_alloc:
kfree(mid);
return NULL;
} }
static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_mid *mid) struct mlxsw_sp_mid *mid)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
int err = 0;
clear_bit(mlxsw_sp_port->local_port, mid->ports_in_mid); clear_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
if (bitmap_empty(mid->ports_in_mid, if (bitmap_empty(mid->ports_in_mid,
mlxsw_core_max_ports(mlxsw_sp->core))) { mlxsw_core_max_ports(mlxsw_sp->core))) {
err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
list_del(&mid->list); list_del(&mid->list);
clear_bit(mid->mid, mlxsw_sp->bridge->mids_bitmap);
kfree(mid->ports_in_mid); kfree(mid->ports_in_mid);
kfree(mid); kfree(mid);
return 1;
} }
return 0; return err;
} }
static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
...@@ -1324,7 +1361,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1324,7 +1361,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_bridge_device *bridge_device; struct mlxsw_sp_bridge_device *bridge_device;
struct mlxsw_sp_bridge_port *bridge_port; struct mlxsw_sp_bridge_port *bridge_port;
struct mlxsw_sp_mid *mid; struct mlxsw_sp_mid *mid;
bool is_new_mid = false;
u16 fid_index; u16 fid_index;
int err = 0; int err = 0;
...@@ -1352,8 +1388,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1352,8 +1388,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
netdev_err(dev, "Unable to allocate MC group\n"); netdev_err(dev, "Unable to allocate MC group\n");
return -ENOMEM; return -ENOMEM;
} }
is_new_mid = true;
mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid->mid);
} }
set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid); set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
...@@ -1363,15 +1397,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1363,15 +1397,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
goto err_out; goto err_out;
} }
if (is_new_mid) {
err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid_index,
mid->mid, true);
if (err) {
netdev_err(dev, "Unable to set MC SFD\n");
goto err_out;
}
}
return 0; return 0;
err_out: err_out:
...@@ -1481,12 +1506,9 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -1481,12 +1506,9 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
netdev_err(dev, "Unable to remove port from SMID\n"); netdev_err(dev, "Unable to remove port from SMID\n");
mid_idx = mid->mid; mid_idx = mid->mid;
if (mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid)) { err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb->addr, fid_index, if (err)
mid_idx, false); netdev_err(dev, "Unable to remove MC SFD\n");
if (err)
netdev_err(dev, "Unable to remove MC SFD\n");
}
return err; return err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册