diff mbox series

[net-next,11/20] net: ethernet: qualcomm: Add PPE port control config

Message ID 20240110114033.32575-12-quic_luoj@quicinc.com
State New
Headers show
Series net: ethernet: Add qcom PPE driver | expand

Commit Message

Luo Jie Jan. 10, 2024, 11:40 a.m. UTC
1. Enable the port statistics counter for the physical port.

2. Configure the default action as drop when the packet size is more
   than the configured MTU of physical port.

3. For IPQ5322, the number of PPE port is 3.

Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
 drivers/net/ethernet/qualcomm/ppe/ppe.c      | 60 ++++++++++++++++-
 drivers/net/ethernet/qualcomm/ppe/ppe.h      | 10 +++
 drivers/net/ethernet/qualcomm/ppe/ppe_ops.c  | 22 +++++++
 drivers/net/ethernet/qualcomm/ppe/ppe_ops.h  |  1 +
 drivers/net/ethernet/qualcomm/ppe/ppe_regs.h | 69 ++++++++++++++++++++
 5 files changed, 161 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.c b/drivers/net/ethernet/qualcomm/ppe/ppe.c
index acff37f9d832..bce0a9137c9f 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.c
@@ -18,6 +18,7 @@ 
 #include "ppe_ops.h"
 
 #define PPE_SCHEDULER_PORT_NUM		8
+#define MPPE_SCHEDULER_PORT_NUM		3
 #define PPE_SCHEDULER_L0_NUM		300
 #define PPE_SCHEDULER_L1_NUM		64
 #define PPE_SP_PRIORITY_NUM		8
@@ -1118,6 +1119,59 @@  static int ppe_servcode_init(struct ppe_device *ppe_dev)
 	return ppe_servcode_config_set(ppe_dev, 1, servcode_cfg);
 }
 
+static int ppe_port_ctrl_init(struct ppe_device *ppe_dev)
+{
+	union ppe_mru_mtu_ctrl_cfg_u mru_mtu_cfg;
+	int ret, port_num = PPE_SCHEDULER_PORT_NUM;
+	u32 reg_val;
+
+	if (ppe_type_get(ppe_dev) == PPE_TYPE_MPPE) {
+		for (ret = 0; ret < MPPE_SCHEDULER_PORT_NUM; ret++) {
+			reg_val = FIELD_PREP(PPE_TX_BUFF_THRSH_XOFF, 3) |
+				  FIELD_PREP(PPE_TX_BUFF_THRSH_XON, 3);
+			ppe_write(ppe_dev, PPE_TX_BUFF_THRSH + PPE_TX_BUFF_THRSH_INC * ret,
+				  reg_val);
+
+			/* Fix 147B line rate on physical port */
+			if (ret != 0)
+				ppe_mask(ppe_dev, PPE_RX_FIFO_CFG + PPE_RX_FIFO_CFG_INC * ret,
+					 PPE_RX_FIFO_CFG_THRSH,
+					 FIELD_PREP(PPE_RX_FIFO_CFG_THRSH, 7));
+		}
+
+		port_num = MPPE_SCHEDULER_PORT_NUM;
+	}
+
+	for (ret = 0; ret < port_num; ret++) {
+		if (ret != 0) {
+			memset(&mru_mtu_cfg, 0, sizeof(mru_mtu_cfg));
+			ppe_read_tbl(ppe_dev,
+				     PPE_MRU_MTU_CTRL_TBL + PPE_MRU_MTU_CTRL_TBL_INC * ret,
+				     mru_mtu_cfg.val, sizeof(mru_mtu_cfg.val));
+
+			/* Drop the packet when the packet size is more than
+			 * the MTU of the physical interface.
+			 */
+			mru_mtu_cfg.bf.mru_cmd = PPE_ACTION_DROP;
+			mru_mtu_cfg.bf.mtu_cmd = PPE_ACTION_DROP;
+
+			ppe_write_tbl(ppe_dev,
+				      PPE_MRU_MTU_CTRL_TBL + PPE_MRU_MTU_CTRL_TBL_INC * ret,
+				      mru_mtu_cfg.val, sizeof(mru_mtu_cfg.val));
+
+			ppe_mask(ppe_dev,
+				 PPE_MC_MTU_CTRL_TBL + PPE_MC_MTU_CTRL_TBL_INC * ret,
+				 PPE_MC_MTU_CTRL_TBL_MTU_CMD,
+				 FIELD_PREP(PPE_MC_MTU_CTRL_TBL_MTU_CMD, PPE_ACTION_DROP));
+		}
+
+		/* Enable PPE port counter */
+		ppe_counter_set(ppe_dev, ret, true);
+	}
+
+	return 0;
+}
+
 static int ppe_dev_hw_init(struct ppe_device *ppe_dev)
 {
 	int ret;
@@ -1126,7 +1180,11 @@  static int ppe_dev_hw_init(struct ppe_device *ppe_dev)
 	if (ret)
 		return ret;
 
-	return ppe_servcode_init(ppe_dev);
+	ret = ppe_servcode_init(ppe_dev);
+	if (ret)
+		return ret;
+
+	return ppe_port_ctrl_init(ppe_dev);
 }
 
 static int qcom_ppe_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe.h b/drivers/net/ethernet/qualcomm/ppe/ppe.h
index 84b1c9761f79..507626b6ab2e 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe.h
@@ -132,6 +132,16 @@  enum {
 	PPE_TYPE_MAX = 0xff,
 };
 
+/* The action of packet received by PPE can be forwarded, dropped, copied
+ * to CPU(enter multicast queue), redirected to CPU(enter unicast queue).
+ */
+enum {
+	PPE_ACTION_FORWARD = 0,
+	PPE_ACTION_DROP,
+	PPE_ACTION_COPY_TO_CPU,
+	PPE_ACTION_REDIRECTED_TO_CPU
+};
+
 /* PPE private data of different PPE type device */
 struct ppe_data {
 	int ppe_type;
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_ops.c b/drivers/net/ethernet/qualcomm/ppe/ppe_ops.c
index a3269c0898be..b017983e7cbf 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_ops.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_ops.c
@@ -311,6 +311,28 @@  int ppe_servcode_config_set(struct ppe_device *ppe_dev,
 	return ppe_write(ppe_dev, PPE_TL_SERVICE_TBL + PPE_TL_SERVICE_TBL_INC * servcode, val);
 }
 
+int ppe_counter_set(struct ppe_device *ppe_dev, int port, bool enable)
+{
+	union ppe_mru_mtu_ctrl_cfg_u mru_mtu_cfg;
+
+	memset(&mru_mtu_cfg, 0, sizeof(mru_mtu_cfg));
+
+	ppe_read_tbl(ppe_dev, PPE_MRU_MTU_CTRL_TBL + PPE_MRU_MTU_CTRL_TBL_INC * port,
+		     mru_mtu_cfg.val, sizeof(mru_mtu_cfg.val));
+	mru_mtu_cfg.bf.rx_cnt_en = enable;
+	mru_mtu_cfg.bf.tx_cnt_en = enable;
+	ppe_write_tbl(ppe_dev, PPE_MRU_MTU_CTRL_TBL + PPE_MRU_MTU_CTRL_TBL_INC * port,
+		      mru_mtu_cfg.val, sizeof(mru_mtu_cfg.val));
+
+	ppe_mask(ppe_dev, PPE_MC_MTU_CTRL_TBL + PPE_MC_MTU_CTRL_TBL_INC * port,
+		 PPE_MC_MTU_CTRL_TBL_TX_CNT_EN,
+		 FIELD_PREP(PPE_MC_MTU_CTRL_TBL_TX_CNT_EN, enable));
+
+	return ppe_mask(ppe_dev, PPE_PORT_EG_VLAN + PPE_PORT_EG_VLAN_INC * port,
+			PPE_PORT_EG_VLAN_TX_COUNTING_EN,
+			FIELD_PREP(PPE_PORT_EG_VLAN_TX_COUNTING_EN, enable));
+}
+
 static const struct ppe_queue_ops qcom_ppe_queue_config_ops = {
 	.queue_scheduler_set = ppe_queue_scheduler_set,
 	.queue_scheduler_get = ppe_queue_scheduler_get,
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_ops.h b/drivers/net/ethernet/qualcomm/ppe/ppe_ops.h
index b3c1ade7c948..ab64a760b60b 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_ops.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_ops.h
@@ -183,4 +183,5 @@  const struct ppe_queue_ops *ppe_queue_config_ops_get(void);
 int ppe_servcode_config_set(struct ppe_device *ppe_dev,
 			    int servcode,
 			    struct ppe_servcode_cfg cfg);
+int ppe_counter_set(struct ppe_device *ppe_dev, int port, bool enable);
 #endif
diff --git a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
index 66ddfd5cd123..3e61de54f921 100644
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_regs.h
@@ -14,6 +14,11 @@ 
 #define PPE_BM_TDM_CTRL_TDM_OFFSET				GENMASK(14, 8)
 #define PPE_BM_TDM_CTRL_TDM_EN					BIT(31)
 
+#define PPE_RX_FIFO_CFG						0xb004
+#define PPE_RX_FIFO_CFG_NUM					8
+#define PPE_RX_FIFO_CFG_INC					4
+#define PPE_RX_FIFO_CFG_THRSH					GENMASK(2, 0)
+
 #define PPE_BM_TDM_CFG_TBL					0xc000
 #define PPE_BM_TDM_CFG_TBL_NUM					128
 #define PPE_BM_TDM_CFG_TBL_INC					0x10
@@ -43,6 +48,17 @@  union ppe_service_cfg_u {
 	struct ppe_service_cfg bf;
 };
 
+#define PPE_PORT_EG_VLAN					0x20020
+#define PPE_PORT_EG_VLAN_NUM					8
+#define PPE_PORT_EG_VLAN_INC					4
+#define PPE_PORT_EG_VLAN_PORT_VLAN_TYPE				BIT(0)
+#define PPE_PORT_EG_VLAN_PORT_EG_VLAN_CTAG_MODE			GENMASK(2, 1)
+#define PPE_PORT_EG_VLAN_PORT_EG_VLAN_STAG_MODE			GENMASK(4, 3)
+#define PPE_PORT_EG_VLAN_VSI_TAG_MODE_EN			BIT(5)
+#define PPE_PORT_EG_VLAN_PORT_EG_PCP_PROP_CMD			BIT(6)
+#define PPE_PORT_EG_VLAN_PORT_EG_DEI_PROP_CMD			BIT(7)
+#define PPE_PORT_EG_VLAN_TX_COUNTING_EN				BIT(8)
+
 #define PPE_EG_BRIDGE_CONFIG					0x20044
 #define PPE_EG_BRIDGE_CONFIG_QUEUE_CNT_EN			BIT(2)
 
@@ -73,6 +89,59 @@  union ppe_eg_service_cfg_u {
 	struct ppe_eg_service_cfg bf;
 };
 
+#define PPE_TX_BUFF_THRSH					0x26100
+#define PPE_TX_BUFF_THRSH_NUM					8
+#define PPE_TX_BUFF_THRSH_INC					4
+#define PPE_TX_BUFF_THRSH_XOFF					GENMASK(7, 0)
+#define PPE_TX_BUFF_THRSH_XON					GENMASK(15, 8)
+
+#define PPE_MC_MTU_CTRL_TBL					0x60a00
+#define PPE_MC_MTU_CTRL_TBL_NUM					8
+#define PPE_MC_MTU_CTRL_TBL_INC					4
+#define PPE_MC_MTU_CTRL_TBL_MTU					GENMASK(13, 0)
+#define PPE_MC_MTU_CTRL_TBL_MTU_CMD				GENMASK(15, 14)
+#define PPE_MC_MTU_CTRL_TBL_TX_CNT_EN				BIT(16)
+
+#define PPE_MRU_MTU_CTRL_TBL					0x65000
+#define PPE_MRU_MTU_CTRL_TBL_NUM				256
+#define PPE_MRU_MTU_CTRL_TBL_INC				0x10
+
+/* PPE port control configuration, the MTU and QoS are configured by
+ * this table.
+ */
+struct ppe_mru_mtu_ctrl_cfg {
+	u32 mru:14,
+	    mru_cmd:2,
+	    mtu:14,
+	    mtu_cmd:2;
+
+	u32 rx_cnt_en:1,
+	    tx_cnt_en:1,
+	    src_profile:2,
+	    pcp_qos_group_id:1,
+	    dscp_qos_group_id:1,
+	    pcp_res_prec_force:1,
+	    dscp_res_prec_force:1,
+	    preheader_res_prec:3,
+	    pcp_res_prec:3,
+	    dscp_res_prec:3,
+	    flow_res_prec:3,
+	    pre_acl_res_prec:3,
+	    post_acl_res_prec:3,
+	    source_filtering_bypass:1,
+	    source_filtering_mode:1,
+	    pre_ipo_outer_res_prec:3,
+	    pre_ipo_inner_res_prec_0:1;
+
+	u32 pre_ipo_inner_res_prec_1:2,
+	    res0:30;
+};
+
+union ppe_mru_mtu_ctrl_cfg_u {
+	u32 val[3];
+	struct ppe_mru_mtu_ctrl_cfg bf;
+};
+
 #define PPE_IN_L2_SERVICE_TBL					0x66000
 #define PPE_IN_L2_SERVICE_TBL_NUM				256
 #define PPE_IN_L2_SERVICE_TBL_INC				0x10