All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6
@ 2022-06-27  7:06 Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 01/13] mlxsw: spectrum: Add a temporary variable to indicate bridge model Ido Schimmel
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

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

Unlike previous parts that prepared mlxsw for the conversion, this part
actually starts the conversion. It focuses on flooding configuration and
converts mlxsw to the more "raw" APIs of the unified bridge model.

The patches configure the different stages of the flooding pipeline in
Spectrum that looks as follows (at a high-level):

         +------------+                +----------+           +-------+
  {FID,  |            | {Packet type,  |          |           |       |  MID
   DMAC} | FDB lookup |  Bridge type}  |   SFGC   | MID base  |       | Index
+-------->   (miss)   +----------------> register +-----------> Adder +------->
         |            |                |          |           |       |
         |            |                |          |           |       |
         +------------+                +----+-----+           +---^---+
                                            |                     |
                                    Table   |                     |
                                     type   |                     | Offset
                                            |      +-------+      |
                                            |      |       |      |
                                            |      |       |      |
                                            +----->+  Mux  +------+
                                                   |       |
                                                   |       |
                                                   +-^---^-+
                                                     |   |
                                                  FID|   |FID
                                                     |   |offset
                                                     +   +

The multicast identifier (MID) index is used as an index to the port
group table (PGT) that contains a bitmap of ports via which a packet
needs to be replicated.

From the PGT table, the packet continues to the multicast port egress
(MPE) table that determines the packet's egress VLAN. This is a
two-dimensional table that is indexed by port and switch multicast port
to egress (SMPE) index. The latter can be thought of as a FID. Without
it, all the packets replicated via a certain port would get the same
VLAN, regardless of the bridge domain (FID).

Logically, these two steps look as follows:

                     PGT table                           MPE table
             +-----------------------+               +---------------+
             |                       | {Local port,  |               | Egress
  MID index  | Local ports bitmap #1 |  SMPE index}  |               |  VID
+------------>        ...            +--------------->               +-------->
             | Local ports bitmap #N |               |               |
             |                       |          SMPE |               |
             +-----------------------+               +---------------+
                                                        Local port

Patchset overview:

Patch #1 adds a variable to guard against mixed model configuration.
Will be removed in part 6 when mlxsw is fully converted to the unified
model.

Patches #2-#5 introduce two new FID attributes required for flooding
configuration in the new model:

1. 'flood_rsp': Instructs the firmware to handle flooding configuration
for this FID. Only set for router FIDs (rFIDs) which are used to connect
a {Port, VLAN} to the router block.

2. 'bridge_type': Allows the device to determine the flood table (i.e.,
base index to the PGT table) for the FID. The first type will be used
for FIDs in a VLAN-aware bridge and the second for FIDs representing
VLAN-unaware bridges.

Patch #6 configures the MPE table that determines the egress VLAN of a
packet that is forwarded according to L2 multicast / flood.

Patches #7-#11 add the PGT table and related APIs to allocate entries
and set / clear ports in them.

Patches #12-#13 convert the flooding configuration to use the new PGT
APIs.

Amit Cohen (13):
  mlxsw: spectrum: Add a temporary variable to indicate bridge model
  mlxsw: spectrum_fid: Configure flooding table type for rFID
  mlxsw: Prepare 'bridge_type' field for SFMR usage
  mlxsw: spectrum_fid: Store 'bridge_type' as part of FID family
  mlxsw: Set flood bridge type for FIDs
  mlxsw: spectrum_fid: Configure egress VID classification for multicast
  mlxsw: Add an initial PGT table support
  mlxsw: Add an indication of SMPE index validity for PGT table
  mlxsw: Add a dedicated structure for bitmap of ports
  mlxsw: Extend PGT APIs to support maintaining list of ports per entry
  mlxsw: spectrum: Initialize PGT table
  mlxsw: spectrum_fid: Set 'mid_base' as part of flood tables
    initialization
  mlxsw: spectrum_fid: Configure flooding entries using PGT APIs

 drivers/net/ethernet/mellanox/mlxsw/Makefile  |   3 +-
 drivers/net/ethernet/mellanox/mlxsw/reg.h     |  17 +-
 .../net/ethernet/mellanox/mlxsw/resources.h   |   2 +
 .../net/ethernet/mellanox/mlxsw/spectrum.c    |  14 +
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  41 ++
 .../ethernet/mellanox/mlxsw/spectrum_fid.c    | 147 +++++++-
 .../ethernet/mellanox/mlxsw/spectrum_pgt.c    | 351 ++++++++++++++++++
 .../mellanox/mlxsw/spectrum_switchdev.c       |  37 +-
 8 files changed, 572 insertions(+), 40 deletions(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c

-- 
2.36.1


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

* [PATCH net-next 01/13] mlxsw: spectrum: Add a temporary variable to indicate bridge model
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 02/13] mlxsw: spectrum_fid: Configure flooding table type for rFID Ido Schimmel
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

As part of transition to unified bridge model, many different firmware
configurations are done.

Some of the configuration that needs to be done for the unified bridge
model is not valid under the legacy model, and would be rejected by the
firmware. At the same time, the driver cannot switch to the unified bridge
model until all of the code has been converted.

To allow breaking the change into patches, and to not break driver
behavior during the transition, add a boolean variable to indicate bridge
model. Then, forbidden configurations will be skipped using the check -
"if (!mlxsw_sp->ubridge)".

The new variable is temporary for several sets, it will be removed when
firmware will be configured to work with unified bridge model.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index e58acd397edf..6b17fa9ab9c7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3155,6 +3155,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 		goto err_ports_create;
 	}
 
+	mlxsw_sp->ubridge = false;
 	return 0;
 
 err_ports_create:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 80006a631333..828d5a265157 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -216,6 +216,7 @@ struct mlxsw_sp {
 	u32 lowest_shaper_bs;
 	struct rhashtable ipv6_addr_ht;
 	struct mutex ipv6_addr_ht_lock; /* Protects ipv6_addr_ht */
+	bool ubridge;
 };
 
 struct mlxsw_sp_ptp_ops {
-- 
2.36.1


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

* [PATCH net-next 02/13] mlxsw: spectrum_fid: Configure flooding table type for rFID
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 01/13] mlxsw: spectrum: Add a temporary variable to indicate bridge model Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 03/13] mlxsw: Prepare 'bridge_type' field for SFMR usage Ido Schimmel
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Using unified bridge model, RITR register no longer configures the rFID
used for sub-port RIFs. It needs to be created by software via SFMR. Such
FIDs need to be created with a special flood indication using
'SFMR.flood_rsp=1'. It means that for such FIDs, router sub-port flooding
table will be used, this table is configured by firmware.

Set the above mentioned field as part of FID initialization and FID
edition, so then when other fields will be updated in SFMR, this field
will store the correct value and will not be overwritten.

Add 'flood_rsp' variable to 'struct mlxsw_sp_fid_family', set it to true
for rFID and to false for the rest.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h          |  3 ++-
 drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c | 14 ++++++++++++--
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 7961f0c55fa6..80a02ba788bb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -1960,7 +1960,7 @@ MLXSW_ITEM32(reg, sfmr, smpe, 0x28, 0, 16);
 
 static inline void mlxsw_reg_sfmr_pack(char *payload,
 				       enum mlxsw_reg_sfmr_op op, u16 fid,
-				       u16 fid_offset)
+				       u16 fid_offset, bool flood_rsp)
 {
 	MLXSW_REG_ZERO(sfmr, payload);
 	mlxsw_reg_sfmr_op_set(payload, op);
@@ -1968,6 +1968,7 @@ static inline void mlxsw_reg_sfmr_pack(char *payload,
 	mlxsw_reg_sfmr_fid_offset_set(payload, fid_offset);
 	mlxsw_reg_sfmr_vtfp_set(payload, false);
 	mlxsw_reg_sfmr_vv_set(payload, false);
+	mlxsw_reg_sfmr_flood_rsp_set(payload, flood_rsp);
 }
 
 /* SPVMLR - Switch Port VLAN MAC Learning Register
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index fb04fbec7c82..b67b51addb7d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -109,6 +109,7 @@ struct mlxsw_sp_fid_family {
 	enum mlxsw_sp_rif_type rif_type;
 	const struct mlxsw_sp_fid_ops *ops;
 	struct mlxsw_sp *mlxsw_sp;
+	bool flood_rsp;
 };
 
 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
@@ -422,9 +423,13 @@ static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
 {
 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
+	bool flood_rsp = false;
+
+	if (mlxsw_sp->ubridge)
+		flood_rsp = fid->fid_family->flood_rsp;
 
 	mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
-			    fid->fid_offset);
+			    fid->fid_offset, flood_rsp);
 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
 }
 
@@ -432,9 +437,13 @@ static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid)
 {
 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
+	bool flood_rsp = false;
+
+	if (mlxsw_sp->ubridge)
+		flood_rsp = fid->fid_family->flood_rsp;
 
 	mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
-			    fid->fid_index, fid->fid_offset);
+			    fid->fid_index, fid->fid_offset, flood_rsp);
 	mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
 	mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
 	mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
@@ -898,6 +907,7 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_rfid_family = {
 	.end_index		= MLXSW_SP_RFID_BASE + MLXSW_SP_RFID_MAX - 1,
 	.rif_type		= MLXSW_SP_RIF_TYPE_SUBPORT,
 	.ops			= &mlxsw_sp_fid_rfid_ops,
+	.flood_rsp		= true,
 };
 
 static void mlxsw_sp_fid_dummy_setup(struct mlxsw_sp_fid *fid, const void *arg)
-- 
2.36.1


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

* [PATCH net-next 03/13] mlxsw: Prepare 'bridge_type' field for SFMR usage
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 01/13] mlxsw: spectrum: Add a temporary variable to indicate bridge model Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 02/13] mlxsw: spectrum_fid: Configure flooding table type for rFID Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 04/13] mlxsw: spectrum_fid: Store 'bridge_type' as part of FID family Ido Schimmel
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Under the legacy bridge model, the field 'bridge_type' is used only
in SFGC register, to determine the type of flood table (FID/FID offset).

Under the unified bridge model, it will be used also in SFMR register.
When a BUM packet needs to be flooded, SFGC is used to provide the
'mid_base' for PGT table. The access to SFGC is by
{packet type, bridge type}. Under the unified bridge model, software is
responsible for configuring 'bridge_type' as part of SFMR.

As preparation for the new required configuration, rename
'enum mlxsw_reg_sfgc_bridge_type' to 'enum mlxsw_reg_bridge_type'. Then
it can be used also in SFMR. In addition, align the names of the values to
internal documentation.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h          | 9 +++++----
 drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c | 8 ++++----
 2 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 80a02ba788bb..e198ee7365b5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -1054,9 +1054,10 @@ enum mlxsw_reg_sfgc_type {
  */
 MLXSW_ITEM32(reg, sfgc, type, 0x00, 0, 4);
 
-enum mlxsw_reg_sfgc_bridge_type {
-	MLXSW_REG_SFGC_BRIDGE_TYPE_1Q_FID = 0,
-	MLXSW_REG_SFGC_BRIDGE_TYPE_VFID = 1,
+/* bridge_type is used in SFGC and SFMR. */
+enum mlxsw_reg_bridge_type {
+	MLXSW_REG_BRIDGE_TYPE_0 = 0, /* Used for .1q FIDs. */
+	MLXSW_REG_BRIDGE_TYPE_1 = 1, /* Used for .1d FIDs. */
 };
 
 /* reg_sfgc_bridge_type
@@ -1111,7 +1112,7 @@ MLXSW_ITEM32(reg, sfgc, mid_base, 0x10, 0, 16);
 
 static inline void
 mlxsw_reg_sfgc_pack(char *payload, enum mlxsw_reg_sfgc_type type,
-		    enum mlxsw_reg_sfgc_bridge_type bridge_type,
+		    enum mlxsw_reg_bridge_type bridge_type,
 		    enum mlxsw_flood_table_type table_type,
 		    unsigned int flood_table)
 {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index b67b51addb7d..ef4d8ddb2a12 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -71,7 +71,7 @@ static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
 
 struct mlxsw_sp_flood_table {
 	enum mlxsw_sp_flood_type packet_type;
-	enum mlxsw_reg_sfgc_bridge_type bridge_type;
+	enum mlxsw_reg_bridge_type bridge_type;
 	enum mlxsw_flood_table_type table_type;
 	int table_index;
 };
@@ -709,19 +709,19 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
 	{
 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
-		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
+		.bridge_type	= MLXSW_REG_BRIDGE_TYPE_1,
 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
 		.table_index	= 0,
 	},
 	{
 		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
-		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
+		.bridge_type	= MLXSW_REG_BRIDGE_TYPE_1,
 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
 		.table_index	= 1,
 	},
 	{
 		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
-		.bridge_type	= MLXSW_REG_SFGC_BRIDGE_TYPE_VFID,
+		.bridge_type	= MLXSW_REG_BRIDGE_TYPE_1,
 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
 		.table_index	= 2,
 	},
-- 
2.36.1


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

* [PATCH net-next 04/13] mlxsw: spectrum_fid: Store 'bridge_type' as part of FID family
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (2 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 03/13] mlxsw: Prepare 'bridge_type' field for SFMR usage Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 05/13] mlxsw: Set flood bridge type for FIDs Ido Schimmel
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Currently, 'bridge_type' is an attribute of 'struct mlxsw_sp_flood_table',
which is defined per FID family. Instead, it can be an attribute of
'struct mlxsw_sp_fid_family' as all flood tables in the same family are of
the same type. This change will ease the configuration of
'SFMR.flood_bridge_type' which will be added in the next patch.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index ef4d8ddb2a12..279e65a5fad2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -71,7 +71,6 @@ static const struct rhashtable_params mlxsw_sp_fid_vni_ht_params = {
 
 struct mlxsw_sp_flood_table {
 	enum mlxsw_sp_flood_type packet_type;
-	enum mlxsw_reg_bridge_type bridge_type;
 	enum mlxsw_flood_table_type table_type;
 	int table_index;
 };
@@ -110,6 +109,7 @@ struct mlxsw_sp_fid_family {
 	const struct mlxsw_sp_fid_ops *ops;
 	struct mlxsw_sp *mlxsw_sp;
 	bool flood_rsp;
+	enum mlxsw_reg_bridge_type bridge_type;
 };
 
 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
@@ -709,19 +709,16 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
 	{
 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
-		.bridge_type	= MLXSW_REG_BRIDGE_TYPE_1,
 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
 		.table_index	= 0,
 	},
 	{
 		.packet_type	= MLXSW_SP_FLOOD_TYPE_MC,
-		.bridge_type	= MLXSW_REG_BRIDGE_TYPE_1,
 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
 		.table_index	= 1,
 	},
 	{
 		.packet_type	= MLXSW_SP_FLOOD_TYPE_BC,
-		.bridge_type	= MLXSW_REG_BRIDGE_TYPE_1,
 		.table_type	= MLXSW_REG_SFGC_TABLE_TYPE_FID,
 		.table_index	= 2,
 	},
@@ -737,6 +734,7 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
 	.ops			= &mlxsw_sp_fid_8021d_ops,
+	.bridge_type		= MLXSW_REG_BRIDGE_TYPE_1,
 };
 
 static bool
@@ -785,6 +783,7 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
 	.nr_flood_tables	= ARRAY_SIZE(mlxsw_sp_fid_8021d_flood_tables),
 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN_EMU,
 	.ops			= &mlxsw_sp_fid_8021q_emu_ops,
+	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
 };
 
 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
@@ -1132,7 +1131,7 @@ mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
 
 		if (!sfgc_packet_types[i])
 			continue;
-		mlxsw_reg_sfgc_pack(sfgc_pl, i, flood_table->bridge_type,
+		mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
 				    flood_table->table_type,
 				    flood_table->table_index);
 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
-- 
2.36.1


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

* [PATCH net-next 05/13] mlxsw: Set flood bridge type for FIDs
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (3 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 04/13] mlxsw: spectrum_fid: Store 'bridge_type' as part of FID family Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 06/13] mlxsw: spectrum_fid: Configure egress VID classification for multicast Ido Schimmel
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

In the unified bridge model, the bridge type FID attribute is no longer
configured by the firmware, but instead by software when creating and
editing a FID via SFMR register.

Set this field as part of FID creation and edition flow. Default to 0
(reserved) as long as the driver operates in the legacy bridge model.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h         |  4 +++-
 .../net/ethernet/mellanox/mlxsw/spectrum_fid.c    | 15 +++++++++++----
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index e198ee7365b5..d0ebb565b5cd 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -1961,7 +1961,8 @@ MLXSW_ITEM32(reg, sfmr, smpe, 0x28, 0, 16);
 
 static inline void mlxsw_reg_sfmr_pack(char *payload,
 				       enum mlxsw_reg_sfmr_op op, u16 fid,
-				       u16 fid_offset, bool flood_rsp)
+				       u16 fid_offset, bool flood_rsp,
+				       enum mlxsw_reg_bridge_type bridge_type)
 {
 	MLXSW_REG_ZERO(sfmr, payload);
 	mlxsw_reg_sfmr_op_set(payload, op);
@@ -1970,6 +1971,7 @@ static inline void mlxsw_reg_sfmr_pack(char *payload,
 	mlxsw_reg_sfmr_vtfp_set(payload, false);
 	mlxsw_reg_sfmr_vv_set(payload, false);
 	mlxsw_reg_sfmr_flood_rsp_set(payload, flood_rsp);
+	mlxsw_reg_sfmr_flood_bridge_type_set(payload, bridge_type);
 }
 
 /* SPVMLR - Switch Port VLAN MAC Learning Register
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index 279e65a5fad2..3335d744f870 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -422,28 +422,35 @@ static enum mlxsw_reg_sfmr_op mlxsw_sp_sfmr_op(bool valid)
 static int mlxsw_sp_fid_op(const struct mlxsw_sp_fid *fid, bool valid)
 {
 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
+	enum mlxsw_reg_bridge_type bridge_type = 0;
 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
 	bool flood_rsp = false;
 
-	if (mlxsw_sp->ubridge)
+	if (mlxsw_sp->ubridge) {
 		flood_rsp = fid->fid_family->flood_rsp;
+		bridge_type = fid->fid_family->bridge_type;
+	}
 
 	mlxsw_reg_sfmr_pack(sfmr_pl, mlxsw_sp_sfmr_op(valid), fid->fid_index,
-			    fid->fid_offset, flood_rsp);
+			    fid->fid_offset, flood_rsp, bridge_type);
 	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfmr), sfmr_pl);
 }
 
 static int mlxsw_sp_fid_edit_op(const struct mlxsw_sp_fid *fid)
 {
 	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
+	enum mlxsw_reg_bridge_type bridge_type = 0;
 	char sfmr_pl[MLXSW_REG_SFMR_LEN];
 	bool flood_rsp = false;
 
-	if (mlxsw_sp->ubridge)
+	if (mlxsw_sp->ubridge) {
 		flood_rsp = fid->fid_family->flood_rsp;
+		bridge_type = fid->fid_family->bridge_type;
+	}
 
 	mlxsw_reg_sfmr_pack(sfmr_pl, MLXSW_REG_SFMR_OP_CREATE_FID,
-			    fid->fid_index, fid->fid_offset, flood_rsp);
+			    fid->fid_index, fid->fid_offset, flood_rsp,
+			    bridge_type);
 	mlxsw_reg_sfmr_vv_set(sfmr_pl, fid->vni_valid);
 	mlxsw_reg_sfmr_vni_set(sfmr_pl, be32_to_cpu(fid->vni));
 	mlxsw_reg_sfmr_vtfp_set(sfmr_pl, fid->nve_flood_index_valid);
-- 
2.36.1


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

* [PATCH net-next 06/13] mlxsw: spectrum_fid: Configure egress VID classification for multicast
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (4 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 05/13] mlxsw: Set flood bridge type for FIDs Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 07/13] mlxsw: Add an initial PGT table support Ido Schimmel
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

The device includes two main tables to support layer 2 multicast (i.e.,
MDB and flooding). These are the PGT (Port Group Table) table and the MPE
(Multicast Port Egress) table.
- PGT is {MID -> (bitmap of local_port, SPME index)}
- MPE is {(Local port, SMPE index) -> eVID}

In the legacy model, software did not interact with MPE table as it was
completely hidden in firmware. In the new model, software needs to
populate the table itself in order to map from {Local port, SMPE} to an
egress VID. This is done using the SMPE register.

Configure SMPE register when a {Local port, VID} are mapped/unmapped to a
802.1d and 802.1q emulated FIDs. The MPE table is not relevant for rFIDs as
firmware handles their flooding.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_fid.c    | 23 +++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index 3335d744f870..a82612a894eb 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -622,6 +622,18 @@ mlxsw_sp_fid_port_vid_list_del(struct mlxsw_sp_fid *fid, u16 local_port,
 	}
 }
 
+static int
+mlxsw_sp_fid_mpe_table_map(const struct mlxsw_sp_fid *fid, u16 local_port,
+			   u16 vid, bool valid)
+{
+	struct mlxsw_sp *mlxsw_sp = fid->fid_family->mlxsw_sp;
+	char smpe_pl[MLXSW_REG_SMPE_LEN];
+
+	mlxsw_reg_smpe_pack(smpe_pl, local_port, fid->fid_index,
+			    valid ? vid : 0);
+	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(smpe), smpe_pl);
+}
+
 static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
 					   struct mlxsw_sp_port *mlxsw_sp_port,
 					   u16 vid)
@@ -635,6 +647,12 @@ static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
 	if (err)
 		return err;
 
+	if (fid->fid_family->mlxsw_sp->ubridge) {
+		err = mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, true);
+		if (err)
+			goto err_mpe_table_map;
+	}
+
 	err = mlxsw_sp_fid_port_vid_list_add(fid, mlxsw_sp_port->local_port,
 					     vid);
 	if (err)
@@ -652,6 +670,9 @@ static int mlxsw_sp_fid_8021d_port_vid_map(struct mlxsw_sp_fid *fid,
 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
 err_port_vid_list_add:
+	if (fid->fid_family->mlxsw_sp->ubridge)
+		mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, false);
+err_mpe_table_map:
 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
 	return err;
 }
@@ -667,6 +688,8 @@ mlxsw_sp_fid_8021d_port_vid_unmap(struct mlxsw_sp_fid *fid,
 		mlxsw_sp_port_vlan_mode_trans(mlxsw_sp_port);
 	mlxsw_sp->fid_core->port_fid_mappings[local_port]--;
 	mlxsw_sp_fid_port_vid_list_del(fid, mlxsw_sp_port->local_port, vid);
+	if (fid->fid_family->mlxsw_sp->ubridge)
+		mlxsw_sp_fid_mpe_table_map(fid, local_port, vid, false);
 	__mlxsw_sp_fid_port_vid_map(fid, mlxsw_sp_port->local_port, vid, false);
 }
 
-- 
2.36.1


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

* [PATCH net-next 07/13] mlxsw: Add an initial PGT table support
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (5 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 06/13] mlxsw: spectrum_fid: Configure egress VID classification for multicast Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 08/13] mlxsw: Add an indication of SMPE index validity for PGT table Ido Schimmel
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

The PGT (Port Group Table) table maps an index to a bitmap of local ports
to which a packet needs to be replicated. This table is used for layer 2
multicast and flooding.

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, the SFTR register is deprecated and
software has full control over the PGT table using the SMID register.

The entire state of the PGT table needs to be maintained in software
because member ports in a PGT entry needs to be reference counted to avoid
releasing entries which are still in use.

Add the following APIs:
1. mlxsw_sp_pgt_{init, fini}() - allocate/free the PGT table.
2. mlxsw_sp_pgt_mid_alloc_range() - allocate a range of MID indexes in PGT.
   To be used by FID code during initialization to reserve specific PGT
   indexes for flooding entries.
3. mlxsw_sp_pgt_mid_free_range() - free indexes in a given range.
4. mlxsw_sp_pgt_mid_alloc() - allocate one MID index in the PGT at a
   non-specific range, just search for free index. To be used by MDB code.
5. mlxsw_sp_pgt_mid_free() - free the given index.

Note that alloc() functions do not allocate the entries in software, just
allocate IDs using 'idr'.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/Makefile  |   3 +-
 .../net/ethernet/mellanox/mlxsw/resources.h   |   2 +
 .../net/ethernet/mellanox/mlxsw/spectrum.h    |  12 ++
 .../ethernet/mellanox/mlxsw/spectrum_pgt.c    | 120 ++++++++++++++++++
 4 files changed, 136 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c

diff --git a/drivers/net/ethernet/mellanox/mlxsw/Makefile b/drivers/net/ethernet/mellanox/mlxsw/Makefile
index c57e293cca25..c2d6d64ffe4b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Makefile
+++ b/drivers/net/ethernet/mellanox/mlxsw/Makefile
@@ -28,7 +28,8 @@ mlxsw_spectrum-objs		:= spectrum.o spectrum_buffers.o \
 				   spectrum_qdisc.o spectrum_span.o \
 				   spectrum_nve.o spectrum_nve_vxlan.o \
 				   spectrum_dpipe.o spectrum_trap.o \
-				   spectrum_ethtool.o spectrum_policer.o
+				   spectrum_ethtool.o spectrum_policer.o \
+				   spectrum_pgt.o
 mlxsw_spectrum-$(CONFIG_MLXSW_SPECTRUM_DCB)	+= spectrum_dcb.o
 mlxsw_spectrum-$(CONFIG_PTP_1588_CLOCK)		+= spectrum_ptp.o
 obj-$(CONFIG_MLXSW_MINIMAL)	+= mlxsw_minimal.o
diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h
index daacf6291253..826e47fb4586 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/resources.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h
@@ -11,6 +11,7 @@ enum mlxsw_res_id {
 	MLXSW_RES_ID_KVD_SIZE,
 	MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE,
 	MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE,
+	MLXSW_RES_ID_PGT_SIZE,
 	MLXSW_RES_ID_MAX_KVD_LINEAR_RANGE,
 	MLXSW_RES_ID_MAX_KVD_ACTION_SETS,
 	MLXSW_RES_ID_MAX_TRAP_GROUPS,
@@ -69,6 +70,7 @@ static u16 mlxsw_res_ids[] = {
 	[MLXSW_RES_ID_KVD_SIZE] = 0x1001,
 	[MLXSW_RES_ID_KVD_SINGLE_MIN_SIZE] = 0x1002,
 	[MLXSW_RES_ID_KVD_DOUBLE_MIN_SIZE] = 0x1003,
+	[MLXSW_RES_ID_PGT_SIZE] = 0x1004,
 	[MLXSW_RES_ID_MAX_KVD_LINEAR_RANGE] = 0x1005,
 	[MLXSW_RES_ID_MAX_KVD_ACTION_SETS] = 0x1007,
 	[MLXSW_RES_ID_MAX_TRAP_GROUPS] = 0x2201,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 828d5a265157..b42b23d09ab2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -143,6 +143,7 @@ struct mlxsw_sp_ptp_ops;
 struct mlxsw_sp_span_ops;
 struct mlxsw_sp_qdisc_state;
 struct mlxsw_sp_mall_entry;
+struct mlxsw_sp_pgt;
 
 struct mlxsw_sp_port_mapping {
 	u8 module;
@@ -217,6 +218,7 @@ struct mlxsw_sp {
 	struct rhashtable ipv6_addr_ht;
 	struct mutex ipv6_addr_ht_lock; /* Protects ipv6_addr_ht */
 	bool ubridge;
+	struct mlxsw_sp_pgt *pgt;
 };
 
 struct mlxsw_sp_ptp_ops {
@@ -1448,4 +1450,14 @@ int mlxsw_sp_policers_init(struct mlxsw_sp *mlxsw_sp);
 void mlxsw_sp_policers_fini(struct mlxsw_sp *mlxsw_sp);
 int mlxsw_sp_policer_resources_register(struct mlxsw_core *mlxsw_core);
 
+/* spectrum_pgt.c */
+int mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid);
+void mlxsw_sp_pgt_mid_free(struct mlxsw_sp *mlxsw_sp, u16 mid_base);
+int mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
+				 u16 count);
+void mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
+				 u16 count);
+int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_pgt_fini(struct mlxsw_sp *mlxsw_sp);
+
 #endif
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
new file mode 100644
index 000000000000..27db277bc906
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
@@ -0,0 +1,120 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include <linux/refcount.h>
+#include <linux/idr.h>
+
+#include "spectrum.h"
+#include "reg.h"
+
+struct mlxsw_sp_pgt {
+	struct idr pgt_idr;
+	u16 end_index; /* Exclusive. */
+	struct mutex lock; /* Protects PGT. */
+};
+
+int mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid)
+{
+	int index, err = 0;
+
+	mutex_lock(&mlxsw_sp->pgt->lock);
+	index = idr_alloc(&mlxsw_sp->pgt->pgt_idr, NULL, 0,
+			  mlxsw_sp->pgt->end_index, GFP_KERNEL);
+
+	if (index < 0) {
+		err = index;
+		goto err_idr_alloc;
+	}
+
+	*p_mid = index;
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+	return 0;
+
+err_idr_alloc:
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+	return err;
+}
+
+void mlxsw_sp_pgt_mid_free(struct mlxsw_sp *mlxsw_sp, u16 mid_base)
+{
+	mutex_lock(&mlxsw_sp->pgt->lock);
+	WARN_ON(idr_remove(&mlxsw_sp->pgt->pgt_idr, mid_base));
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+}
+
+int
+mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
+{
+	unsigned int idr_cursor;
+	int i, err;
+
+	mutex_lock(&mlxsw_sp->pgt->lock);
+
+	/* This function is supposed to be called several times as part of
+	 * driver init, in specific order. Verify that the mid_index is the
+	 * first free index in the idr, to be able to free the indexes in case
+	 * of error.
+	 */
+	idr_cursor = idr_get_cursor(&mlxsw_sp->pgt->pgt_idr);
+	if (WARN_ON(idr_cursor != mid_base)) {
+		err = -EINVAL;
+		goto err_idr_cursor;
+	}
+
+	for (i = 0; i < count; i++) {
+		err = idr_alloc_cyclic(&mlxsw_sp->pgt->pgt_idr, NULL,
+				       mid_base, mid_base + count, GFP_KERNEL);
+		if (err < 0)
+			goto err_idr_alloc_cyclic;
+	}
+
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+	return 0;
+
+err_idr_alloc_cyclic:
+	for (i--; i >= 0; i--)
+		idr_remove(&mlxsw_sp->pgt->pgt_idr, mid_base + i);
+err_idr_cursor:
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+	return err;
+}
+
+void
+mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
+{
+	struct idr *pgt_idr = &mlxsw_sp->pgt->pgt_idr;
+	int i;
+
+	mutex_lock(&mlxsw_sp->pgt->lock);
+
+	for (i = 0; i < count; i++)
+		WARN_ON_ONCE(idr_remove(pgt_idr, mid_base + i));
+
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+}
+
+int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp)
+{
+	struct mlxsw_sp_pgt *pgt;
+
+	if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, PGT_SIZE))
+		return -EIO;
+
+	pgt = kzalloc(sizeof(*mlxsw_sp->pgt), GFP_KERNEL);
+	if (!pgt)
+		return -ENOMEM;
+
+	idr_init(&pgt->pgt_idr);
+	pgt->end_index = MLXSW_CORE_RES_GET(mlxsw_sp->core, PGT_SIZE);
+	mutex_init(&pgt->lock);
+	mlxsw_sp->pgt = pgt;
+	return 0;
+}
+
+void mlxsw_sp_pgt_fini(struct mlxsw_sp *mlxsw_sp)
+{
+	mutex_destroy(&mlxsw_sp->pgt->lock);
+	WARN_ON(!idr_is_empty(&mlxsw_sp->pgt->pgt_idr));
+	idr_destroy(&mlxsw_sp->pgt->pgt_idr);
+	kfree(mlxsw_sp->pgt);
+}
-- 
2.36.1


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

* [PATCH net-next 08/13] mlxsw: Add an indication of SMPE index validity for PGT table
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (6 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 07/13] mlxsw: Add an initial PGT table support Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 09/13] mlxsw: Add a dedicated structure for bitmap of ports Ido Schimmel
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

In Spectrum-1, the index into the MPE table - called switch multicast to
port egress VID (SMPE) - is derived from the PGT entry, whereas in
Spectrum-2 and later ASICs it is derived from the FID.

Therefore, in Spectrum-1, the SMPE index needs to be programmed as part of
the PGT entry via SMID register, while it is reserved for Spectrum-2 and
later ASICs.

Add 'pgt_smpe_index_valid' boolean as part of 'struct mlxsw_sp' and set
it to true for Spectrum-1 and to false for the later ASICs. Add
'smpe_index_valid' as part of 'struct mlxsw_sp_pgt' and set it according
to the value in 'struct mlxsw_sp' as part of PGT initialization.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 6b17fa9ab9c7..b128f900d0fe 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3235,6 +3235,7 @@ static int mlxsw_sp1_init(struct mlxsw_core *mlxsw_core,
 	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp1_listener);
 	mlxsw_sp->fid_family_arr = mlxsw_sp1_fid_family_arr;
 	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP1;
+	mlxsw_sp->pgt_smpe_index_valid = true;
 
 	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
 }
@@ -3268,6 +3269,7 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
 	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
 	mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr;
 	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP2;
+	mlxsw_sp->pgt_smpe_index_valid = false;
 
 	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
 }
@@ -3301,6 +3303,7 @@ static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
 	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
 	mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr;
 	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP3;
+	mlxsw_sp->pgt_smpe_index_valid = false;
 
 	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
 }
@@ -3334,6 +3337,7 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core,
 	mlxsw_sp->listeners_count = ARRAY_SIZE(mlxsw_sp2_listener);
 	mlxsw_sp->fid_family_arr = mlxsw_sp2_fid_family_arr;
 	mlxsw_sp->lowest_shaper_bs = MLXSW_REG_QEEC_LOWEST_SHAPER_BS_SP4;
+	mlxsw_sp->pgt_smpe_index_valid = false;
 
 	return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
 }
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index b42b23d09ab2..600089364575 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -219,6 +219,7 @@ struct mlxsw_sp {
 	struct mutex ipv6_addr_ht_lock; /* Protects ipv6_addr_ht */
 	bool ubridge;
 	struct mlxsw_sp_pgt *pgt;
+	bool pgt_smpe_index_valid;
 };
 
 struct mlxsw_sp_ptp_ops {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
index 27db277bc906..0fc29d486efc 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
@@ -11,6 +11,7 @@ struct mlxsw_sp_pgt {
 	struct idr pgt_idr;
 	u16 end_index; /* Exclusive. */
 	struct mutex lock; /* Protects PGT. */
+	bool smpe_index_valid;
 };
 
 int mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid)
@@ -107,6 +108,7 @@ int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp)
 	idr_init(&pgt->pgt_idr);
 	pgt->end_index = MLXSW_CORE_RES_GET(mlxsw_sp->core, PGT_SIZE);
 	mutex_init(&pgt->lock);
+	pgt->smpe_index_valid = mlxsw_sp->pgt_smpe_index_valid;
 	mlxsw_sp->pgt = pgt;
 	return 0;
 }
-- 
2.36.1


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

* [PATCH net-next 09/13] mlxsw: Add a dedicated structure for bitmap of ports
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (7 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 08/13] mlxsw: Add an indication of SMPE index validity for PGT table Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 10/13] mlxsw: Extend PGT APIs to support maintaining list of ports per entry Ido Schimmel
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Currently when bitmap of ports is needed, 'unsigned long *' type is
used. The functions which use the bitmap assume its length according to
its name, i.e., each function which gets a bitmap of ports queries the
maximum number of ports and uses it as the size.

As preparation for the next patch which will use bitmap of ports, add a
dedicated structure for it. Refactor the existing code to use the new
structure.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 600089364575..645244ac5dfc 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -395,6 +395,31 @@ struct mlxsw_sp_port_type_speed_ops {
 	u32 (*ptys_proto_cap_masked_get)(u32 eth_proto_cap);
 };
 
+struct mlxsw_sp_ports_bitmap {
+	unsigned long *bitmap;
+	unsigned int nbits;
+};
+
+static inline int
+mlxsw_sp_port_bitmap_init(struct mlxsw_sp *mlxsw_sp,
+			  struct mlxsw_sp_ports_bitmap *ports_bm)
+{
+	unsigned int nbits = mlxsw_core_max_ports(mlxsw_sp->core);
+
+	ports_bm->nbits = nbits;
+	ports_bm->bitmap = bitmap_zalloc(nbits, GFP_KERNEL);
+	if (!ports_bm->bitmap)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static inline void
+mlxsw_sp_port_bitmap_fini(struct mlxsw_sp_ports_bitmap *ports_bm)
+{
+	bitmap_free(ports_bm->bitmap);
+}
+
 static inline u8 mlxsw_sp_tunnel_ecn_decap(u8 outer_ecn, u8 inner_ecn,
 					   bool *trap_en)
 {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 863c8055746b..e153b6f2783a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1646,9 +1646,10 @@ static int mlxsw_sp_port_mdb_op(struct mlxsw_sp *mlxsw_sp, const char *addr,
 	return err;
 }
 
-static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp, u16 mid_idx,
-					 long *ports_bitmap,
-					 bool set_router_port)
+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;
@@ -1666,7 +1667,7 @@ static int mlxsw_sp_port_smid_full_entry(struct mlxsw_sp *mlxsw_sp, u16 mid_idx,
 	mlxsw_reg_smid2_port_mask_set(smid2_pl,
 				      mlxsw_sp_router_port(mlxsw_sp), 1);
 
-	for_each_set_bit(i, ports_bitmap, mlxsw_core_max_ports(mlxsw_sp->core))
+	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),
@@ -1712,14 +1713,14 @@ mlxsw_sp_mid *__mlxsw_sp_mc_get(struct mlxsw_sp_bridge_device *bridge_device,
 static void
 mlxsw_sp_bridge_port_get_ports_bitmap(struct mlxsw_sp *mlxsw_sp,
 				      struct mlxsw_sp_bridge_port *bridge_port,
-				      unsigned long *ports_bitmap)
+				      struct mlxsw_sp_ports_bitmap *ports_bm)
 {
 	struct mlxsw_sp_port *mlxsw_sp_port;
 	u64 max_lag_members, i;
 	int lag_id;
 
 	if (!bridge_port->lagged) {
-		set_bit(bridge_port->system_port, ports_bitmap);
+		set_bit(bridge_port->system_port, ports_bm->bitmap);
 	} else {
 		max_lag_members = MLXSW_CORE_RES_GET(mlxsw_sp->core,
 						     MAX_LAG_MEMBERS);
@@ -1729,13 +1730,13 @@ mlxsw_sp_bridge_port_get_ports_bitmap(struct mlxsw_sp *mlxsw_sp,
 								 lag_id, i);
 			if (mlxsw_sp_port)
 				set_bit(mlxsw_sp_port->local_port,
-					ports_bitmap);
+					ports_bm->bitmap);
 		}
 	}
 }
 
 static void
-mlxsw_sp_mc_get_mrouters_bitmap(unsigned long *flood_bitmap,
+mlxsw_sp_mc_get_mrouters_bitmap(struct mlxsw_sp_ports_bitmap *flood_bm,
 				struct mlxsw_sp_bridge_device *bridge_device,
 				struct mlxsw_sp *mlxsw_sp)
 {
@@ -1745,7 +1746,7 @@ mlxsw_sp_mc_get_mrouters_bitmap(unsigned long *flood_bitmap,
 		if (bridge_port->mrouter) {
 			mlxsw_sp_bridge_port_get_ports_bitmap(mlxsw_sp,
 							      bridge_port,
-							      flood_bitmap);
+							      flood_bm);
 		}
 	}
 }
@@ -1755,8 +1756,7 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 			    struct mlxsw_sp_mid *mid,
 			    struct mlxsw_sp_bridge_device *bridge_device)
 {
-	long *flood_bitmap;
-	int num_of_ports;
+	struct mlxsw_sp_ports_bitmap flood_bitmap;
 	u16 mid_idx;
 	int err;
 
@@ -1765,18 +1765,17 @@ mlxsw_sp_mc_write_mdb_entry(struct mlxsw_sp *mlxsw_sp,
 	if (mid_idx == MLXSW_SP_MID_MAX)
 		return -ENOBUFS;
 
-	num_of_ports = mlxsw_core_max_ports(mlxsw_sp->core);
-	flood_bitmap = bitmap_alloc(num_of_ports, GFP_KERNEL);
-	if (!flood_bitmap)
-		return -ENOMEM;
+	err = mlxsw_sp_port_bitmap_init(mlxsw_sp, &flood_bitmap);
+	if (err)
+		return err;
 
-	bitmap_copy(flood_bitmap, mid->ports_in_mid, num_of_ports);
-	mlxsw_sp_mc_get_mrouters_bitmap(flood_bitmap, bridge_device, mlxsw_sp);
+	bitmap_copy(flood_bitmap.bitmap, mid->ports_in_mid, flood_bitmap.nbits);
+	mlxsw_sp_mc_get_mrouters_bitmap(&flood_bitmap, bridge_device, mlxsw_sp);
 
 	mid->mid = mid_idx;
-	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, flood_bitmap,
+	err = mlxsw_sp_port_smid_full_entry(mlxsw_sp, mid_idx, &flood_bitmap,
 					    bridge_device->mrouter);
-	bitmap_free(flood_bitmap);
+	mlxsw_sp_port_bitmap_fini(&flood_bitmap);
 	if (err)
 		return err;
 
-- 
2.36.1


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

* [PATCH net-next 10/13] mlxsw: Extend PGT APIs to support maintaining list of ports per entry
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (8 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 09/13] mlxsw: Add a dedicated structure for bitmap of ports Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 11/13] mlxsw: spectrum: Initialize PGT table Ido Schimmel
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Add an API to associate a PGT entry with SMPE index and add or remove a
port. This API will be used by FID code and MDB code, to add/remove port
from specific PGT entry.

When the first port is added to PGT entry, allocate the entry in the given
MID index, when the last port is removed from PGT entry, free it.

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

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 645244ac5dfc..b128692611d9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -1483,6 +1483,8 @@ int mlxsw_sp_pgt_mid_alloc_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base,
 				 u16 count);
 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);
 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 0fc29d486efc..3b7265b539b2 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_pgt.c
@@ -14,6 +14,17 @@ struct mlxsw_sp_pgt {
 	bool smpe_index_valid;
 };
 
+struct mlxsw_sp_pgt_entry {
+	struct list_head ports_list;
+	u16 index;
+	u16 smpe_index;
+};
+
+struct mlxsw_sp_pgt_entry_port {
+	struct list_head list; /* Member of 'ports_list'. */
+	u16 local_port;
+};
+
 int mlxsw_sp_pgt_mid_alloc(struct mlxsw_sp *mlxsw_sp, u16 *p_mid)
 {
 	int index, err = 0;
@@ -94,6 +105,224 @@ mlxsw_sp_pgt_mid_free_range(struct mlxsw_sp *mlxsw_sp, u16 mid_base, u16 count)
 	mutex_unlock(&mlxsw_sp->pgt->lock);
 }
 
+static struct mlxsw_sp_pgt_entry_port *
+mlxsw_sp_pgt_entry_port_lookup(struct mlxsw_sp_pgt_entry *pgt_entry,
+			       u16 local_port)
+{
+	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
+
+	list_for_each_entry(pgt_entry_port, &pgt_entry->ports_list, list) {
+		if (pgt_entry_port->local_port == local_port)
+			return pgt_entry_port;
+	}
+
+	return NULL;
+}
+
+static struct mlxsw_sp_pgt_entry *
+mlxsw_sp_pgt_entry_create(struct mlxsw_sp_pgt *pgt, u16 mid, u16 smpe)
+{
+	struct mlxsw_sp_pgt_entry *pgt_entry;
+	void *ret;
+	int err;
+
+	pgt_entry = kzalloc(sizeof(*pgt_entry), GFP_KERNEL);
+	if (!pgt_entry)
+		return ERR_PTR(-ENOMEM);
+
+	ret = idr_replace(&pgt->pgt_idr, pgt_entry, mid);
+	if (IS_ERR(ret)) {
+		err = PTR_ERR(ret);
+		goto err_idr_replace;
+	}
+
+	INIT_LIST_HEAD(&pgt_entry->ports_list);
+	pgt_entry->index = mid;
+	pgt_entry->smpe_index = smpe;
+	return pgt_entry;
+
+err_idr_replace:
+	kfree(pgt_entry);
+	return ERR_PTR(err);
+}
+
+static void mlxsw_sp_pgt_entry_destroy(struct mlxsw_sp_pgt *pgt,
+				       struct mlxsw_sp_pgt_entry *pgt_entry)
+{
+	WARN_ON(!list_empty(&pgt_entry->ports_list));
+
+	pgt_entry = idr_replace(&pgt->pgt_idr, NULL, pgt_entry->index);
+	if (WARN_ON(IS_ERR(pgt_entry)))
+		return;
+
+	kfree(pgt_entry);
+}
+
+static struct mlxsw_sp_pgt_entry *
+mlxsw_sp_pgt_entry_get(struct mlxsw_sp_pgt *pgt, u16 mid, u16 smpe)
+{
+	struct mlxsw_sp_pgt_entry *pgt_entry;
+
+	pgt_entry = idr_find(&pgt->pgt_idr, mid);
+	if (pgt_entry)
+		return pgt_entry;
+
+	return mlxsw_sp_pgt_entry_create(pgt, mid, smpe);
+}
+
+static void mlxsw_sp_pgt_entry_put(struct mlxsw_sp_pgt *pgt, u16 mid)
+{
+	struct mlxsw_sp_pgt_entry *pgt_entry;
+
+	pgt_entry = idr_find(&pgt->pgt_idr, mid);
+	if (WARN_ON(!pgt_entry))
+		return;
+
+	if (list_empty(&pgt_entry->ports_list))
+		mlxsw_sp_pgt_entry_destroy(pgt, pgt_entry);
+}
+
+static void mlxsw_sp_pgt_smid2_port_set(char *smid2_pl, u16 local_port,
+					bool member)
+{
+	mlxsw_reg_smid2_port_set(smid2_pl, local_port, member);
+	mlxsw_reg_smid2_port_mask_set(smid2_pl, local_port, 1);
+}
+
+static int
+mlxsw_sp_pgt_entry_port_write(struct mlxsw_sp *mlxsw_sp,
+			      const struct mlxsw_sp_pgt_entry *pgt_entry,
+			      u16 local_port, bool member)
+{
+	bool smpe_index_valid;
+	char *smid2_pl;
+	u16 smpe;
+	int err;
+
+	smid2_pl = kmalloc(MLXSW_REG_SMID2_LEN, GFP_KERNEL);
+	if (!smid2_pl)
+		return -ENOMEM;
+
+	smpe_index_valid = mlxsw_sp->ubridge ? mlxsw_sp->pgt->smpe_index_valid :
+			   false;
+	smpe = mlxsw_sp->ubridge ? pgt_entry->smpe_index : 0;
+
+	mlxsw_reg_smid2_pack(smid2_pl, pgt_entry->index, 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);
+
+	kfree(smid2_pl);
+
+	return err;
+}
+
+static struct mlxsw_sp_pgt_entry_port *
+mlxsw_sp_pgt_entry_port_create(struct mlxsw_sp *mlxsw_sp,
+			       struct mlxsw_sp_pgt_entry *pgt_entry,
+			       u16 local_port)
+{
+	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
+	int err;
+
+	pgt_entry_port = kzalloc(sizeof(*pgt_entry_port), GFP_KERNEL);
+	if (!pgt_entry_port)
+		return ERR_PTR(-ENOMEM);
+
+	err = mlxsw_sp_pgt_entry_port_write(mlxsw_sp, pgt_entry, local_port,
+					    true);
+	if (err)
+		goto err_pgt_entry_port_write;
+
+	pgt_entry_port->local_port = local_port;
+	list_add(&pgt_entry_port->list, &pgt_entry->ports_list);
+
+	return pgt_entry_port;
+
+err_pgt_entry_port_write:
+	kfree(pgt_entry_port);
+	return ERR_PTR(err);
+}
+
+static void
+mlxsw_sp_pgt_entry_port_destroy(struct mlxsw_sp *mlxsw_sp,
+				struct mlxsw_sp_pgt_entry *pgt_entry,
+				struct mlxsw_sp_pgt_entry_port *pgt_entry_port)
+
+{
+	list_del(&pgt_entry_port->list);
+	mlxsw_sp_pgt_entry_port_write(mlxsw_sp, pgt_entry,
+				      pgt_entry_port->local_port, false);
+	kfree(pgt_entry_port);
+}
+
+static int mlxsw_sp_pgt_entry_port_add(struct mlxsw_sp *mlxsw_sp, u16 mid,
+				       u16 smpe, u16 local_port)
+{
+	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
+	struct mlxsw_sp_pgt_entry *pgt_entry;
+	int err;
+
+	mutex_lock(&mlxsw_sp->pgt->lock);
+
+	pgt_entry = mlxsw_sp_pgt_entry_get(mlxsw_sp->pgt, mid, smpe);
+	if (IS_ERR(pgt_entry)) {
+		err = PTR_ERR(pgt_entry);
+		goto err_pgt_entry_get;
+	}
+
+	pgt_entry_port = mlxsw_sp_pgt_entry_port_create(mlxsw_sp, pgt_entry,
+							local_port);
+	if (IS_ERR(pgt_entry_port)) {
+		err = PTR_ERR(pgt_entry_port);
+		goto err_pgt_entry_port_get;
+	}
+
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+	return 0;
+
+err_pgt_entry_port_get:
+	mlxsw_sp_pgt_entry_put(mlxsw_sp->pgt, mid);
+err_pgt_entry_get:
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+	return err;
+}
+
+static void mlxsw_sp_pgt_entry_port_del(struct mlxsw_sp *mlxsw_sp,
+					u16 mid, u16 smpe, u16 local_port)
+{
+	struct mlxsw_sp_pgt_entry_port *pgt_entry_port;
+	struct mlxsw_sp_pgt_entry *pgt_entry;
+
+	mutex_lock(&mlxsw_sp->pgt->lock);
+
+	pgt_entry = idr_find(&mlxsw_sp->pgt->pgt_idr, mid);
+	if (!pgt_entry)
+		goto out;
+
+	pgt_entry_port = mlxsw_sp_pgt_entry_port_lookup(pgt_entry, local_port);
+	if (!pgt_entry_port)
+		goto out;
+
+	mlxsw_sp_pgt_entry_port_destroy(mlxsw_sp, pgt_entry, pgt_entry_port);
+	mlxsw_sp_pgt_entry_put(mlxsw_sp->pgt, mid);
+
+out:
+	mutex_unlock(&mlxsw_sp->pgt->lock);
+}
+
+int mlxsw_sp_pgt_entry_port_set(struct mlxsw_sp *mlxsw_sp, u16 mid,
+				u16 smpe, u16 local_port, bool member)
+{
+	if (member)
+		return mlxsw_sp_pgt_entry_port_add(mlxsw_sp, mid, smpe,
+						   local_port);
+
+	mlxsw_sp_pgt_entry_port_del(mlxsw_sp, mid, smpe, local_port);
+	return 0;
+}
+
 int mlxsw_sp_pgt_init(struct mlxsw_sp *mlxsw_sp)
 {
 	struct mlxsw_sp_pgt *pgt;
-- 
2.36.1


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

* [PATCH net-next 11/13] mlxsw: spectrum: Initialize PGT table
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (9 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 10/13] mlxsw: Extend PGT APIs to support maintaining list of ports per entry Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 12/13] mlxsw: spectrum_fid: Set 'mid_base' as part of flood tables initialization Ido Schimmel
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

Initialize PGT table as part of mlxsw_sp_init(). This table will be used
first in the next patch by FID code to set flooding entries, and later by
MDB code to add multicast entries.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index b128f900d0fe..ff94cd9d872f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3010,6 +3010,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 		return err;
 	}
 
+	err = mlxsw_sp_pgt_init(mlxsw_sp);
+	if (err) {
+		dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize PGT\n");
+		goto err_pgt_init;
+	}
+
 	err = mlxsw_sp_fids_init(mlxsw_sp);
 	if (err) {
 		dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize FIDs\n");
@@ -3202,6 +3208,8 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
 err_policers_init:
 	mlxsw_sp_fids_fini(mlxsw_sp);
 err_fids_init:
+	mlxsw_sp_pgt_fini(mlxsw_sp);
+err_pgt_init:
 	mlxsw_sp_kvdl_fini(mlxsw_sp);
 	mlxsw_sp_parsing_fini(mlxsw_sp);
 	return err;
@@ -3370,6 +3378,7 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
 	mlxsw_sp_traps_fini(mlxsw_sp);
 	mlxsw_sp_policers_fini(mlxsw_sp);
 	mlxsw_sp_fids_fini(mlxsw_sp);
+	mlxsw_sp_pgt_fini(mlxsw_sp);
 	mlxsw_sp_kvdl_fini(mlxsw_sp);
 	mlxsw_sp_parsing_fini(mlxsw_sp);
 }
-- 
2.36.1


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

* [PATCH net-next 12/13] mlxsw: spectrum_fid: Set 'mid_base' as part of flood tables initialization
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (10 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 11/13] mlxsw: spectrum: Initialize PGT table Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-27  7:06 ` [PATCH net-next 13/13] mlxsw: spectrum_fid: Configure flooding entries using PGT APIs Ido Schimmel
  2022-06-28 13:00 ` [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 patchwork-bot+netdevbpf
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

The PGT (Port Group Table) table maps an index to a bitmap of local ports
to which a packet needs to be replicated. This table is used for layer 2
multicast and flooding.

The index to PGT table which is called 'mid_index', is a result of
'mid_base' + 'fid_offset'. Using the legacy bridge model, firmware
configures 'mid_base'. However, using the new model, software is
responsible to configure it via SFGC register. The first 15K entries will
be used for flooding and the rest for multicast. The table will look as
follows:

+----------------------------+
|                            |
| 802.1q, unicast flooding   | 4K entries
|                            |
+----------------------------+
|                            |
| 802.1q, multicast flooding | 4K entries
|                            |
+----------------------------+
|                            |
| 802.1q, broadcast flooding | 4K entries
|                            |
+----------------------------+
| 802.1d, unicast flooding   | 1K entries
+----------------------------+
| 802.1d, multicast flooding | 1K entries
+----------------------------+
| 802.1d, broadcast flooding | 1K entries
+----------------------------+
|                            |
|                            |
|    Multicast entries       | The rest of the table
|                            |
|                            |
+----------------------------+

Add 'pgt_base' to 'struct mlxsw_sp_fid_family' and use it to calculate
MID base, set 'SFGC.mid_base' as part of flood tables initialization.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 drivers/net/ethernet/mellanox/mlxsw/reg.h     |  3 +-
 .../ethernet/mellanox/mlxsw/spectrum_fid.c    | 33 +++++++++++++++++--
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index d0ebb565b5cd..022b2168f3a5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -1114,13 +1114,14 @@ static inline void
 mlxsw_reg_sfgc_pack(char *payload, enum mlxsw_reg_sfgc_type type,
 		    enum mlxsw_reg_bridge_type bridge_type,
 		    enum mlxsw_flood_table_type table_type,
-		    unsigned int flood_table)
+		    unsigned int flood_table, u16 mid_base)
 {
 	MLXSW_REG_ZERO(sfgc, payload);
 	mlxsw_reg_sfgc_type_set(payload, type);
 	mlxsw_reg_sfgc_bridge_type_set(payload, bridge_type);
 	mlxsw_reg_sfgc_table_type_set(payload, table_type);
 	mlxsw_reg_sfgc_flood_table_set(payload, flood_table);
+	mlxsw_reg_sfgc_mid_base_set(payload, mid_base);
 }
 
 /* SFDF - Switch Filtering DB Flush
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index a82612a894eb..d168e9f5c62d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -110,6 +110,7 @@ struct mlxsw_sp_fid_family {
 	struct mlxsw_sp *mlxsw_sp;
 	bool flood_rsp;
 	enum mlxsw_reg_bridge_type bridge_type;
+	u16 pgt_base;
 };
 
 static const int mlxsw_sp_sfgc_uc_packet_types[MLXSW_REG_SFGC_TYPE_MAX] = {
@@ -321,6 +322,18 @@ mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
 	return NULL;
 }
 
+static u16
+mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
+			     const struct mlxsw_sp_flood_table *flood_table,
+			     u16 fid_offset)
+{
+	u16 num_fids;
+
+	num_fids = fid_family->end_index - fid_family->start_index + 1;
+	return fid_family->pgt_base + num_fids * flood_table->table_index +
+	       fid_offset;
+}
+
 int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
 			   enum mlxsw_sp_flood_type packet_type, u16 local_port,
 			   bool member)
@@ -736,6 +749,10 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021d_ops = {
 	.fdb_clear_offload	= mlxsw_sp_fid_8021d_fdb_clear_offload,
 };
 
+#define MLXSW_SP_FID_8021Q_MAX (VLAN_N_VID - 2)
+#define MLXSW_SP_FID_8021Q_PGT_BASE 0
+#define MLXSW_SP_FID_8021D_PGT_BASE (3 * MLXSW_SP_FID_8021Q_MAX)
+
 static const struct mlxsw_sp_flood_table mlxsw_sp_fid_8021d_flood_tables[] = {
 	{
 		.packet_type	= MLXSW_SP_FLOOD_TYPE_UC,
@@ -765,6 +782,7 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021d_family = {
 	.rif_type		= MLXSW_SP_RIF_TYPE_FID,
 	.ops			= &mlxsw_sp_fid_8021d_ops,
 	.bridge_type		= MLXSW_REG_BRIDGE_TYPE_1,
+	.pgt_base		= MLXSW_SP_FID_8021D_PGT_BASE,
 };
 
 static bool
@@ -801,7 +819,7 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_8021q_emu_ops = {
 /* There are 4K-2 emulated 802.1Q FIDs, starting right after the 802.1D FIDs */
 #define MLXSW_SP_FID_8021Q_EMU_START	(VLAN_N_VID + MLXSW_SP_FID_8021D_MAX)
 #define MLXSW_SP_FID_8021Q_EMU_END	(MLXSW_SP_FID_8021Q_EMU_START + \
-					 VLAN_VID_MASK - 2)
+					 MLXSW_SP_FID_8021Q_MAX - 1)
 
 /* Range and flood configuration must match mlxsw_config_profile */
 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
@@ -814,6 +832,7 @@ static const struct mlxsw_sp_fid_family mlxsw_sp_fid_8021q_emu_family = {
 	.rif_type		= MLXSW_SP_RIF_TYPE_VLAN_EMU,
 	.ops			= &mlxsw_sp_fid_8021q_emu_ops,
 	.bridge_type            = MLXSW_REG_BRIDGE_TYPE_1,
+	.pgt_base		= MLXSW_SP_FID_8021Q_PGT_BASE,
 };
 
 static void mlxsw_sp_fid_rfid_setup(struct mlxsw_sp_fid *fid, const void *arg)
@@ -1151,8 +1170,11 @@ mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
 {
 	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
 	const int *sfgc_packet_types;
+	u16 mid_base, table_index;
 	int i;
 
+	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
+
 	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
 	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
 		struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
@@ -1161,9 +1183,14 @@ mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
 
 		if (!sfgc_packet_types[i])
 			continue;
+
+		mid_base = mlxsw_sp->ubridge ? mid_base : 0;
+		table_index = mlxsw_sp->ubridge ? 0 : flood_table->table_index;
+
 		mlxsw_reg_sfgc_pack(sfgc_pl, i, fid_family->bridge_type,
-				    flood_table->table_type,
-				    flood_table->table_index);
+				    flood_table->table_type, table_index,
+				    mid_base);
+
 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
 		if (err)
 			return err;
-- 
2.36.1


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

* [PATCH net-next 13/13] mlxsw: spectrum_fid: Configure flooding entries using PGT APIs
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (11 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 12/13] mlxsw: spectrum_fid: Set 'mid_base' as part of flood tables initialization Ido Schimmel
@ 2022-06-27  7:06 ` Ido Schimmel
  2022-06-28 13:00 ` [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 patchwork-bot+netdevbpf
  13 siblings, 0 replies; 15+ messages in thread
From: Ido Schimmel @ 2022-06-27  7:06 UTC (permalink / raw)
  To: netdev; +Cc: davem, kuba, pabeni, edumazet, petrm, amcohen, mlxsw, Ido Schimmel

From: Amit Cohen <amcohen@nvidia.com>

The PGT (Port Group Table) table maps an index to a bitmap of local ports
to which a packet needs to be replicated. This table is used for layer 2
multicast and flooding.

In the legacy model, software did not interact with PGT table directly.
Instead, it was accessed by firmware in response to registers such as SFTR
and SMID. In the new model, the SFTR register is deprecated and software
has full control over the PGT table using the SMID register.

Use the new PGT APIs to allocate entries for flooding as part of flood
tables initialization. Add mlxsw_sp_fid_flood_tables_fini() to free the
allocated indexes. In addition, use PGT APIs to add/remove ports from PGT
table. The existing code which configures the flood entries via SFTR2 will
be removed later.

Signed-off-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
---
 .../ethernet/mellanox/mlxsw/spectrum_fid.c    | 65 +++++++++++++++++--
 1 file changed, 59 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
index d168e9f5c62d..160c5af5235d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_fid.c
@@ -322,6 +322,12 @@ mlxsw_sp_fid_flood_table_lookup(const struct mlxsw_sp_fid *fid,
 	return NULL;
 }
 
+static u16
+mlxsw_sp_fid_family_num_fids(const struct mlxsw_sp_fid_family *fid_family)
+{
+	return fid_family->end_index - fid_family->start_index + 1;
+}
+
 static u16
 mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
 			     const struct mlxsw_sp_flood_table *flood_table,
@@ -329,7 +335,7 @@ mlxsw_sp_fid_flood_table_mid(const struct mlxsw_sp_fid_family *fid_family,
 {
 	u16 num_fids;
 
-	num_fids = fid_family->end_index - fid_family->start_index + 1;
+	num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
 	return fid_family->pgt_base + num_fids * flood_table->table_index +
 	       fid_offset;
 }
@@ -342,6 +348,7 @@ int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
 	const struct mlxsw_sp_fid_ops *ops = fid_family->ops;
 	const struct mlxsw_sp_flood_table *flood_table;
 	char *sftr2_pl;
+	u16 mid_index;
 	int err;
 
 	if (WARN_ON(!fid_family->flood_tables || !ops->flood_index))
@@ -351,6 +358,15 @@ int mlxsw_sp_fid_flood_set(struct mlxsw_sp_fid *fid,
 	if (!flood_table)
 		return -ESRCH;
 
+	if (fid_family->mlxsw_sp->ubridge) {
+		mid_index = mlxsw_sp_fid_flood_table_mid(fid_family,
+							 flood_table,
+							 fid->fid_offset);
+		return mlxsw_sp_pgt_entry_port_set(fid_family->mlxsw_sp,
+						   mid_index, fid->fid_index,
+						   local_port, member);
+	}
+
 	sftr2_pl = kmalloc(MLXSW_REG_SFTR2_LEN, GFP_KERNEL);
 	if (!sftr2_pl)
 		return -ENOMEM;
@@ -1169,17 +1185,20 @@ mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
 			      const struct mlxsw_sp_flood_table *flood_table)
 {
 	enum mlxsw_sp_flood_type packet_type = flood_table->packet_type;
+	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
+	u16 mid_base, num_fids, table_index;
 	const int *sfgc_packet_types;
-	u16 mid_base, table_index;
-	int i;
+	int err, i;
 
 	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
+	num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
+	err = mlxsw_sp_pgt_mid_alloc_range(mlxsw_sp, mid_base, num_fids);
+	if (err)
+		return err;
 
 	sfgc_packet_types = mlxsw_sp_packet_type_sfgc_types[packet_type];
 	for (i = 0; i < MLXSW_REG_SFGC_TYPE_MAX; i++) {
-		struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
 		char sfgc_pl[MLXSW_REG_SFGC_LEN];
-		int err;
 
 		if (!sfgc_packet_types[i])
 			continue;
@@ -1193,10 +1212,27 @@ mlxsw_sp_fid_flood_table_init(struct mlxsw_sp_fid_family *fid_family,
 
 		err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfgc), sfgc_pl);
 		if (err)
-			return err;
+			goto err_reg_write;
 	}
 
 	return 0;
+
+err_reg_write:
+	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
+	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
+	return err;
+}
+
+static void
+mlxsw_sp_fid_flood_table_fini(struct mlxsw_sp_fid_family *fid_family,
+			      const struct mlxsw_sp_flood_table *flood_table)
+{
+	struct mlxsw_sp *mlxsw_sp = fid_family->mlxsw_sp;
+	u16 num_fids, mid_base;
+
+	mid_base = mlxsw_sp_fid_flood_table_mid(fid_family, flood_table, 0);
+	num_fids = mlxsw_sp_fid_family_num_fids(fid_family);
+	mlxsw_sp_pgt_mid_free_range(mlxsw_sp, mid_base, num_fids);
 }
 
 static int
@@ -1217,6 +1253,19 @@ mlxsw_sp_fid_flood_tables_init(struct mlxsw_sp_fid_family *fid_family)
 	return 0;
 }
 
+static void
+mlxsw_sp_fid_flood_tables_fini(struct mlxsw_sp_fid_family *fid_family)
+{
+	int i;
+
+	for (i = 0; i < fid_family->nr_flood_tables; i++) {
+		const struct mlxsw_sp_flood_table *flood_table;
+
+		flood_table = &fid_family->flood_tables[i];
+		mlxsw_sp_fid_flood_table_fini(fid_family, flood_table);
+	}
+}
+
 static int mlxsw_sp_fid_family_register(struct mlxsw_sp *mlxsw_sp,
 					const struct mlxsw_sp_fid_family *tmpl)
 {
@@ -1258,6 +1307,10 @@ mlxsw_sp_fid_family_unregister(struct mlxsw_sp *mlxsw_sp,
 			       struct mlxsw_sp_fid_family *fid_family)
 {
 	mlxsw_sp->fid_core->fid_family_arr[fid_family->type] = NULL;
+
+	if (fid_family->flood_tables)
+		mlxsw_sp_fid_flood_tables_fini(fid_family);
+
 	bitmap_free(fid_family->fids_bitmap);
 	WARN_ON_ONCE(!list_empty(&fid_family->fids_list));
 	kfree(fid_family);
-- 
2.36.1


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

* Re: [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6
  2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
                   ` (12 preceding siblings ...)
  2022-06-27  7:06 ` [PATCH net-next 13/13] mlxsw: spectrum_fid: Configure flooding entries using PGT APIs Ido Schimmel
@ 2022-06-28 13:00 ` patchwork-bot+netdevbpf
  13 siblings, 0 replies; 15+ messages in thread
From: patchwork-bot+netdevbpf @ 2022-06-28 13:00 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 Paolo Abeni <pabeni@redhat.com>:

On Mon, 27 Jun 2022 10:06:08 +0300 you wrote:
> This is the fourth part of the conversion of mlxsw to the unified bridge
> model.
> 
> Unlike previous parts that prepared mlxsw for the conversion, this part
> actually starts the conversion. It focuses on flooding configuration and
> converts mlxsw to the more "raw" APIs of the unified bridge model.
> 
> [...]

Here is the summary with links:
  - [net-next,01/13] mlxsw: spectrum: Add a temporary variable to indicate bridge model
    https://git.kernel.org/netdev/net-next/c/d6d9026668db
  - [net-next,02/13] mlxsw: spectrum_fid: Configure flooding table type for rFID
    https://git.kernel.org/netdev/net-next/c/93303ff828fd
  - [net-next,03/13] mlxsw: Prepare 'bridge_type' field for SFMR usage
    https://git.kernel.org/netdev/net-next/c/fad8e1b6d52d
  - [net-next,04/13] mlxsw: spectrum_fid: Store 'bridge_type' as part of FID family
    https://git.kernel.org/netdev/net-next/c/dd8c77d59708
  - [net-next,05/13] mlxsw: Set flood bridge type for FIDs
    https://git.kernel.org/netdev/net-next/c/aa845e36a069
  - [net-next,06/13] mlxsw: spectrum_fid: Configure egress VID classification for multicast
    https://git.kernel.org/netdev/net-next/c/8c2da081c8b8
  - [net-next,07/13] mlxsw: Add an initial PGT table support
    https://git.kernel.org/netdev/net-next/c/d8782ec59eb8
  - [net-next,08/13] mlxsw: Add an indication of SMPE index validity for PGT table
    https://git.kernel.org/netdev/net-next/c/a1697d11c945
  - [net-next,09/13] mlxsw: Add a dedicated structure for bitmap of ports
    https://git.kernel.org/netdev/net-next/c/d7a7b6978709
  - [net-next,10/13] mlxsw: Extend PGT APIs to support maintaining list of ports per entry
    https://git.kernel.org/netdev/net-next/c/a3a7992bc4e4
  - [net-next,11/13] mlxsw: spectrum: Initialize PGT table
    https://git.kernel.org/netdev/net-next/c/bb1bba35f50a
  - [net-next,12/13] mlxsw: spectrum_fid: Set 'mid_base' as part of flood tables initialization
    https://git.kernel.org/netdev/net-next/c/9f6f467a3cdb
  - [net-next,13/13] mlxsw: spectrum_fid: Configure flooding entries using PGT APIs
    https://git.kernel.org/netdev/net-next/c/fe94df6dc622

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] 15+ messages in thread

end of thread, other threads:[~2022-06-28 13:00 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-27  7:06 [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/6 Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 01/13] mlxsw: spectrum: Add a temporary variable to indicate bridge model Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 02/13] mlxsw: spectrum_fid: Configure flooding table type for rFID Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 03/13] mlxsw: Prepare 'bridge_type' field for SFMR usage Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 04/13] mlxsw: spectrum_fid: Store 'bridge_type' as part of FID family Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 05/13] mlxsw: Set flood bridge type for FIDs Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 06/13] mlxsw: spectrum_fid: Configure egress VID classification for multicast Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 07/13] mlxsw: Add an initial PGT table support Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 08/13] mlxsw: Add an indication of SMPE index validity for PGT table Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 09/13] mlxsw: Add a dedicated structure for bitmap of ports Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 10/13] mlxsw: Extend PGT APIs to support maintaining list of ports per entry Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 11/13] mlxsw: spectrum: Initialize PGT table Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 12/13] mlxsw: spectrum_fid: Set 'mid_base' as part of flood tables initialization Ido Schimmel
2022-06-27  7:06 ` [PATCH net-next 13/13] mlxsw: spectrum_fid: Configure flooding entries using PGT APIs Ido Schimmel
2022-06-28 13:00 ` [PATCH net-next 00/13] mlxsw: Unified bridge conversion - part 4/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.