diff mbox series

[net-next,v2,12/14] net: ethernet: qualcomm: Initialize PPE L2 bridge settings

Message ID 20250108-qcom_ipq_ppe-v2-12-7394dbda7199@quicinc.com (mailing list archive)
State Not Applicable
Headers show
Series Add PPE driver for Qualcomm IPQ9574 SoC | expand

Commit Message

Jie Luo Jan. 8, 2025, 1:47 p.m. UTC
From: Lei Wei <quic_leiwei@quicinc.com>

Configure the default L2 bridge settings for the PPE ports to
enable L2 frame forwarding between CPU port and PPE Ethernet
ports.

The per-port L2 bridge settings are initialized as follows:
For PPE CPU port, the PPE bridge TX is enabled and FDB learn is
disabled. For PPE physical port, the PPE bridge TX is disabled
and FDB learn is enabled by default and the L2 forward action
is initialized as forward to CPU port.

Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
 drivers/net/ethernet/qualcomm/ppe/ppe_config.c | 74 +++++++++++++++++++++++++-
 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h   | 50 +++++++++++++++++
 2 files changed, 123 insertions(+), 1 deletion(-)

Comments

Andrew Lunn Jan. 8, 2025, 4:59 p.m. UTC | #1
On Wed, Jan 08, 2025 at 09:47:19PM +0800, Luo Jie wrote:
> From: Lei Wei <quic_leiwei@quicinc.com>
> 
> Configure the default L2 bridge settings for the PPE ports to
> enable L2 frame forwarding between CPU port and PPE Ethernet
> ports.

It would be good to have an 'only' in there:

> to _only_
> enable L2 frame forwarding between CPU port and PPE Ethernet
> ports

That makes it clear there is no port to port forwarding, the ports are
isolated.

> The per-port L2 bridge settings are initialized as follows:
> For PPE CPU port, the PPE bridge TX is enabled and FDB learn is
> disabled. For PPE physical port, the PPE bridge TX is disabled
> and FDB learn is enabled by default and the L2 forward action
> is initialized as forward to CPU port.

Why is learning needed on physical ports? In general, switches forward
unknown destination addresses to the CPU. Which is what you want when
the ports are isolated from each other. Everything goes to the
CPU. But maybe this switch does not work like this?

	Andrew
Lei Wei Jan. 13, 2025, 3:39 a.m. UTC | #2
On 1/9/2025 12:59 AM, Andrew Lunn wrote:
> On Wed, Jan 08, 2025 at 09:47:19PM +0800, Luo Jie wrote:
>> From: Lei Wei <quic_leiwei@quicinc.com>
>>
>> Configure the default L2 bridge settings for the PPE ports to
>> enable L2 frame forwarding between CPU port and PPE Ethernet
>> ports.
> 
> It would be good to have an 'only' in there:
> 
>> to _only_
>> enable L2 frame forwarding between CPU port and PPE Ethernet
>> ports
> 
> That makes it clear there is no port to port forwarding, the ports are
> isolated.
> 

Sure, I will add 'only' to make it clear.

>> The per-port L2 bridge settings are initialized as follows:
>> For PPE CPU port, the PPE bridge TX is enabled and FDB learn is
>> disabled. For PPE physical port, the PPE bridge TX is disabled
>> and FDB learn is enabled by default and the L2 forward action
>> is initialized as forward to CPU port.
> 
> Why is learning needed on physical ports? In general, switches forward
> unknown destination addresses to the CPU. Which is what you want when
> the ports are isolated from each other. Everything goes to the
> CPU. But maybe this switch does not work like this?
> 

L2 forwarding can be disabled in PPE in two ways:

1.) Keep the learning enabled (which is the default HW setting) and
configure the FDB-miss-action to redirect to CPU.

This works because even if FDB learning is enabled, we need to represent
the bridge and the physical ports using their 'virtual switch instance'
(VSI) in the PPE HW, and create the 'port membership' for the bridge VSI
(the list of slave ports), before FDB based forwarding can take place. 
Since we do not yet support switchdev, these VSI are not created and 
packets are always forwarded to CPU due to FDB miss.

(or)

2.) Explicitly disable learning either globally or on the ports.

With method 1 we can achieve packet forwarding to CPU without explicitly
disabling learning. When switchdev is enabled later, L2 forwarding can 
be enabled as a natural extension on top of this configuration. So we 
have chosen the first approach.

> 	Andrew
>
Andrew Lunn Jan. 13, 2025, 1:37 p.m. UTC | #3
> > Why is learning needed on physical ports? In general, switches forward
> > unknown destination addresses to the CPU. Which is what you want when
> > the ports are isolated from each other. Everything goes to the
> > CPU. But maybe this switch does not work like this?
> > 
> 
> L2 forwarding can be disabled in PPE in two ways:
> 
> 1.) Keep the learning enabled (which is the default HW setting) and
> configure the FDB-miss-action to redirect to CPU.
> 
> This works because even if FDB learning is enabled, we need to represent
> the bridge and the physical ports using their 'virtual switch instance'
> (VSI) in the PPE HW, and create the 'port membership' for the bridge VSI
> (the list of slave ports), before FDB based forwarding can take place. Since
> we do not yet support switchdev, these VSI are not created and packets are
> always forwarded to CPU due to FDB miss.
> 
> (or)
> 
> 2.) Explicitly disable learning either globally or on the ports.
> 
> With method 1 we can achieve packet forwarding to CPU without explicitly
> disabling learning. When switchdev is enabled later, L2 forwarding can be
> enabled as a natural extension on top of this configuration. So we have
> chosen the first approach.

How does ageing work in this setup? Will a cable unplug/plug flush all
the learned entries? Is ageing set to some reasonable default in case
a MAC address moves?

	Andrew
Lei Wei Jan. 14, 2025, 11:29 a.m. UTC | #4
On 1/13/2025 9:37 PM, Andrew Lunn wrote:
>>> Why is learning needed on physical ports? In general, switches forward
>>> unknown destination addresses to the CPU. Which is what you want when
>>> the ports are isolated from each other. Everything goes to the
>>> CPU. But maybe this switch does not work like this?
>>>
>>
>> L2 forwarding can be disabled in PPE in two ways:
>>
>> 1.) Keep the learning enabled (which is the default HW setting) and
>> configure the FDB-miss-action to redirect to CPU.
>>
>> This works because even if FDB learning is enabled, we need to represent
>> the bridge and the physical ports using their 'virtual switch instance'
>> (VSI) in the PPE HW, and create the 'port membership' for the bridge VSI
>> (the list of slave ports), before FDB based forwarding can take place. Since
>> we do not yet support switchdev, these VSI are not created and packets are
>> always forwarded to CPU due to FDB miss.
>>
>> (or)
>>
>> 2.) Explicitly disable learning either globally or on the ports.
>>
>> With method 1 we can achieve packet forwarding to CPU without explicitly
>> disabling learning. When switchdev is enabled later, L2 forwarding can be
>> enabled as a natural extension on top of this configuration. So we have
>> chosen the first approach.
> 
> How does ageing work in this setup? Will a cable unplug/plug flush all
> the learned entries? Is ageing set to some reasonable default in case
> a MAC address moves?
> 

I would like to clarify that representing the bridge and its slave ports
inside PPE (using a VSI - virtual switch instance) is a pre-requisite 
before learning can take place on a port. At this point, since switchdev
is not enabled, VSI is not created for port/bridge and hence FDB 
learning does not take place. Later when we enable switchdev and 
represent the bridge/slave-ports in PPE, FDB learning will automatically 
occur on top of this initial configuration. I will add this note in the 
comments and commit message to make it clear.

Regarding FDB entry ageing (when switchdev is enabled later), MAC 
address move can be automatically detected and old entry flushed by the 
PPE. However for link change events on a port, PPE will rely on software 
to flush FDB entries for the port.

> 	Andrew
Andrew Lunn Jan. 14, 2025, 1:02 p.m. UTC | #5
> I would like to clarify that representing the bridge and its slave ports
> inside PPE (using a VSI - virtual switch instance) is a pre-requisite before
> learning can take place on a port. At this point, since switchdev
> is not enabled, VSI is not created for port/bridge and hence FDB learning
> does not take place. Later when we enable switchdev and represent the
> bridge/slave-ports in PPE, FDB learning will automatically occur on top of
> this initial configuration. I will add this note in the comments and commit
> message to make it clear.

So it seems like the comment is not the best. You don't actually
enable learning...

	Andrew
Lei Wei Jan. 15, 2025, 6:57 a.m. UTC | #6
On 1/14/2025 9:02 PM, Andrew Lunn wrote:
>> I would like to clarify that representing the bridge and its slave ports
>> inside PPE (using a VSI - virtual switch instance) is a pre-requisite before
>> learning can take place on a port. At this point, since switchdev
>> is not enabled, VSI is not created for port/bridge and hence FDB learning
>> does not take place. Later when we enable switchdev and represent the
>> bridge/slave-ports in PPE, FDB learning will automatically occur on top of
>> this initial configuration. I will add this note in the comments and commit
>> message to make it clear.
> 
> So it seems like the comment is not the best. You don't actually
> enable learning...
>

Yes, I will update the comment to make it more clear.

> 	Andrew
diff mbox series

Patch

diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
index 39e4d19c2bd6..ab008aa1c23c 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
@@ -1895,6 +1895,74 @@  static int ppe_queues_to_ring_init(struct ppe_device *ppe_dev)
 	return ppe_ring_queue_map_set(ppe_dev, 0, queue_bmap);
 }
 
+/* Initialize PPE bridge settings to enable L2 frame receive and transmit
+ * between CPU port and PPE Ethernet ports.
+ */
+static int ppe_bridge_init(struct ppe_device *ppe_dev)
+{
+	u32 reg, mask, port_cfg[4], vsi_cfg[2];
+	int ret, i;
+
+	/* Configure the following settings for CPU port0:
+	 * a.) Enable Bridge TX
+	 * b.) Disable FDB new address learning
+	 * c.) Disable station move address learning
+	 */
+	mask = PPE_PORT_BRIDGE_TXMAC_EN;
+	mask |= PPE_PORT_BRIDGE_NEW_LRN_EN;
+	mask |= PPE_PORT_BRIDGE_STA_MOVE_LRN_EN;
+	ret = regmap_update_bits(ppe_dev->regmap,
+				 PPE_PORT_BRIDGE_CTRL_ADDR,
+				 mask,
+				 PPE_PORT_BRIDGE_TXMAC_EN);
+	if (ret)
+		return ret;
+
+	for (i = 1; i < ppe_dev->num_ports; i++) {
+		/* Enable invalid VSI forwarding for all the physical ports
+		 * to CPU port0, in case no VSI is assigned to the physical
+		 * port.
+		 */
+		reg = PPE_L2_VP_PORT_TBL_ADDR + PPE_L2_VP_PORT_TBL_INC * i;
+		ret = regmap_bulk_read(ppe_dev->regmap, reg,
+				       port_cfg, ARRAY_SIZE(port_cfg));
+
+		if (ret)
+			return ret;
+
+		PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(port_cfg, true);
+		PPE_L2_PORT_SET_DST_INFO(port_cfg, 0);
+
+		ret = regmap_bulk_write(ppe_dev->regmap, reg,
+					port_cfg, ARRAY_SIZE(port_cfg));
+		if (ret)
+			return ret;
+	}
+
+	for (i = 0; i < PPE_VSI_TBL_ENTRIES; i++) {
+		/* Enable address learning for the bridge VSI to enable
+		 * forwarding. Set VSI forward membership to include only
+		 * CPU port0.
+		 */
+		PPE_VSI_SET_MEMBER_PORT_BITMAP(vsi_cfg, BIT(0));
+		PPE_VSI_SET_UUC_BITMAP(vsi_cfg, BIT(0));
+		PPE_VSI_SET_UMC_BITMAP(vsi_cfg, BIT(0));
+		PPE_VSI_SET_BC_BITMAP(vsi_cfg, BIT(0));
+		PPE_VSI_SET_NEW_ADDR_LRN_EN(vsi_cfg, true);
+		PPE_VSI_SET_NEW_ADDR_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD);
+		PPE_VSI_SET_STATION_MOVE_LRN_EN(vsi_cfg, true);
+		PPE_VSI_SET_STATION_MOVE_FWD_CMD(vsi_cfg, PPE_ACTION_FORWARD);
+
+		reg = PPE_VSI_TBL_ADDR + PPE_VSI_TBL_INC * i;
+		ret = regmap_bulk_write(ppe_dev->regmap, reg,
+					vsi_cfg, ARRAY_SIZE(vsi_cfg));
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 int ppe_hw_config(struct ppe_device *ppe_dev)
 {
 	int ret;
@@ -1927,5 +1995,9 @@  int ppe_hw_config(struct ppe_device *ppe_dev)
 	if (ret)
 		return ret;
 
-	return ppe_queues_to_ring_init(ppe_dev);
+	ret = ppe_queues_to_ring_init(ppe_dev);
+	if (ret)
+		return ret;
+
+	return ppe_bridge_init(ppe_dev);
 }
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
index da55b06b30b8..f23fafa35766 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
@@ -117,6 +117,14 @@ 
 #define PPE_EG_SERVICE_SET_TX_CNT_EN(tbl_cfg, value)	\
 	u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_EG_SERVICE_W1_TX_CNT_EN)
 
+/* PPE port bridge configuration */
+#define PPE_PORT_BRIDGE_CTRL_ADDR		0x60300
+#define PPE_PORT_BRIDGE_CTRL_ENTRIES		8
+#define PPE_PORT_BRIDGE_CTRL_INC		4
+#define PPE_PORT_BRIDGE_NEW_LRN_EN		BIT(0)
+#define PPE_PORT_BRIDGE_STA_MOVE_LRN_EN		BIT(3)
+#define PPE_PORT_BRIDGE_TXMAC_EN		BIT(16)
+
 /* PPE port control configurations for the traffic to the multicast queues. */
 #define PPE_MC_MTU_CTRL_TBL_ADDR		0x60a00
 #define PPE_MC_MTU_CTRL_TBL_ENTRIES		8
@@ -125,6 +133,36 @@ 
 #define PPE_MC_MTU_CTRL_TBL_MTU_CMD		GENMASK(15, 14)
 #define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN		BIT(16)
 
+/* PPE VSI configurations */
+#define PPE_VSI_TBL_ADDR			0x63800
+#define PPE_VSI_TBL_ENTRIES			64
+#define PPE_VSI_TBL_INC				0x10
+#define PPE_VSI_W0_MEMBER_PORT_BITMAP		GENMASK(7, 0)
+#define PPE_VSI_W0_UUC_BITMAP			GENMASK(15, 8)
+#define PPE_VSI_W0_UMC_BITMAP			GENMASK(23, 16)
+#define PPE_VSI_W0_BC_BITMAP			GENMASK(31, 24)
+#define PPE_VSI_W1_NEW_ADDR_LRN_EN		BIT(0)
+#define PPE_VSI_W1_NEW_ADDR_FWD_CMD		GENMASK(2, 1)
+#define PPE_VSI_W1_STATION_MOVE_LRN_EN		BIT(3)
+#define PPE_VSI_W1_STATION_MOVE_FWD_CMD		GENMASK(5, 4)
+
+#define PPE_VSI_SET_MEMBER_PORT_BITMAP(tbl_cfg, value)		\
+	u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_MEMBER_PORT_BITMAP)
+#define PPE_VSI_SET_UUC_BITMAP(tbl_cfg, value)			\
+	u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UUC_BITMAP)
+#define PPE_VSI_SET_UMC_BITMAP(tbl_cfg, value)			\
+	u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_UMC_BITMAP)
+#define PPE_VSI_SET_BC_BITMAP(tbl_cfg, value)			\
+	u32p_replace_bits((u32 *)tbl_cfg, value, PPE_VSI_W0_BC_BITMAP)
+#define PPE_VSI_SET_NEW_ADDR_LRN_EN(tbl_cfg, value)		\
+	u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_LRN_EN)
+#define PPE_VSI_SET_NEW_ADDR_FWD_CMD(tbl_cfg, value)		\
+	u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_NEW_ADDR_FWD_CMD)
+#define PPE_VSI_SET_STATION_MOVE_LRN_EN(tbl_cfg, value)		\
+	u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_LRN_EN)
+#define PPE_VSI_SET_STATION_MOVE_FWD_CMD(tbl_cfg, value)	\
+	u32p_replace_bits((u32 *)(tbl_cfg) + 0x1, value, PPE_VSI_W1_STATION_MOVE_FWD_CMD)
+
 /* PPE port control configurations for the traffic to the unicast queues. */
 #define PPE_MRU_MTU_CTRL_TBL_ADDR		0x65000
 #define PPE_MRU_MTU_CTRL_TBL_ENTRIES		256
@@ -163,6 +201,18 @@ 
 #define PPE_IN_L2_SERVICE_TBL_RX_CNT_EN		BIT(30)
 #define PPE_IN_L2_SERVICE_TBL_TX_CNT_EN		BIT(31)
 
+/* L2 Port configurations */
+#define PPE_L2_VP_PORT_TBL_ADDR			0x98000
+#define PPE_L2_VP_PORT_TBL_ENTRIES		256
+#define PPE_L2_VP_PORT_TBL_INC			0x10
+#define PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN	BIT(0)
+#define PPE_L2_VP_PORT_W0_DST_INFO		GENMASK(9, 2)
+
+#define PPE_L2_PORT_SET_INVALID_VSI_FWD_EN(tbl_cfg, value)	\
+	u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_INVALID_VSI_FWD_EN)
+#define PPE_L2_PORT_SET_DST_INFO(tbl_cfg, value)		\
+	u32p_replace_bits((u32 *)tbl_cfg, value, PPE_L2_VP_PORT_W0_DST_INFO)
+
 /* PPE service code configuration for the tunnel packet. */
 #define PPE_TL_SERVICE_TBL_ADDR			0x306000
 #define PPE_TL_SERVICE_TBL_ENTRIES		256