All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6
@ 2022-06-29  9:39 Ido Schimmel
  2022-06-29  9:39 ` [PATCH net-next 01/10] mlxsw: Align PGT index to legacy bridge model Ido Schimmel
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

This is the fifth part of the conversion of mlxsw to the unified bridge
model.

The previous part that was merged in commit d521bc0a0f7c ("Merge branch
'mlxsw-unified-bridge-conversion-part-4-6'") converted the flooding code
to use the new APIs of the unified bridge model. As part of this
conversion, the flooding code started accessing the port group table
(PGT) directly in order to allocate MID indexes and configure the ports
via which a packet needs to be replicated.

MDB entries in the device also make use of the PGT table, but the
related code has its own PGT allocator and does not make use of the
common core that was added in the previous patchset. This patchset
converts the MDB code to use the common PGT code.

The first nine patches prepare the MDB code for the conversion that is
performed by the last patch.

Amit Cohen (10):
  mlxsw: Align PGT index to legacy bridge model
  mlxsw: spectrum_switchdev: Rename MID structure
  mlxsw: spectrum_switchdev: Rename MIDs list
  mlxsw: spectrum_switchdev: Save MAC and FID as a key in 'struct
    mlxsw_sp_mdb_entry'
  mlxsw: spectrum_switchdev: Add support for maintaining hash table of
    MDB entries
  mlxsw: spectrum_switchdev: Add support for maintaining list of ports
    per MDB entry
  mlxsw: spectrum_switchdev: Implement mlxsw_sp_mc_mdb_entry_{init,
    fini}()
  mlxsw: spectrum_switchdev: Add support for getting and putting MDB
    entry
  mlxsw: spectrum_switchdev: Flush port from MDB entries according to
    FID index
  mlxsw: spectrum_switchdev: Convert MDB code to use PGT APIs

 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  10 +-
 .../ethernet/mellanox/mlxsw/spectrum_pgt.c    |  16 +-
 .../mellanox/mlxsw/spectrum_switchdev.c       | 697 +++++++++++-------
 3 files changed, 455 insertions(+), 268 deletions(-)

-- 
2.36.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH net-next 01/10] mlxsw: Align PGT index to legacy bridge model
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
@ 2022-06-29  9:39 ` Ido Schimmel
  2022-06-29  9:39 ` [PATCH net-next 02/10] mlxsw: spectrum_switchdev: Rename MID structure Ido Schimmel
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

FID code reserves about 15K entries in PGT table for flooding. These
entries are just allocated and are not used yet because the code that uses
them is skipped now.

The next patches will convert MDB code to use PGT APIs. The allocation of
indexes for multicast is done after FID code reserves 15K entries.
Currently, legacy bridge model is used and firmware manages PGT table. That
means that the indexes which are allocated using PGT API are too high when
legacy bridge model is used. To not exceed firmware limitation for MDB
entries, add an API that returns the correct 'mid_index', based on bridge
model. For legacy model, subtract the number of flood entries from PGT
index. Use it to write the correct MID to SMID register. This API will be
used also from MDB code in the next patches.

PGT should not be aware of MDB and FID different usage, this API is
temporary and will be removed once unified bridge model will be used.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.h   |  1 +
 .../net/ethernet/mellanox/mlxsw/spectrum_pgt.c   | 16 +++++++++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index b128692611d9..b7709e759080 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -1485,6 +1485,7 @@ void mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
 				 u16 count);
 int mlxsw_sp_pgt_entry_port_set(struct mlxsw_sp *mlxsw_sp, u16 mid,
 				u16 smpe, u16 local_port, bool member);
+u16 mlxsw_sp_pgt_index_to_mid(const struct mlxsw_sp *mlxsw_sp, u16 pgt_index);
 int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp);
 void mlxsw_sp_pgt_fini(struct mlxsw_sp *mlxsw_sp);
 
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
index 3b7265b539b2..e6bbe08ef379 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
@@ -182,6 +182,16 @@ static void mlxsw_sp_pgt_entry_put(struct mlxsw_sp_pgt *pgt, u16 mid)
 		mlxsw_sp_pgt_entry_destroy(pgt, pgt_entry);
 }
 
+#define MLXSW_SP_FID_PGT_FLOOD_ENTRIES	15354 /* Reserved for flooding. */
+
+u16 mlxsw_sp_pgt_index_to_mid(const struct mlxsw_sp *mlxsw_sp, u16 pgt_index)
+{
+	if (mlxsw_sp->ubridge)
+		return pgt_index;
+
+	return pgt_index - MLXSW_SP_FID_PGT_FLOOD_ENTRIES;
+}
+
 static void mlxsw_sp_pgt_smid2_port_set(char *smid2_pl, u16 local_port,
 					bool member)
 {
@@ -196,7 +206,7 @@ mlxsw_sp_pgt_entry_port_write(struct mlxsw_sp *mlxsw_sp,
 {
 	bool smpe_index_valid;
 	char *smid2_pl;
-	u16 smpe;
+	u16 smpe, mid;
 	int err;
 
 	smid2_pl = kmalloc(MLXSW_REG_SMID2_LEN, GFP_KERNEL);
@@ -206,9 +216,9 @@ mlxsw_sp_pgt_entry_port_write(struct mlxsw_sp *mlxsw_sp,
 	smpe_index_valid = mlxsw_sp->ubridge ? mlxsw_sp->pgt->smpe_index_valid :
 			   false;
 	smpe = mlxsw_sp->ubridge ? pgt_entry->smpe_index : 0;
+	mid = mlxsw_sp_pgt_index_to_mid(mlxsw_sp, pgt_entry->index);
 
-	mlxsw_reg_smid2_pack(smid2_pl, pgt_entry->index, 0, 0, smpe_index_valid,
-			     smpe);
+	mlxsw_reg_smid2_pack(smid2_pl, mid, 0, 0, smpe_index_valid, smpe);
 
 	mlxsw_sp_pgt_smid2_port_set(smid2_pl, local_port, member);
 	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid2), smid2_pl);
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 02/10] mlxsw: spectrum_switchdev: Rename MID structure
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
  2022-06-29  9:39 ` [PATCH net-next 01/10] mlxsw: Align PGT index to legacy bridge model Ido Schimmel
@ 2022-06-29  9:39 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 03/10] mlxsw: spectrum_switchdev: Rename MIDs list Ido Schimmel
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:39 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Currently the structure which represents MDB entry is called
'struct mlxsw_sp_mid'. This name is not accurate as a MID entry stores a
bitmap of ports to which a packet needs to be replicated and a MDB entry
stores the mapping from {MAC, FID} to PGT index (MID).

Rename the structure to 'struct mlxsw_sp_mdb_entry'. The structure
'mlxsw_sp_mid' is defined as part of spectrum.h. The only file which
uses it is spectrum_switchdev.c, so there is no reason to expose it to
other files. Move the definition to spectrum_switchdev.c.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |   9 -
 .../mellanox/mlxsw/spectrum_switchdev.c       | 179 ++++++++++--------
 2 files changed, 97 insertions(+), 91 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index b7709e759080..8de3bdcdf143 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -112,15 +112,6 @@ enum mlxsw_sp_nve_type {
 	MLXSW_SP_NVE_TYPE_VXLAN,
 };
 
-struct mlxsw_sp_mid {
-	struct list_head list;
-	unsigned char addr[ETH_ALEN];
-	u16 fid;
-	u16 mid;
-	bool in_hw;
-	unsigned long *ports_in_mid; /* bits array */
-};
-
 struct mlxsw_sp_sb;
 struct mlxsw_sp_bridge;
 struct mlxsw_sp_router;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index e153b6f2783a..70b48b922520 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -102,6 +102,15 @@ struct mlxsw_sp_switchdev_ops {
 	void (*init)(struct mlxsw_sp *mlxsw_sp);
 };
 
+struct mlxsw_sp_mdb_entry {
+	struct list_head list;
+	unsigned char addr[ETH_ALEN];
+	u16 fid;
+	u16 mid;
+	bool in_hw;
+	unsigned long *ports_in_mid; /* bits array */
+};
+
 static int
 mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 			       struct mlxsw_sp_bridge_port *bridge_port,
@@ -971,10 +980,10 @@ mlxsw_sp_bridge_mrouter_update_mdb(struct mlxsw_sp *mlxsw_sp,
 				   struct mlxsw_sp_bridge_device *bridge_device,
 				   bool add)
 {
-	struct mlxsw_sp_mid *mid;
+	struct mlxsw_sp_mdb_entry *mdb_entry;
 
-	list_for_each_entry(mid, &bridge_device->mids_list, list)
-		mlxsw_sp_smid_router_port_set(mlxsw_sp, mid->mid, add);
+	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list)
+		mlxsw_sp_smid_router_port_set(mlxsw_sp, mdb_entry->mid, add);
 }
 
 static int
@@ -1696,16 +1705,16 @@ static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	return err;
 }
 
-static struct
-mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
-				const unsigned char *addr,
-				u16 fid)
+static struct mlxsw_sp_mdb_entry *
+__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
+		  const unsigned char *addr, u16 fid)
 {
-	struct mlxsw_sp_mid *mid;
+	struct mlxsw_sp_mdb_entry *mdb_entry;
 
-	list_for_each_entry(mid, &bridge_device->mids_list, list) {
-		if (ether_addr_equal(mid->addr, addr) && mid->fid == fid)
-			return mid;
+	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list) {
+		if (ether_addr_equal(mdb_entry->addr, addr) &&
+		    mdb_entry->fid == fid)
+			return mdb_entry;
 	}
 	return NULL;
 }
@@ -1753,7 +1762,7 @@ mlxsw_sp_mc_get_mrouters_bitmap(struct mlxsw_sp_ports_bitmap *flood_bm,
 
 static int
 mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
-			    struct mlxsw_sp_mid *mid,
+			    struct mlxsw_sp_mdb_entry *mdb_entry,
 			    struct mlxsw_sp_bridge_device *bridge_device)
 {
 	struct mlxsw_sp_ports_bitmap flood_bitmap;
@@ -1769,91 +1778,91 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 	if (err)
 		return err;
 
-	bitmap_copy(flood_bitmap.bitmap, mid->ports_in_mid, flood_bitmap.nbits);
+	bitmap_copy(flood_bitmap.bitmap, mdb_entry->ports_in_mid,
+		    flood_bitmap.nbits);
 	mlxsw_sp_mc_get_mrouters_bitmap(&flood_bitmap, bridge_device, mlxsw_sp);
 
-	mid->mid = mid_idx;
+	mdb_entry->mid = mid_idx;
 	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, &flood_bitmap,
 					    bridge_device->mrouter);
 	mlxsw_sp_port_bitmap_fini(&flood_bitmap);
 	if (err)
 		return err;
 
-	err = mlxsw_sp_port_mdb_op(mlxsw_sp, mid->addr, mid->fid, mid_idx,
-				   true);
+	err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->addr, mdb_entry->fid,
+				   mid_idx, true);
 	if (err)
 		return err;
 
 	set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
-	mid->in_hw = true;
+	mdb_entry->in_hw = true;
 	return 0;
 }
 
 static int mlxsw_sp_mc_remove_mdb_entry(struct mlxsw_sp *mlxsw_sp,
-					struct mlxsw_sp_mid *mid)
+					struct mlxsw_sp_mdb_entry *mdb_entry)
 {
-	if (!mid->in_hw)
+	if (!mdb_entry->in_hw)
 		return 0;
 
-	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);
+	clear_bit(mdb_entry->mid, mlxsw_sp->bridge->mids_bitmap);
+	mdb_entry->in_hw = false;
+	return mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->addr, mdb_entry->fid,
+				    mdb_entry->mid, false);
 }
 
-static struct
-mlxsw_sp_mid *__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
-				  struct mlxsw_sp_bridge_device *bridge_device,
-				  const unsigned char *addr,
-				  u16 fid)
+static struct mlxsw_sp_mdb_entry *
+__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
+		    struct mlxsw_sp_bridge_device *bridge_device,
+		    const unsigned char *addr, u16 fid)
 {
-	struct mlxsw_sp_mid *mid;
+	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
+	struct mlxsw_sp_mdb_entry *mdb_entry;
 	int err;
 
-	mid = kzalloc(sizeof(*mid), GFP_KERNEL);
-	if (!mid)
+	mdb_entry = kzalloc(sizeof(*mdb_entry), GFP_KERNEL);
+	if (!mdb_entry)
 		return NULL;
 
-	mid->ports_in_mid = bitmap_zalloc(mlxsw_core_max_ports(mlxsw_sp->core),
-					  GFP_KERNEL);
-	if (!mid->ports_in_mid)
+	mdb_entry->ports_in_mid = bitmap_zalloc(max_ports, GFP_KERNEL);
+	if (!mdb_entry->ports_in_mid)
 		goto err_ports_in_mid_alloc;
 
-	ether_addr_copy(mid->addr, addr);
-	mid->fid = fid;
-	mid->in_hw = false;
+	ether_addr_copy(mdb_entry->addr, addr);
+	mdb_entry->fid = fid;
+	mdb_entry->in_hw = false;
 
 	if (!bridge_device->multicast_enabled)
 		goto out;
 
-	err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid, bridge_device);
+	err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mdb_entry, bridge_device);
 	if (err)
 		goto err_write_mdb_entry;
 
 out:
-	list_add_tail(&mid->list, &bridge_device->mids_list);
-	return mid;
+	list_add_tail(&mdb_entry->list, &bridge_device->mids_list);
+	return mdb_entry;
 
 err_write_mdb_entry:
-	bitmap_free(mid->ports_in_mid);
+	bitmap_free(mdb_entry->ports_in_mid);
 err_ports_in_mid_alloc:
-	kfree(mid);
+	kfree(mdb_entry);
 	return NULL;
 }
 
 static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
-					 struct mlxsw_sp_mid *mid)
+					 struct mlxsw_sp_mdb_entry *mdb_entry)
 {
 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 	int err = 0;
 
-	clear_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
-	if (bitmap_empty(mid->ports_in_mid,
+	clear_bit(mlxsw_sp_port->local_port, mdb_entry->ports_in_mid);
+	if (bitmap_empty(mdb_entry->ports_in_mid,
 			 mlxsw_core_max_ports(mlxsw_sp->core))) {
-		err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
-		list_del(&mid->list);
-		bitmap_free(mid->ports_in_mid);
-		kfree(mid);
+		err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mdb_entry);
+		list_del(&mdb_entry->list);
+		bitmap_free(mdb_entry->ports_in_mid);
+		kfree(mdb_entry);
 	}
 	return err;
 }
@@ -1867,7 +1876,7 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct net_device *dev = mlxsw_sp_port->dev;
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_bridge_port *bridge_port;
-	struct mlxsw_sp_mid *mid;
+	struct mlxsw_sp_mdb_entry *mdb_entry;
 	u16 fid_index;
 	int err = 0;
 
@@ -1884,16 +1893,16 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
 
-	mid = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
-	if (!mid) {
-		mid = __mlxsw_sp_mc_alloc(mlxsw_sp, bridge_device, mdb->addr,
-					  fid_index);
-		if (!mid) {
+	mdb_entry = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
+	if (!mdb_entry) {
+		mdb_entry = __mlxsw_sp_mc_alloc(mlxsw_sp, bridge_device,
+						mdb->addr, fid_index);
+		if (!mdb_entry) {
 			netdev_err(dev, "Unable to allocate MC group\n");
 			return -ENOMEM;
 		}
 	}
-	set_bit(mlxsw_sp_port->local_port, mid->ports_in_mid);
+	set_bit(mlxsw_sp_port->local_port, mdb_entry->ports_in_mid);
 
 	if (!bridge_device->multicast_enabled)
 		return 0;
@@ -1901,7 +1910,7 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	if (bridge_port->mrouter)
 		return 0;
 
-	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, true);
+	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid, true);
 	if (err) {
 		netdev_err(dev, "Unable to set SMID\n");
 		goto err_out;
@@ -1910,7 +1919,7 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 
 err_out:
-	mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
+	mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mdb_entry);
 	return err;
 }
 
@@ -1919,15 +1928,15 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
 				   struct mlxsw_sp_bridge_device *bridge_device,
 				   bool mc_enabled)
 {
-	struct mlxsw_sp_mid *mid;
+	struct mlxsw_sp_mdb_entry *mdb_entry;
 	int err;
 
-	list_for_each_entry(mid, &bridge_device->mids_list, list) {
+	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list) {
 		if (mc_enabled)
-			err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid,
+			err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mdb_entry,
 							  bridge_device);
 		else
-			err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
+			err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mdb_entry);
 
 		if (err)
 			goto err_mdb_entry_update;
@@ -1936,12 +1945,12 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
 	return 0;
 
 err_mdb_entry_update:
-	list_for_each_entry_continue_reverse(mid, &bridge_device->mids_list,
-					     list) {
+	list_for_each_entry_continue_reverse(mdb_entry,
+					     &bridge_device->mids_list, list) {
 		if (mc_enabled)
-			mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mid);
+			mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mdb_entry);
 		else
-			mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mid,
+			mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mdb_entry,
 						    bridge_device);
 	}
 	return err;
@@ -1953,13 +1962,15 @@ mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,
 				 bool add)
 {
 	struct mlxsw_sp_bridge_device *bridge_device;
-	struct mlxsw_sp_mid *mid;
+	struct mlxsw_sp_mdb_entry *mdb_entry;
 
 	bridge_device = bridge_port->bridge_device;
 
-	list_for_each_entry(mid, &bridge_device->mids_list, list) {
-		if (!test_bit(mlxsw_sp_port->local_port, mid->ports_in_mid))
-			mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, add);
+	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list) {
+		if (!test_bit(mlxsw_sp_port->local_port,
+			      mdb_entry->ports_in_mid))
+			mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid,
+					       add);
 	}
 }
 
@@ -2040,19 +2051,20 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
 static int
 __mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 			struct mlxsw_sp_bridge_port *bridge_port,
-			struct mlxsw_sp_mid *mid)
+			struct mlxsw_sp_mdb_entry *mdb_entry)
 {
 	struct net_device *dev = mlxsw_sp_port->dev;
 	int err;
 
 	if (bridge_port->bridge_device->multicast_enabled &&
 	    !bridge_port->mrouter) {
-		err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
+		err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid,
+					     false);
 		if (err)
 			netdev_err(dev, "Unable to remove port from SMID\n");
 	}
 
-	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mid);
+	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mdb_entry);
 	if (err)
 		netdev_err(dev, "Unable to remove MC SFD\n");
 
@@ -2068,7 +2080,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct net_device *dev = mlxsw_sp_port->dev;
 	struct mlxsw_sp_bridge_port *bridge_port;
-	struct mlxsw_sp_mid *mid;
+	struct mlxsw_sp_mdb_entry *mdb_entry;
 	u16 fid_index;
 
 	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
@@ -2084,13 +2096,13 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
 
-	mid = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
-	if (!mid) {
+	mdb_entry = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
+	if (!mdb_entry) {
 		netdev_err(dev, "Unable to remove port from MC DB\n");
 		return -EINVAL;
 	}
 
-	return __mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port, mid);
+	return __mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port, mdb_entry);
 }
 
 static void
@@ -2098,17 +2110,20 @@ mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
 			       struct mlxsw_sp_bridge_port *bridge_port)
 {
 	struct mlxsw_sp_bridge_device *bridge_device;
-	struct mlxsw_sp_mid *mid, *tmp;
+	struct mlxsw_sp_mdb_entry *mdb_entry, *tmp;
+	u16 local_port = mlxsw_sp_port->local_port;
 
 	bridge_device = bridge_port->bridge_device;
 
-	list_for_each_entry_safe(mid, tmp, &bridge_device->mids_list, list) {
-		if (test_bit(mlxsw_sp_port->local_port, mid->ports_in_mid)) {
+	list_for_each_entry_safe(mdb_entry, tmp, &bridge_device->mids_list,
+				 list) {
+		if (test_bit(local_port, mdb_entry->ports_in_mid)) {
 			__mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port,
-						mid);
+						mdb_entry);
 		} else if (bridge_device->multicast_enabled &&
 			   bridge_port->mrouter) {
-			mlxsw_sp_port_smid_set(mlxsw_sp_port, mid->mid, false);
+			mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid,
+					       false);
 		}
 	}
 }
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 03/10] mlxsw: spectrum_switchdev: Rename MIDs list
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
  2022-06-29  9:39 ` [PATCH net-next 01/10] mlxsw: Align PGT index to legacy bridge model Ido Schimmel
  2022-06-29  9:39 ` [PATCH net-next 02/10] mlxsw: spectrum_switchdev: Rename MID structure Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 04/10] mlxsw: spectrum_switchdev: Save MAC and FID as a key in 'struct mlxsw_sp_mdb_entry' Ido Schimmel
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Currently, the list which stores the MDB entries for a given bridge
instance is called 'mids_list'.

This name is not accurate as a MID entry stores a bitmap of ports to
which a packet needs to be replicated and a MDB entry stores the mapping
from {MAC, FID} to PGT index (MID)

Rename it to 'mdb_list'.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../mellanox/mlxsw/spectrum_switchdev.c       | 21 ++++++++++---------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 70b48b922520..bd182736f44d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -48,7 +48,7 @@ struct mlxsw_sp_bridge_device {
 	struct net_device *dev;
 	struct list_head list;
 	struct list_head ports_list;
-	struct list_head mids_list;
+	struct list_head mdb_list;
 	u8 vlan_enabled:1,
 	   multicast_enabled:1,
 	   mrouter:1;
@@ -263,7 +263,8 @@ mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge,
 	} else {
 		bridge_device->ops = bridge->bridge_8021d_ops;
 	}
-	INIT_LIST_HEAD(&bridge_device->mids_list);
+	INIT_LIST_HEAD(&bridge_device->mdb_list);
+
 	if (list_empty(&bridge->bridges_list))
 		mlxsw_sp_fdb_notify_work_schedule(bridge->mlxsw_sp, false);
 	list_add(&bridge_device->list, &bridge->bridges_list);
@@ -299,7 +300,7 @@ mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge,
 	if (bridge_device->vlan_enabled)
 		bridge->vlan_enabled_exists = false;
 	WARN_ON(!list_empty(&bridge_device->ports_list));
-	WARN_ON(!list_empty(&bridge_device->mids_list));
+	WARN_ON(!list_empty(&bridge_device->mdb_list));
 	kfree(bridge_device);
 }
 
@@ -982,7 +983,7 @@ mlxsw_sp_bridge_mrouter_update_mdb(struct mlxsw_sp *mlxsw_sp,
 {
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 
-	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list)
+	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list)
 		mlxsw_sp_smid_router_port_set(mlxsw_sp, mdb_entry->mid, add);
 }
 
@@ -1711,7 +1712,7 @@ __mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
 {
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 
-	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list) {
+	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
 		if (ether_addr_equal(mdb_entry->addr, addr) &&
 		    mdb_entry->fid == fid)
 			return mdb_entry;
@@ -1840,7 +1841,7 @@ __mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 		goto err_write_mdb_entry;
 
 out:
-	list_add_tail(&mdb_entry->list, &bridge_device->mids_list);
+	list_add_tail(&mdb_entry->list, &bridge_device->mdb_list);
 	return mdb_entry;
 
 err_write_mdb_entry:
@@ -1931,7 +1932,7 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 	int err;
 
-	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list) {
+	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
 		if (mc_enabled)
 			err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mdb_entry,
 							  bridge_device);
@@ -1946,7 +1947,7 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
 
 err_mdb_entry_update:
 	list_for_each_entry_continue_reverse(mdb_entry,
-					     &bridge_device->mids_list, list) {
+					     &bridge_device->mdb_list, list) {
 		if (mc_enabled)
 			mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mdb_entry);
 		else
@@ -1966,7 +1967,7 @@ mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	bridge_device = bridge_port->bridge_device;
 
-	list_for_each_entry(mdb_entry, &bridge_device->mids_list, list) {
+	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
 		if (!test_bit(mlxsw_sp_port->local_port,
 			      mdb_entry->ports_in_mid))
 			mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid,
@@ -2115,7 +2116,7 @@ mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	bridge_device = bridge_port->bridge_device;
 
-	list_for_each_entry_safe(mdb_entry, tmp, &bridge_device->mids_list,
+	list_for_each_entry_safe(mdb_entry, tmp, &bridge_device->mdb_list,
 				 list) {
 		if (test_bit(local_port, mdb_entry->ports_in_mid)) {
 			__mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port,
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 04/10] mlxsw: spectrum_switchdev: Save MAC and FID as a key in 'struct mlxsw_sp_mdb_entry'
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (2 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 03/10] mlxsw: spectrum_switchdev: Rename MIDs list Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 05/10] mlxsw: spectrum_switchdev: Add support for maintaining hash table of MDB entries Ido Schimmel
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

The next patch will add support for storing all the MDB entries in a hash
table. As a preparation, save the MAC address and the FID in a
separate structure. This structure will be used later as a key for the
hash table.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../mellanox/mlxsw/spectrum_switchdev.c       | 24 +++++++++++--------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index bd182736f44d..d1a1d55b0068 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -102,10 +102,14 @@ struct mlxsw_sp_switchdev_ops {
 	void (*init)(struct mlxsw_sp *mlxsw_sp);
 };
 
-struct mlxsw_sp_mdb_entry {
-	struct list_head list;
+struct mlxsw_sp_mdb_entry_key {
 	unsigned char addr[ETH_ALEN];
 	u16 fid;
+};
+
+struct mlxsw_sp_mdb_entry {
+	struct list_head list;
+	struct mlxsw_sp_mdb_entry_key key;
 	u16 mid;
 	bool in_hw;
 	unsigned long *ports_in_mid; /* bits array */
@@ -1713,8 +1717,8 @@ __mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 
 	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
-		if (ether_addr_equal(mdb_entry->addr, addr) &&
-		    mdb_entry->fid == fid)
+		if (ether_addr_equal(mdb_entry->key.addr, addr) &&
+		    mdb_entry->key.fid == fid)
 			return mdb_entry;
 	}
 	return NULL;
@@ -1790,8 +1794,8 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 	if (err)
 		return err;
 
-	err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->addr, mdb_entry->fid,
-				   mid_idx, true);
+	err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->key.addr,
+				   mdb_entry->key.fid, mid_idx, true);
 	if (err)
 		return err;
 
@@ -1808,8 +1812,8 @@ static int mlxsw_sp_mc_remove_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 
 	clear_bit(mdb_entry->mid, mlxsw_sp->bridge->mids_bitmap);
 	mdb_entry->in_hw = false;
-	return mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->addr, mdb_entry->fid,
-				    mdb_entry->mid, false);
+	return mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->key.addr,
+				    mdb_entry->key.fid, mdb_entry->mid, false);
 }
 
 static struct mlxsw_sp_mdb_entry *
@@ -1829,8 +1833,8 @@ __mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
 	if (!mdb_entry->ports_in_mid)
 		goto err_ports_in_mid_alloc;
 
-	ether_addr_copy(mdb_entry->addr, addr);
-	mdb_entry->fid = fid;
+	ether_addr_copy(mdb_entry->key.addr, addr);
+	mdb_entry->key.fid = fid;
 	mdb_entry->in_hw = false;
 
 	if (!bridge_device->multicast_enabled)
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 05/10] mlxsw: spectrum_switchdev: Add support for maintaining hash table of MDB entries
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (3 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 04/10] mlxsw: spectrum_switchdev: Save MAC and FID as a key in 'struct mlxsw_sp_mdb_entry' Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 06/10] mlxsw: spectrum_switchdev: Add support for maintaining list of ports per MDB entry Ido Schimmel
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Currently MDB entries are stored in a list as part of
'struct mlxsw_sp_bridge_device'. Storing them in a hash table in
addition to the list will allow finding a specific entry more efficiently.

Add support for the required hash table, the next patches will insert
and remove MDB entries from the table. The existing code which adds and
removes entries will be removed and replaced by new code in the next
patches, so there is no point to adjust the existing code.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_switchdev.c  | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index d1a1d55b0068..617ec3312fd8 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -49,6 +49,7 @@ struct mlxsw_sp_bridge_device {
 	struct list_head list;
 	struct list_head ports_list;
 	struct list_head mdb_list;
+	struct rhashtable mdb_ht;
 	u8 vlan_enabled:1,
 	   multicast_enabled:1,
 	   mrouter:1;
@@ -109,12 +110,19 @@ struct mlxsw_sp_mdb_entry_key {
 
 struct mlxsw_sp_mdb_entry {
 	struct list_head list;
+	struct rhash_head ht_node;
 	struct mlxsw_sp_mdb_entry_key key;
 	u16 mid;
 	bool in_hw;
 	unsigned long *ports_in_mid; /* bits array */
 };
 
+static const struct rhashtable_params mlxsw_sp_mdb_ht_params = {
+	.key_offset = offsetof(struct mlxsw_sp_mdb_entry, key),
+	.head_offset = offsetof(struct mlxsw_sp_mdb_entry, ht_node),
+	.key_len = sizeof(struct mlxsw_sp_mdb_entry_key),
+};
+
 static int
 mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 			       struct mlxsw_sp_bridge_port *bridge_port,
@@ -250,6 +258,10 @@ mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge,
 	if (!bridge_device)
 		return ERR_PTR(-ENOMEM);
 
+	err = rhashtable_init(&bridge_device->mdb_ht, &mlxsw_sp_mdb_ht_params);
+	if (err)
+		goto err_mdb_rhashtable_init;
+
 	bridge_device->dev = br_dev;
 	bridge_device->vlan_enabled = vlan_enabled;
 	bridge_device->multicast_enabled = br_multicast_enabled(br_dev);
@@ -287,6 +299,8 @@ mlxsw_sp_bridge_device_create(struct mlxsw_sp_bridge *bridge,
 	list_del(&bridge_device->list);
 	if (bridge_device->vlan_enabled)
 		bridge->vlan_enabled_exists = false;
+	rhashtable_destroy(&bridge_device->mdb_ht);
+err_mdb_rhashtable_init:
 	kfree(bridge_device);
 	return ERR_PTR(err);
 }
@@ -305,6 +319,7 @@ mlxsw_sp_bridge_device_destroy(struct mlxsw_sp_bridge *bridge,
 		bridge->vlan_enabled_exists = false;
 	WARN_ON(!list_empty(&bridge_device->ports_list));
 	WARN_ON(!list_empty(&bridge_device->mdb_list));
+	rhashtable_destroy(&bridge_device->mdb_ht);
 	kfree(bridge_device);
 }
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 06/10] mlxsw: spectrum_switchdev: Add support for maintaining list of ports per MDB entry
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (4 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 05/10] mlxsw: spectrum_switchdev: Add support for maintaining hash table of MDB entries Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 07/10] mlxsw: spectrum_switchdev: Implement mlxsw_sp_mc_mdb_entry_{init, fini}() Ido Schimmel
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

As part of converting MDB code to use PGT APIs, PGT code stores which ports
are mapped to each PGT entry. PGT code is not aware of the type of the port
(multicast router or not), as it is not relevant there.

To be able to release an MDB entry when the there are no ports which are
not multicast routers, the entry should be aware of the state of its
ports. Add support for maintaining list of ports per MDB entry.

Each port will hold a reference count as multiple MDB entries can use the
same hardware MDB entry. It occurs because MDB entries in the Linux bridge
are keyed according to their multicast IP, when these entries are notified
to device drivers via switchdev, the multicast IP is converted to a
multicast MAC. This conversion might cause collisions, for example,
ff0e::1 and ff0e:1234::1 are both mapped to the multicast MAC
33:33:00:00:00:01.

Multicast router port will take a reference once, and will be marked as
'mrouter', then when port in the list is multicast router and its
reference value is one, it means that the entry can be removed in case
that there are no other ports which are not multicast routers. For that,
maintain a counter per MDB entry to count ports in the list, which were
added to the multicast group, and not because they are multicast routers.
When this counter is zero, the entry can be removed.

Add mlxsw_sp_mdb_entry_port_{get,put}() for regular ports and
mlxsw_sp_mdb_entry_mrouter_port_{get,put}() for multicast router ports.
Call PGT API to add or remove port from PGT entry when port is first added
or removed, according to the reference counting.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../mellanox/mlxsw/spectrum_switchdev.c       | 153 ++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 617ec3312fd8..d1b0eddad504 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -113,10 +113,19 @@ struct mlxsw_sp_mdb_entry {
 	struct rhash_head ht_node;
 	struct mlxsw_sp_mdb_entry_key key;
 	u16 mid;
+	struct list_head ports_list;
+	u16 ports_count;
 	bool in_hw;
 	unsigned long *ports_in_mid; /* bits array */
 };
 
+struct mlxsw_sp_mdb_entry_port {
+	struct list_head list; /* Member of 'ports_list'. */
+	u16 local_port;
+	refcount_t refcount;
+	bool mrouter;
+};
+
 static const struct rhashtable_params mlxsw_sp_mdb_ht_params = {
 	.key_offset = offsetof(struct mlxsw_sp_mdb_entry, key),
 	.head_offset = offsetof(struct mlxsw_sp_mdb_entry, ht_node),
@@ -995,6 +1004,150 @@ static int mlxsw_sp_smid_router_port_set(struct mlxsw_sp *mlxsw_sp,
 	return err;
 }
 
+static struct mlxsw_sp_mdb_entry_port *
+mlxsw_sp_mdb_entry_port_lookup(struct mlxsw_sp_mdb_entry *mdb_entry,
+			       u16 local_port)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+
+	list_for_each_entry(mdb_entry_port, &mdb_entry->ports_list, list) {
+		if (mdb_entry_port->local_port == local_port)
+			return mdb_entry_port;
+	}
+
+	return NULL;
+}
+
+static __always_unused struct mlxsw_sp_mdb_entry_port *
+mlxsw_sp_mdb_entry_port_get(struct mlxsw_sp *mlxsw_sp,
+			    struct mlxsw_sp_mdb_entry *mdb_entry,
+			    u16 local_port)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+	int err;
+
+	mdb_entry_port = mlxsw_sp_mdb_entry_port_lookup(mdb_entry, local_port);
+	if (mdb_entry_port) {
+		if (mdb_entry_port->mrouter &&
+		    refcount_read(&mdb_entry_port->refcount) == 1)
+			mdb_entry->ports_count++;
+
+		refcount_inc(&mdb_entry_port->refcount);
+		return mdb_entry_port;
+	}
+
+	err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, mdb_entry->mid,
+					  mdb_entry->key.fid, local_port, true);
+	if (err)
+		return ERR_PTR(err);
+
+	mdb_entry_port = kzalloc(sizeof(*mdb_entry_port), GFP_KERNEL);
+	if (!mdb_entry_port) {
+		err = -ENOMEM;
+		goto err_mdb_entry_port_alloc;
+	}
+
+	mdb_entry_port->local_port = local_port;
+	refcount_set(&mdb_entry_port->refcount, 1);
+	list_add(&mdb_entry_port->list, &mdb_entry->ports_list);
+	mdb_entry->ports_count++;
+
+	return mdb_entry_port;
+
+err_mdb_entry_port_alloc:
+	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, mdb_entry->mid,
+				    mdb_entry->key.fid, local_port, false);
+	return ERR_PTR(err);
+}
+
+static __always_unused void
+mlxsw_sp_mdb_entry_port_put(struct mlxsw_sp *mlxsw_sp,
+			    struct mlxsw_sp_mdb_entry *mdb_entry,
+			    u16 local_port, bool force)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+
+	mdb_entry_port = mlxsw_sp_mdb_entry_port_lookup(mdb_entry, local_port);
+	if (!mdb_entry_port)
+		return;
+
+	if (!force && !refcount_dec_and_test(&mdb_entry_port->refcount)) {
+		if (mdb_entry_port->mrouter &&
+		    refcount_read(&mdb_entry_port->refcount) == 1)
+			mdb_entry->ports_count--;
+		return;
+	}
+
+	mdb_entry->ports_count--;
+	list_del(&mdb_entry_port->list);
+	kfree(mdb_entry_port);
+	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, mdb_entry->mid,
+				    mdb_entry->key.fid, local_port, false);
+}
+
+static __always_unused struct mlxsw_sp_mdb_entry_port *
+mlxsw_sp_mdb_entry_mrouter_port_get(struct mlxsw_sp *mlxsw_sp,
+				    struct mlxsw_sp_mdb_entry *mdb_entry,
+				    u16 local_port)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+	int err;
+
+	mdb_entry_port = mlxsw_sp_mdb_entry_port_lookup(mdb_entry, local_port);
+	if (mdb_entry_port) {
+		if (!mdb_entry_port->mrouter)
+			refcount_inc(&mdb_entry_port->refcount);
+		return mdb_entry_port;
+	}
+
+	err = mlxsw_sp_pgt_entry_port_set(mlxsw_sp, mdb_entry->mid,
+					  mdb_entry->key.fid, local_port, true);
+	if (err)
+		return ERR_PTR(err);
+
+	mdb_entry_port = kzalloc(sizeof(*mdb_entry_port), GFP_KERNEL);
+	if (!mdb_entry_port) {
+		err = -ENOMEM;
+		goto err_mdb_entry_port_alloc;
+	}
+
+	mdb_entry_port->local_port = local_port;
+	refcount_set(&mdb_entry_port->refcount, 1);
+	mdb_entry_port->mrouter = true;
+	list_add(&mdb_entry_port->list, &mdb_entry->ports_list);
+
+	return mdb_entry_port;
+
+err_mdb_entry_port_alloc:
+	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, mdb_entry->mid,
+				    mdb_entry->key.fid, local_port, false);
+	return ERR_PTR(err);
+}
+
+static __always_unused void
+mlxsw_sp_mdb_entry_mrouter_port_put(struct mlxsw_sp *mlxsw_sp,
+				    struct mlxsw_sp_mdb_entry *mdb_entry,
+				    u16 local_port)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+
+	mdb_entry_port = mlxsw_sp_mdb_entry_port_lookup(mdb_entry, local_port);
+	if (!mdb_entry_port)
+		return;
+
+	if (!mdb_entry_port->mrouter)
+		return;
+
+	mdb_entry_port->mrouter = false;
+	if (!refcount_dec_and_test(&mdb_entry_port->refcount))
+		return;
+
+	list_del(&mdb_entry_port->list);
+	kfree(mdb_entry_port);
+	mlxsw_sp_pgt_entry_port_set(mlxsw_sp, mdb_entry->mid,
+				    mdb_entry->key.fid, local_port, false);
+}
+
 static void
 mlxsw_sp_bridge_mrouter_update_mdb(struct mlxsw_sp *mlxsw_sp,
 				   struct mlxsw_sp_bridge_device *bridge_device,
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 07/10] mlxsw: spectrum_switchdev: Implement mlxsw_sp_mc_mdb_entry_{init, fini}()
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (5 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 06/10] mlxsw: spectrum_switchdev: Add support for maintaining list of ports per MDB entry Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 08/10] mlxsw: spectrum_switchdev: Add support for getting and putting MDB entry Ido Schimmel
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

The next patches will convert MDB code to use PGT APIs. The change will
move the responsibility of allocating MID indexes and writing PGT
configurations to hardware to PGT code. As part of this change, most of the
MDB code will be changed and improved.

As a preparation for the above mentioned change, implement
mlxsw_sp_mc_mdb_entry_{init, fini}(). Currently, there is a function
__mlxsw_sp_mc_alloc(), which does not only allocate MID. In addition,
there is no an equivalent function to free the MID. When
mlxsw_sp_port_remove_from_mid() removes the last port, it handles MID
removal. Instead, add init() and fini() functions, which use PGT APIs.

The differences between the existing and the new functions are as follows:
1. Today MDB code does not update SMID when port is added/removed while
   multicast is disabled. It maintains a bitmap of ports and once multicast
   is enabled, it writes the entry to hardware. Instead, using PGT APIs,
   the entry will be updated also when multicast is disabled, but the
   mapping between {MAC, FID}->{MID} (is configured using SFD) will be
   updated according to multicast state. It means that SMID will be updated
   all the time and disable/enable multicast will impact only SFD
   configuration.

2. Today the allocation of MID index is done as part of
   mlxsw_sp_mc_write_mdb_entry(). The fact that the entry will be
   written in hardware all the time, moves the allocation of the index to
   be as part of the MDB entry initialization. PGT API is used for the
   allocation.

3. Today the update of multicast router ports is done as part of
   mlxsw_sp_mc_write_mdb_entry(). Instead, add functions to add/remove
   all multicast router ports when entry is first added or removed. When
   new multicast router port will be added/removed, the dedicated API will
   be used to add/remove it from the existing entries.

4. A list of ports will be stored per MDB entry instead of the exiting
   bitmap. The list will contain the multicast router ports and maintain
   reference counter per port.

Add mlxsw_sp_mdb_entry_write() which is almost identical to
mlxsw_sp_port_mdb_op(). Use more clear name and align the MID index to
bridge model using PGT API. The existing function will be removed in the
next patches.

Note that PGT APIs configure the firmware using SMID register, like the
driver already does today for MDB entries, so PGT APIs can be used also
using legacy bridge model.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../mellanox/mlxsw/spectrum_switchdev.c       | 176 +++++++++++++++++-
 1 file changed, 174 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index d1b0eddad504..bb2694ef6220 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1018,7 +1018,7 @@ mlxsw_sp_mdb_entry_port_lookup(struct mlxsw_sp_mdb_entry *mdb_entry,
 	return NULL;
 }
 
-static __always_unused struct mlxsw_sp_mdb_entry_port *
+static struct mlxsw_sp_mdb_entry_port *
 mlxsw_sp_mdb_entry_port_get(struct mlxsw_sp *mlxsw_sp,
 			    struct mlxsw_sp_mdb_entry *mdb_entry,
 			    u16 local_port)
@@ -1060,7 +1060,7 @@ mlxsw_sp_mdb_entry_port_get(struct mlxsw_sp *mlxsw_sp,
 	return ERR_PTR(err);
 }
 
-static __always_unused void
+static void
 mlxsw_sp_mdb_entry_port_put(struct mlxsw_sp *mlxsw_sp,
 			    struct mlxsw_sp_mdb_entry *mdb_entry,
 			    u16 local_port, bool force)
@@ -1801,6 +1801,37 @@ mlxsw_sp_port_fdb_set(struct mlxsw_sp_port *mlxsw_sp_port,
 						   vid, adding, false);
 }
 
+static int mlxsw_sp_mdb_entry_write(struct mlxsw_sp *mlxsw_sp,
+				    const struct mlxsw_sp_mdb_entry *mdb_entry,
+				    bool adding)
+{
+	char *sfd_pl;
+	u16 mid_idx;
+	u8 num_rec;
+	int err;
+
+	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
+	if (!sfd_pl)
+		return -ENOMEM;
+
+	mid_idx = mlxsw_sp_pgt_index_to_mid(mlxsw_sp, mdb_entry->mid);
+	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
+	mlxsw_reg_sfd_mc_pack(sfd_pl, 0, mdb_entry->key.addr,
+			      mdb_entry->key.fid, MLXSW_REG_SFD_REC_ACTION_NOP,
+			      mid_idx);
+	num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
+	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
+	if (err)
+		goto out;
+
+	if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl))
+		err = -EBUSY;
+
+out:
+	kfree(sfd_pl);
+	return err;
+}
+
 static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
 				u16 fid, u16 mid_idx, bool adding)
 {
@@ -2040,6 +2071,147 @@ static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
 	return err;
 }
 
+static int mlxsw_sp_mc_mdb_mrouters_add(struct mlxsw_sp *mlxsw_sp,
+					struct mlxsw_sp_ports_bitmap *ports_bm,
+					struct mlxsw_sp_mdb_entry *mdb_entry)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+	unsigned int nbits = ports_bm->nbits;
+	int i;
+
+	for_each_set_bit(i, ports_bm->bitmap, nbits) {
+		mdb_entry_port = mlxsw_sp_mdb_entry_mrouter_port_get(mlxsw_sp,
+								     mdb_entry,
+								     i);
+		if (IS_ERR(mdb_entry_port)) {
+			nbits = i;
+			goto err_mrouter_port_get;
+		}
+	}
+
+	return 0;
+
+err_mrouter_port_get:
+	for_each_set_bit(i, ports_bm->bitmap, nbits)
+		mlxsw_sp_mdb_entry_mrouter_port_put(mlxsw_sp, mdb_entry, i);
+	return PTR_ERR(mdb_entry_port);
+}
+
+static void mlxsw_sp_mc_mdb_mrouters_del(struct mlxsw_sp *mlxsw_sp,
+					 struct mlxsw_sp_ports_bitmap *ports_bm,
+					 struct mlxsw_sp_mdb_entry *mdb_entry)
+{
+	int i;
+
+	for_each_set_bit(i, ports_bm->bitmap, ports_bm->nbits)
+		mlxsw_sp_mdb_entry_mrouter_port_put(mlxsw_sp, mdb_entry, i);
+}
+
+static int
+mlxsw_sp_mc_mdb_mrouters_set(struct mlxsw_sp *mlxsw_sp,
+			     struct mlxsw_sp_bridge_device *bridge_device,
+			     struct mlxsw_sp_mdb_entry *mdb_entry, bool add)
+{
+	struct mlxsw_sp_ports_bitmap ports_bm;
+	int err;
+
+	err = mlxsw_sp_port_bitmap_init(mlxsw_sp, &ports_bm);
+	if (err)
+		return err;
+
+	mlxsw_sp_mc_get_mrouters_bitmap(&ports_bm, bridge_device, mlxsw_sp);
+
+	if (add)
+		err = mlxsw_sp_mc_mdb_mrouters_add(mlxsw_sp, &ports_bm,
+						   mdb_entry);
+	else
+		mlxsw_sp_mc_mdb_mrouters_del(mlxsw_sp, &ports_bm, mdb_entry);
+
+	mlxsw_sp_port_bitmap_fini(&ports_bm);
+	return err;
+}
+
+static __always_unused struct mlxsw_sp_mdb_entry *
+mlxsw_sp_mc_mdb_entry_init(struct mlxsw_sp *mlxsw_sp,
+			   struct mlxsw_sp_bridge_device *bridge_device,
+			   const unsigned char *addr, u16 fid, u16 local_port)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+	struct mlxsw_sp_mdb_entry *mdb_entry;
+	int err;
+
+	mdb_entry = kzalloc(sizeof(*mdb_entry), GFP_KERNEL);
+	if (!mdb_entry)
+		return ERR_PTR(-ENOMEM);
+
+	ether_addr_copy(mdb_entry->key.addr, addr);
+	mdb_entry->key.fid = fid;
+	err = mlxsw_sp_pgt_mid_alloc(mlxsw_sp, &mdb_entry->mid);
+	if (err)
+		goto err_pgt_mid_alloc;
+
+	INIT_LIST_HEAD(&mdb_entry->ports_list);
+
+	err = mlxsw_sp_mc_mdb_mrouters_set(mlxsw_sp, bridge_device, mdb_entry,
+					   true);
+	if (err)
+		goto err_mdb_mrouters_set;
+
+	mdb_entry_port = mlxsw_sp_mdb_entry_port_get(mlxsw_sp, mdb_entry,
+						     local_port);
+	if (IS_ERR(mdb_entry_port)) {
+		err = PTR_ERR(mdb_entry_port);
+		goto err_mdb_entry_port_get;
+	}
+
+	if (bridge_device->multicast_enabled) {
+		err = mlxsw_sp_mdb_entry_write(mlxsw_sp, mdb_entry, true);
+		if (err)
+			goto err_mdb_entry_write;
+	}
+
+	err = rhashtable_insert_fast(&bridge_device->mdb_ht,
+				     &mdb_entry->ht_node,
+				     mlxsw_sp_mdb_ht_params);
+	if (err)
+		goto err_rhashtable_insert;
+
+	list_add_tail(&mdb_entry->list, &bridge_device->mdb_list);
+
+	return mdb_entry;
+
+err_rhashtable_insert:
+	if (bridge_device->multicast_enabled)
+		mlxsw_sp_mdb_entry_write(mlxsw_sp, mdb_entry, false);
+err_mdb_entry_write:
+	mlxsw_sp_mdb_entry_port_put(mlxsw_sp, mdb_entry, local_port, false);
+err_mdb_entry_port_get:
+	mlxsw_sp_mc_mdb_mrouters_set(mlxsw_sp, bridge_device, mdb_entry, false);
+err_mdb_mrouters_set:
+	mlxsw_sp_pgt_mid_free(mlxsw_sp, mdb_entry->mid);
+err_pgt_mid_alloc:
+	kfree(mdb_entry);
+	return ERR_PTR(err);
+}
+
+static __always_unused void
+mlxsw_sp_mc_mdb_entry_fini(struct mlxsw_sp *mlxsw_sp,
+			   struct mlxsw_sp_mdb_entry *mdb_entry,
+			   struct mlxsw_sp_bridge_device *bridge_device,
+			   u16 local_port, bool force)
+{
+	list_del(&mdb_entry->list);
+	rhashtable_remove_fast(&bridge_device->mdb_ht, &mdb_entry->ht_node,
+			       mlxsw_sp_mdb_ht_params);
+	if (bridge_device->multicast_enabled)
+		mlxsw_sp_mdb_entry_write(mlxsw_sp, mdb_entry, false);
+	mlxsw_sp_mdb_entry_port_put(mlxsw_sp, mdb_entry, local_port, force);
+	mlxsw_sp_mc_mdb_mrouters_set(mlxsw_sp, bridge_device, mdb_entry, false);
+	WARN_ON(!list_empty(&mdb_entry->ports_list));
+	mlxsw_sp_pgt_mid_free(mlxsw_sp, mdb_entry->mid);
+	kfree(mdb_entry);
+}
+
 static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 				 const struct switchdev_obj_port_mdb *mdb)
 {
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 08/10] mlxsw: spectrum_switchdev: Add support for getting and putting MDB entry
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (6 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 07/10] mlxsw: spectrum_switchdev: Implement mlxsw_sp_mc_mdb_entry_{init, fini}() Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 09/10] mlxsw: spectrum_switchdev: Flush port from MDB entries according to FID index Ido Schimmel
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

A previous patch added support for init() and fini() for MDB entries. MDB
entry can be updated, ports can be added and removed from the entry. Add
get() and put() functions, the first one checks if the entry already exists
and otherwise initializes the entry. The second removes the entry just in
case that there are no more ports in this entry.

Use the list of the ports which was added in a previous patch. When the
list contains only one port which is not multicast router, and this port
is removed, the MDB entry can be removed. Use
'struct mlxsw_sp_mdb_entry.ports_count' to know how many ports use the
entry, regardless the use of multicast router ports.

When mlxsw_sp_mc_mdb_entry_put() is called with specific port which
supposed to be removed, check if the removal will cause a deletion of
the entry. If this is the case, call mlxsw_sp_mc_mdb_entry_fini() which
first deletes the MDB entry and then releases the PGT entry, to avoid a
temporary situation in which the MDB entry points to an empty PGT entry,
as otherwise packets will be temporarily dropped instead of being flooded.

The new functions will be used in the next patches.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../mellanox/mlxsw/spectrum_switchdev.c       | 80 ++++++++++++++++++-
 1 file changed, 78 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index bb2694ef6220..5f8136a8db13 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -2131,7 +2131,7 @@ mlxsw_sp_mc_mdb_mrouters_set(struct mlxsw_sp *mlxsw_sp,
 	return err;
 }
 
-static __always_unused struct mlxsw_sp_mdb_entry *
+static struct mlxsw_sp_mdb_entry *
 mlxsw_sp_mc_mdb_entry_init(struct mlxsw_sp *mlxsw_sp,
 			   struct mlxsw_sp_bridge_device *bridge_device,
 			   const unsigned char *addr, u16 fid, u16 local_port)
@@ -2194,7 +2194,7 @@ mlxsw_sp_mc_mdb_entry_init(struct mlxsw_sp *mlxsw_sp,
 	return ERR_PTR(err);
 }
 
-static __always_unused void
+static void
 mlxsw_sp_mc_mdb_entry_fini(struct mlxsw_sp *mlxsw_sp,
 			   struct mlxsw_sp_mdb_entry *mdb_entry,
 			   struct mlxsw_sp_bridge_device *bridge_device,
@@ -2212,6 +2212,82 @@ mlxsw_sp_mc_mdb_entry_fini(struct mlxsw_sp *mlxsw_sp,
 	kfree(mdb_entry);
 }
 
+static __always_unused struct mlxsw_sp_mdb_entry *
+mlxsw_sp_mc_mdb_entry_get(struct mlxsw_sp *mlxsw_sp,
+			  struct mlxsw_sp_bridge_device *bridge_device,
+			  const unsigned char *addr, u16 fid, u16 local_port)
+{
+	struct mlxsw_sp_mdb_entry_key key = {};
+	struct mlxsw_sp_mdb_entry *mdb_entry;
+
+	ether_addr_copy(key.addr, addr);
+	key.fid = fid;
+	mdb_entry = rhashtable_lookup_fast(&bridge_device->mdb_ht, &key,
+					   mlxsw_sp_mdb_ht_params);
+	if (mdb_entry) {
+		struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+
+		mdb_entry_port = mlxsw_sp_mdb_entry_port_get(mlxsw_sp,
+							     mdb_entry,
+							     local_port);
+		if (IS_ERR(mdb_entry_port))
+			return ERR_CAST(mdb_entry_port);
+
+		return mdb_entry;
+	}
+
+	return mlxsw_sp_mc_mdb_entry_init(mlxsw_sp, bridge_device, addr, fid,
+					  local_port);
+}
+
+static bool
+mlxsw_sp_mc_mdb_entry_remove(struct mlxsw_sp_mdb_entry *mdb_entry,
+			     struct mlxsw_sp_mdb_entry_port *removed_entry_port,
+			     bool force)
+{
+	if (mdb_entry->ports_count > 1)
+		return false;
+
+	if (force)
+		return true;
+
+	if (!removed_entry_port->mrouter &&
+	    refcount_read(&removed_entry_port->refcount) > 1)
+		return false;
+
+	if (removed_entry_port->mrouter &&
+	    refcount_read(&removed_entry_port->refcount) > 2)
+		return false;
+
+	return true;
+}
+
+static __always_unused void
+mlxsw_sp_mc_mdb_entry_put(struct mlxsw_sp *mlxsw_sp,
+			  struct mlxsw_sp_bridge_device *bridge_device,
+			  struct mlxsw_sp_mdb_entry *mdb_entry, u16 local_port,
+			  bool force)
+{
+	struct mlxsw_sp_mdb_entry_port *mdb_entry_port;
+
+	mdb_entry_port = mlxsw_sp_mdb_entry_port_lookup(mdb_entry, local_port);
+	if (!mdb_entry_port)
+		return;
+
+	/* Avoid a temporary situation in which the MDB entry points to an empty
+	 * PGT entry, as otherwise packets will be temporarily dropped instead
+	 * of being flooded. Instead, in this situation, call
+	 * mlxsw_sp_mc_mdb_entry_fini(), which first deletes the MDB entry and
+	 * then releases the PGT entry.
+	 */
+	if (mlxsw_sp_mc_mdb_entry_remove(mdb_entry, mdb_entry_port, force))
+		mlxsw_sp_mc_mdb_entry_fini(mlxsw_sp, mdb_entry, bridge_device,
+					   local_port, force);
+	else
+		mlxsw_sp_mdb_entry_port_put(mlxsw_sp, mdb_entry, local_port,
+					    force);
+}
+
 static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 				 const struct switchdev_obj_port_mdb *mdb)
 {
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 09/10] mlxsw: spectrum_switchdev: Flush port from MDB entries according to FID index
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (7 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 08/10] mlxsw: spectrum_switchdev: Add support for getting and putting MDB entry Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29  9:40 ` [PATCH net-next 10/10] mlxsw: spectrum_switchdev: Convert MDB code to use PGT APIs Ido Schimmel
  2022-06-29 12:50 ` [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 patchwork-bot+netdevbpf
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Currently, flushing port from all MDB entries is done when the last VLAN
is removed. This behavior is inaccurate, as port can be removed while there
is another port which uses the same VLAN, in such case, this is not the
last port which uses this VLAN and removed, but this port is supposed to be
removed from the MDB entries.

Flush the port from MDB when it is removed, regardless the state of other
ports. Flush only the MDB entries which are relevant for the same FID
index.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../mellanox/mlxsw/spectrum_switchdev.c         | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 5f8136a8db13..0cf442e0dce0 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -139,7 +139,8 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 
 static void
 mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
-			       struct mlxsw_sp_bridge_port *bridge_port);
+			       struct mlxsw_sp_bridge_port *bridge_port,
+			       u16 fid_index);
 
 static int
 mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
@@ -1382,14 +1383,13 @@ mlxsw_sp_port_vlan_bridge_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 	struct mlxsw_sp_bridge_vlan *bridge_vlan;
 	struct mlxsw_sp_bridge_port *bridge_port;
 	u16 vid = mlxsw_sp_port_vlan->vid;
-	bool last_port, last_vlan;
+	bool last_port;
 
 	if (WARN_ON(mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_8021Q &&
 		    mlxsw_sp_fid_type(fid) != MLXSW_SP_FID_TYPE_8021D))
 		return;
 
 	bridge_port = mlxsw_sp_port_vlan->bridge_port;
-	last_vlan = list_is_singular(&bridge_port->vlans_list);
 	bridge_vlan = mlxsw_sp_bridge_vlan_find(bridge_port, vid);
 	last_port = list_is_singular(&bridge_vlan->port_vlan_list);
 
@@ -1401,8 +1401,9 @@ mlxsw_sp_port_vlan_bridge_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
 		mlxsw_sp_bridge_port_fdb_flush(mlxsw_sp_port->mlxsw_sp,
 					       bridge_port,
 					       mlxsw_sp_fid_index(fid));
-	if (last_vlan)
-		mlxsw_sp_bridge_port_mdb_flush(mlxsw_sp_port, bridge_port);
+
+	mlxsw_sp_bridge_port_mdb_flush(mlxsw_sp_port, bridge_port,
+				       mlxsw_sp_fid_index(fid));
 
 	mlxsw_sp_port_vlan_fid_leave(mlxsw_sp_port_vlan);
 
@@ -2528,7 +2529,8 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 
 static void
 mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
-			       struct mlxsw_sp_bridge_port *bridge_port)
+			       struct mlxsw_sp_bridge_port *bridge_port,
+			       u16 fid_index)
 {
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_mdb_entry *mdb_entry, *tmp;
@@ -2538,6 +2540,9 @@ mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	list_for_each_entry_safe(mdb_entry, tmp, &bridge_device->mdb_list,
 				 list) {
+		if (mdb_entry->key.fid != fid_index)
+			continue;
+
 		if (test_bit(local_port, mdb_entry->ports_in_mid)) {
 			__mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port,
 						mdb_entry);
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH net-next 10/10] mlxsw: spectrum_switchdev: Convert MDB code to use PGT APIs
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (8 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 09/10] mlxsw: spectrum_switchdev: Flush port from MDB entries according to FID index Ido Schimmel
@ 2022-06-29  9:40 ` Ido Schimmel
  2022-06-29 12:50 ` [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 patchwork-bot+netdevbpf
  10 siblings, 0 replies; 12+ messages in thread
From: Ido Schimmel @ 2022-06-29  9:40 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

The previous patches added common APIs for maintaining PGT (Port Group
Table) table. In the legacy model, software did not interact with this
table directly. Instead, it was accessed by firmware in response to
registers such as SFTR and SMID. In the new model, software has full
control over the PGT table using the SMID register.

The configuration of MDB entries is already done via SMID, so the new
PGT APIs can be used also using the legacy model, the only difference is
that MID index should be aligned to bridge model. See a previous patch
which added API for that.

The main changes are:
- MDB code does not maintain bitmap of ports in MDB entry anymore, instead,
  it stores a list of ports with additional information.
- MDB code does not configure SMID register directly anymore, it will be
  done via PGT API when port is first added or removed.
- Today MDB code does not update SMID when port is added/removed while
  multicast is disabled. Instead, it maintains bitmap of ports and once
  multicast is enabled, it rewrite the entry to hardware. Using PGT APIs,
  the entry will be updated also when multicast is disabled, but the
  mapping between {MAC, FID}->{MID} will not appear in SFD register. It
  means that SMID will be updated all the time and disable/enable multicast
  will impact only SFD configuration.
- For multicast router, today only SMID is updated and the bitmap is not
  updated. Using the new list of ports, there is a reference count for each
  port, so it can be saved in software also. For such port,
  'struct mlxsw_sp_mdb_entry.ports_count' will not be updated and the
  port in the list will be marked as 'mrouter'.
- Finally, `struct mlxsw_sp_mid.in_hw` is not needed anymore.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../mellanox/mlxsw/spectrum_switchdev.c       | 352 +++---------------
 1 file changed, 48 insertions(+), 304 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 0cf442e0dce0..7cabe6e8edeb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -115,8 +115,6 @@ struct mlxsw_sp_mdb_entry {
 	u16 mid;
 	struct list_head ports_list;
 	u16 ports_count;
-	bool in_hw;
-	unsigned long *ports_in_mid; /* bits array */
 };
 
 struct mlxsw_sp_mdb_entry_port {
@@ -910,6 +908,9 @@ static int mlxsw_sp_port_attr_mrouter_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	if (!bridge_port)
 		return 0;
 
+	mlxsw_sp_port_mrouter_update_mdb(mlxsw_sp_port, bridge_port,
+					 is_port_mrouter);
+
 	if (!bridge_port->bridge_device->multicast_enabled)
 		goto out;
 
@@ -919,8 +920,6 @@ static int mlxsw_sp_port_attr_mrouter_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	if (err)
 		return err;
 
-	mlxsw_sp_port_mrouter_update_mdb(mlxsw_sp_port, bridge_port,
-					 is_port_mrouter);
 out:
 	bridge_port->mrouter = is_port_mrouter;
 	return 0;
@@ -988,23 +987,6 @@ static int mlxsw_sp_port_mc_disabled_set(struct mlxsw_sp_port *mlxsw_sp_port,
 	return err;
 }
 
-static int mlxsw_sp_smid_router_port_set(struct mlxsw_sp *mlxsw_sp,
-					 u16 mid_idx, bool add)
-{
-	char *smid2_pl;
-	int err;
-
-	smid2_pl = kmalloc(MLXSW_REG_SMID2_LEN, GFP_KERNEL);
-	if (!smid2_pl)
-		return -ENOMEM;
-
-	mlxsw_reg_smid2_pack(smid2_pl, mid_idx,
-			     mlxsw_sp_router_port(mlxsw_sp), add, false, 0);
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid2), smid2_pl);
-	kfree(smid2_pl);
-	return err;
-}
-
 static struct mlxsw_sp_mdb_entry_port *
 mlxsw_sp_mdb_entry_port_lookup(struct mlxsw_sp_mdb_entry *mdb_entry,
 			       u16 local_port)
@@ -1154,10 +1136,17 @@ mlxsw_sp_bridge_mrouter_update_mdb(struct mlxsw_sp *mlxsw_sp,
 				   struct mlxsw_sp_bridge_device *bridge_device,
 				   bool add)
 {
+	u16 local_port = mlxsw_sp_router_port(mlxsw_sp);
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 
-	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list)
-		mlxsw_sp_smid_router_port_set(mlxsw_sp, mdb_entry->mid, add);
+	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
+		if (add)
+			mlxsw_sp_mdb_entry_mrouter_port_get(mlxsw_sp, mdb_entry,
+							    local_port);
+		else
+			mlxsw_sp_mdb_entry_mrouter_port_put(mlxsw_sp, mdb_entry,
+							    local_port);
+	}
 }
 
 static int
@@ -1833,97 +1822,6 @@ static int mlxsw_sp_mdb_entry_write(struct mlxsw_sp *mlxsw_sp,
 	return err;
 }
 
-static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
-				u16 fid, u16 mid_idx, bool adding)
-{
-	char *sfd_pl;
-	u8 num_rec;
-	int err;
-
-	sfd_pl = kmalloc(MLXSW_REG_SFD_LEN, GFP_KERNEL);
-	if (!sfd_pl)
-		return -ENOMEM;
-
-	mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
-	mlxsw_reg_sfd_mc_pack(sfd_pl, 0, addr, fid,
-			      MLXSW_REG_SFD_REC_ACTION_NOP, mid_idx);
-	num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
-	if (err)
-		goto out;
-
-	if (num_rec != mlxsw_reg_sfd_num_rec_get(sfd_pl))
-		err = -EBUSY;
-
-out:
-	kfree(sfd_pl);
-	return err;
-}
-
-static int
-mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp, u16 mid_idx,
-			      const struct mlxsw_sp_ports_bitmap *ports_bm,
-			      bool set_router_port)
-{
-	char *smid2_pl;
-	int err, i;
-
-	smid2_pl = kmalloc(MLXSW_REG_SMID2_LEN, GFP_KERNEL);
-	if (!smid2_pl)
-		return -ENOMEM;
-
-	mlxsw_reg_smid2_pack(smid2_pl, mid_idx, 0, false, false, 0);
-	for (i = 1; i < mlxsw_core_max_ports(mlxsw_sp->core); i++) {
-		if (mlxsw_sp->ports[i])
-			mlxsw_reg_smid2_port_mask_set(smid2_pl, i, 1);
-	}
-
-	mlxsw_reg_smid2_port_mask_set(smid2_pl,
-				      mlxsw_sp_router_port(mlxsw_sp), 1);
-
-	for_each_set_bit(i, ports_bm->bitmap, ports_bm->nbits)
-		mlxsw_reg_smid2_port_set(smid2_pl, i, 1);
-
-	mlxsw_reg_smid2_port_set(smid2_pl, mlxsw_sp_router_port(mlxsw_sp),
-				 set_router_port);
-
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid2), smid2_pl);
-	kfree(smid2_pl);
-	return err;
-}
-
-static int mlxsw_sp_port_smid_set(struct mlxsw_sp_port *mlxsw_sp_port,
-				  u16 mid_idx, bool add)
-{
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-	char *smid2_pl;
-	int err;
-
-	smid2_pl = kmalloc(MLXSW_REG_SMID2_LEN, GFP_KERNEL);
-	if (!smid2_pl)
-		return -ENOMEM;
-
-	mlxsw_reg_smid2_pack(smid2_pl, mid_idx, mlxsw_sp_port->local_port, add,
-			     false, 0);
-	err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smid2), smid2_pl);
-	kfree(smid2_pl);
-	return err;
-}
-
-static struct mlxsw_sp_mdb_entry *
-__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
-		  const unsigned char *addr, u16 fid)
-{
-	struct mlxsw_sp_mdb_entry *mdb_entry;
-
-	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
-		if (ether_addr_equal(mdb_entry->key.addr, addr) &&
-		    mdb_entry->key.fid == fid)
-			return mdb_entry;
-	}
-	return NULL;
-}
-
 static void
 mlxsw_sp_bridge_port_get_ports_bitmap(struct mlxsw_sp *mlxsw_sp,
 				      struct mlxsw_sp_bridge_port *bridge_port,
@@ -1965,113 +1863,6 @@ mlxsw_sp_mc_get_mrouters_bitmap(struct mlxsw_sp_ports_bitmap *flood_bm,
 	}
 }
 
-static int
-mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
-			    struct mlxsw_sp_mdb_entry *mdb_entry,
-			    struct mlxsw_sp_bridge_device *bridge_device)
-{
-	struct mlxsw_sp_ports_bitmap flood_bitmap;
-	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 -ENOBUFS;
-
-	err = mlxsw_sp_port_bitmap_init(mlxsw_sp, &flood_bitmap);
-	if (err)
-		return err;
-
-	bitmap_copy(flood_bitmap.bitmap, mdb_entry->ports_in_mid,
-		    flood_bitmap.nbits);
-	mlxsw_sp_mc_get_mrouters_bitmap(&flood_bitmap, bridge_device, mlxsw_sp);
-
-	mdb_entry->mid = mid_idx;
-	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, &flood_bitmap,
-					    bridge_device->mrouter);
-	mlxsw_sp_port_bitmap_fini(&flood_bitmap);
-	if (err)
-		return err;
-
-	err = mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->key.addr,
-				   mdb_entry->key.fid, mid_idx, true);
-	if (err)
-		return err;
-
-	set_bit(mid_idx, mlxsw_sp->bridge->mids_bitmap);
-	mdb_entry->in_hw = true;
-	return 0;
-}
-
-static int mlxsw_sp_mc_remove_mdb_entry(struct mlxsw_sp *mlxsw_sp,
-					struct mlxsw_sp_mdb_entry *mdb_entry)
-{
-	if (!mdb_entry->in_hw)
-		return 0;
-
-	clear_bit(mdb_entry->mid, mlxsw_sp->bridge->mids_bitmap);
-	mdb_entry->in_hw = false;
-	return mlxsw_sp_port_mdb_op(mlxsw_sp, mdb_entry->key.addr,
-				    mdb_entry->key.fid, mdb_entry->mid, false);
-}
-
-static struct mlxsw_sp_mdb_entry *
-__mlxsw_sp_mc_alloc(struct mlxsw_sp *mlxsw_sp,
-		    struct mlxsw_sp_bridge_device *bridge_device,
-		    const unsigned char *addr, u16 fid)
-{
-	unsigned int max_ports = mlxsw_core_max_ports(mlxsw_sp->core);
-	struct mlxsw_sp_mdb_entry *mdb_entry;
-	int err;
-
-	mdb_entry = kzalloc(sizeof(*mdb_entry), GFP_KERNEL);
-	if (!mdb_entry)
-		return NULL;
-
-	mdb_entry->ports_in_mid = bitmap_zalloc(max_ports, GFP_KERNEL);
-	if (!mdb_entry->ports_in_mid)
-		goto err_ports_in_mid_alloc;
-
-	ether_addr_copy(mdb_entry->key.addr, addr);
-	mdb_entry->key.fid = fid;
-	mdb_entry->in_hw = false;
-
-	if (!bridge_device->multicast_enabled)
-		goto out;
-
-	err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mdb_entry, bridge_device);
-	if (err)
-		goto err_write_mdb_entry;
-
-out:
-	list_add_tail(&mdb_entry->list, &bridge_device->mdb_list);
-	return mdb_entry;
-
-err_write_mdb_entry:
-	bitmap_free(mdb_entry->ports_in_mid);
-err_ports_in_mid_alloc:
-	kfree(mdb_entry);
-	return NULL;
-}
-
-static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
-					 struct mlxsw_sp_mdb_entry *mdb_entry)
-{
-	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
-	int err = 0;
-
-	clear_bit(mlxsw_sp_port->local_port, mdb_entry->ports_in_mid);
-	if (bitmap_empty(mdb_entry->ports_in_mid,
-			 mlxsw_core_max_ports(mlxsw_sp->core))) {
-		err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mdb_entry);
-		list_del(&mdb_entry->list);
-		bitmap_free(mdb_entry->ports_in_mid);
-		kfree(mdb_entry);
-	}
-	return err;
-}
-
 static int mlxsw_sp_mc_mdb_mrouters_add(struct mlxsw_sp *mlxsw_sp,
 					struct mlxsw_sp_ports_bitmap *ports_bm,
 					struct mlxsw_sp_mdb_entry *mdb_entry)
@@ -2213,7 +2004,7 @@ mlxsw_sp_mc_mdb_entry_fini(struct mlxsw_sp *mlxsw_sp,
 	kfree(mdb_entry);
 }
 
-static __always_unused struct mlxsw_sp_mdb_entry *
+static struct mlxsw_sp_mdb_entry *
 mlxsw_sp_mc_mdb_entry_get(struct mlxsw_sp *mlxsw_sp,
 			  struct mlxsw_sp_bridge_device *bridge_device,
 			  const unsigned char *addr, u16 fid, u16 local_port)
@@ -2263,7 +2054,7 @@ mlxsw_sp_mc_mdb_entry_remove(struct mlxsw_sp_mdb_entry *mdb_entry,
 	return true;
 }
 
-static __always_unused void
+static void
 mlxsw_sp_mc_mdb_entry_put(struct mlxsw_sp *mlxsw_sp,
 			  struct mlxsw_sp_bridge_device *bridge_device,
 			  struct mlxsw_sp_mdb_entry *mdb_entry, u16 local_port,
@@ -2295,12 +2086,10 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 	struct net_device *orig_dev = mdb->obj.orig_dev;
 	struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
-	struct net_device *dev = mlxsw_sp_port->dev;
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_bridge_port *bridge_port;
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 	u16 fid_index;
-	int err = 0;
 
 	bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
 	if (!bridge_port)
@@ -2315,34 +2104,13 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
 
-	mdb_entry = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
-	if (!mdb_entry) {
-		mdb_entry = __mlxsw_sp_mc_alloc(mlxsw_sp, bridge_device,
-						mdb->addr, fid_index);
-		if (!mdb_entry) {
-			netdev_err(dev, "Unable to allocate MC group\n");
-			return -ENOMEM;
-		}
-	}
-	set_bit(mlxsw_sp_port->local_port, mdb_entry->ports_in_mid);
-
-	if (!bridge_device->multicast_enabled)
-		return 0;
-
-	if (bridge_port->mrouter)
-		return 0;
-
-	err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid, true);
-	if (err) {
-		netdev_err(dev, "Unable to set SMID\n");
-		goto err_out;
-	}
+	mdb_entry = mlxsw_sp_mc_mdb_entry_get(mlxsw_sp, bridge_device,
+					      mdb->addr, fid_index,
+					      mlxsw_sp_port->local_port);
+	if (IS_ERR(mdb_entry))
+		return PTR_ERR(mdb_entry);
 
 	return 0;
-
-err_out:
-	mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mdb_entry);
-	return err;
 }
 
 static int
@@ -2354,27 +2122,16 @@ mlxsw_sp_bridge_mdb_mc_enable_sync(struct mlxsw_sp *mlxsw_sp,
 	int err;
 
 	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
-		if (mc_enabled)
-			err = mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mdb_entry,
-							  bridge_device);
-		else
-			err = mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mdb_entry);
-
+		err = mlxsw_sp_mdb_entry_write(mlxsw_sp, mdb_entry, mc_enabled);
 		if (err)
-			goto err_mdb_entry_update;
+			goto err_mdb_entry_write;
 	}
-
 	return 0;
 
-err_mdb_entry_update:
+err_mdb_entry_write:
 	list_for_each_entry_continue_reverse(mdb_entry,
-					     &bridge_device->mdb_list, list) {
-		if (mc_enabled)
-			mlxsw_sp_mc_remove_mdb_entry(mlxsw_sp, mdb_entry);
-		else
-			mlxsw_sp_mc_write_mdb_entry(mlxsw_sp, mdb_entry,
-						    bridge_device);
-	}
+					     &bridge_device->mdb_list, list)
+		mlxsw_sp_mdb_entry_write(mlxsw_sp, mdb_entry, !mc_enabled);
 	return err;
 }
 
@@ -2383,16 +2140,20 @@ mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,
 				 struct mlxsw_sp_bridge_port *bridge_port,
 				 bool add)
 {
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 	struct mlxsw_sp_bridge_device *bridge_device;
+	u16 local_port = mlxsw_sp_port->local_port;
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 
 	bridge_device = bridge_port->bridge_device;
 
 	list_for_each_entry(mdb_entry, &bridge_device->mdb_list, list) {
-		if (!test_bit(mlxsw_sp_port->local_port,
-			      mdb_entry->ports_in_mid))
-			mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid,
-					       add);
+		if (add)
+			mlxsw_sp_mdb_entry_mrouter_port_get(mlxsw_sp, mdb_entry,
+							    local_port);
+		else
+			mlxsw_sp_mdb_entry_mrouter_port_put(mlxsw_sp, mdb_entry,
+							    local_port);
 	}
 }
 
@@ -2470,29 +2231,6 @@ static int mlxsw_sp_port_vlans_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	return 0;
 }
 
-static int
-__mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
-			struct mlxsw_sp_bridge_port *bridge_port,
-			struct mlxsw_sp_mdb_entry *mdb_entry)
-{
-	struct net_device *dev = mlxsw_sp_port->dev;
-	int err;
-
-	if (bridge_port->bridge_device->multicast_enabled &&
-	    !bridge_port->mrouter) {
-		err = mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid,
-					     false);
-		if (err)
-			netdev_err(dev, "Unable to remove port from SMID\n");
-	}
-
-	err = mlxsw_sp_port_remove_from_mid(mlxsw_sp_port, mdb_entry);
-	if (err)
-		netdev_err(dev, "Unable to remove MC SFD\n");
-
-	return err;
-}
-
 static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 				 const struct switchdev_obj_port_mdb *mdb)
 {
@@ -2502,6 +2240,7 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct net_device *dev = mlxsw_sp_port->dev;
 	struct mlxsw_sp_bridge_port *bridge_port;
+	struct mlxsw_sp_mdb_entry_key key = {};
 	struct mlxsw_sp_mdb_entry *mdb_entry;
 	u16 fid_index;
 
@@ -2518,13 +2257,18 @@ static int mlxsw_sp_port_mdb_del(struct mlxsw_sp_port *mlxsw_sp_port,
 
 	fid_index = mlxsw_sp_fid_index(mlxsw_sp_port_vlan->fid);
 
-	mdb_entry = __mlxsw_sp_mc_get(bridge_device, mdb->addr, fid_index);
+	ether_addr_copy(key.addr, mdb->addr);
+	key.fid = fid_index;
+	mdb_entry = rhashtable_lookup_fast(&bridge_device->mdb_ht, &key,
+					   mlxsw_sp_mdb_ht_params);
 	if (!mdb_entry) {
 		netdev_err(dev, "Unable to remove port from MC DB\n");
 		return -EINVAL;
 	}
 
-	return __mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port, mdb_entry);
+	mlxsw_sp_mc_mdb_entry_put(mlxsw_sp, bridge_device, mdb_entry,
+				  mlxsw_sp_port->local_port, false);
+	return 0;
 }
 
 static void
@@ -2532,6 +2276,7 @@ mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
 			       struct mlxsw_sp_bridge_port *bridge_port,
 			       u16 fid_index)
 {
+	struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 	struct mlxsw_sp_bridge_device *bridge_device;
 	struct mlxsw_sp_mdb_entry *mdb_entry, *tmp;
 	u16 local_port = mlxsw_sp_port->local_port;
@@ -2543,14 +2288,13 @@ mlxsw_sp_bridge_port_mdb_flush(struct mlxsw_sp_port *mlxsw_sp_port,
 		if (mdb_entry->key.fid != fid_index)
 			continue;
 
-		if (test_bit(local_port, mdb_entry->ports_in_mid)) {
-			__mlxsw_sp_port_mdb_del(mlxsw_sp_port, bridge_port,
-						mdb_entry);
-		} else if (bridge_device->multicast_enabled &&
-			   bridge_port->mrouter) {
-			mlxsw_sp_port_smid_set(mlxsw_sp_port, mdb_entry->mid,
-					       false);
-		}
+		if (bridge_port->mrouter)
+			mlxsw_sp_mdb_entry_mrouter_port_put(mlxsw_sp,
+							    mdb_entry,
+							    local_port);
+
+		mlxsw_sp_mc_mdb_entry_put(mlxsw_sp, bridge_device, mdb_entry,
+					  local_port, true);
 	}
 }
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6
  2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
                   ` (9 preceding siblings ...)
  2022-06-29  9:40 ` [PATCH net-next 10/10] mlxsw: spectrum_switchdev: Convert MDB code to use PGT APIs Ido Schimmel
@ 2022-06-29 12:50 ` patchwork-bot+netdevbpf
  10 siblings, 0 replies; 12+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-06-29 12:50 UTC (permalink / raw)
  To: Ido Schimmel; +Cc: netdev, davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw

Hello:

This series was applied to netdev/net-next.git (master)
by David S. Miller <davem@davemloft.net>:

On Wed, 29 Jun 2022 12:39:57 +0300 you wrote:
> This is the fifth part of the conversion of mlxsw to the unified bridge
> model.
> 
> The previous part that was merged in commit d521bc0a0f7c ("Merge branch
> 'mlxsw-unified-bridge-conversion-part-4-6'") converted the flooding code
> to use the new APIs of the unified bridge model. As part of this
> conversion, the flooding code started accessing the port group table
> (PGT) directly in order to allocate MID indexes and configure the ports
> via which a packet needs to be replicated.
> 
> [...]

Here is the summary with links:
  - [net-next,01/10] mlxsw: Align PGT index to legacy bridge model
    https://git.kernel.org/netdev/net-next/c/4abaa5cc4d7c
  - [net-next,02/10] mlxsw: spectrum_switchdev: Rename MID structure
    https://git.kernel.org/netdev/net-next/c/eede53a49b3c
  - [net-next,03/10] mlxsw: spectrum_switchdev: Rename MIDs list
    https://git.kernel.org/netdev/net-next/c/eaa0791aed8b
  - [net-next,04/10] mlxsw: spectrum_switchdev: Save MAC and FID as a key in 'struct mlxsw_sp_mdb_entry'
    https://git.kernel.org/netdev/net-next/c/0ac985436eb9
  - [net-next,05/10] mlxsw: spectrum_switchdev: Add support for maintaining hash table of MDB entries
    https://git.kernel.org/netdev/net-next/c/5d0512e5cf74
  - [net-next,06/10] mlxsw: spectrum_switchdev: Add support for maintaining list of ports per MDB entry
    https://git.kernel.org/netdev/net-next/c/d2994e130585
  - [net-next,07/10] mlxsw: spectrum_switchdev: Implement mlxsw_sp_mc_mdb_entry_{init, fini}()
    https://git.kernel.org/netdev/net-next/c/ea0f58d6c543
  - [net-next,08/10] mlxsw: spectrum_switchdev: Add support for getting and putting MDB entry
    https://git.kernel.org/netdev/net-next/c/7434ed6102c1
  - [net-next,09/10] mlxsw: spectrum_switchdev: Flush port from MDB entries according to FID index
    https://git.kernel.org/netdev/net-next/c/4c3f7442770b
  - [net-next,10/10] mlxsw: spectrum_switchdev: Convert MDB code to use PGT APIs
    https://git.kernel.org/netdev/net-next/c/e28cd993b9a4

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-06-29 12:50 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-29  9:39 [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 Ido Schimmel
2022-06-29  9:39 ` [PATCH net-next 01/10] mlxsw: Align PGT index to legacy bridge model Ido Schimmel
2022-06-29  9:39 ` [PATCH net-next 02/10] mlxsw: spectrum_switchdev: Rename MID structure Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 03/10] mlxsw: spectrum_switchdev: Rename MIDs list Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 04/10] mlxsw: spectrum_switchdev: Save MAC and FID as a key in 'struct mlxsw_sp_mdb_entry' Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 05/10] mlxsw: spectrum_switchdev: Add support for maintaining hash table of MDB entries Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 06/10] mlxsw: spectrum_switchdev: Add support for maintaining list of ports per MDB entry Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 07/10] mlxsw: spectrum_switchdev: Implement mlxsw_sp_mc_mdb_entry_{init, fini}() Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 08/10] mlxsw: spectrum_switchdev: Add support for getting and putting MDB entry Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 09/10] mlxsw: spectrum_switchdev: Flush port from MDB entries according to FID index Ido Schimmel
2022-06-29  9:40 ` [PATCH net-next 10/10] mlxsw: spectrum_switchdev: Convert MDB code to use PGT APIs Ido Schimmel
2022-06-29 12:50 ` [PATCH net-next 00/10] mlxsw: Unified bridge conversion - part 5/6 patchwork-bot+netdevbpf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.