Files
openwrt_mitrastar/target/linux/qualcommbe/patches-6.12/0337-net-ethernet-qualcomm-Add-PPE-scheduler-config.patch
Alexandru Gagniuc f3fc278fcb qualcommbe: v6.12: add PPE driver (part 2)
Add the second part of the PPE driver. This includes the EDMA and
network device support. This part does not appear to have been
officially submitted for upstream review. The series is taken from
target/linux/qualcommbe/patches-6.6, and had to be heavily modified
in order to compile of v6.12. Changes to patches are noted in the
respective patch body.

Also add the PPE and EDMA nodes in this series.

Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/18796
Signed-off-by: Robert Marko <robimarko@gmail.com>
2025-05-31 12:25:48 +02:00

202 lines
7.1 KiB
Diff

From 93cf3297818ee61607f0a8d1d34e4fb7fcde3cdf Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Tue, 26 Dec 2023 20:18:09 +0800
Subject: [PATCH] net: ethernet: qualcomm: Add PPE scheduler config
PPE scheduler config determines the priority of scheduling the
packet. The scheduler config is used for supporting the QoS
offload in PPE hardware.
Change-Id: I4811bd133074757371775a6a69a1cc3cfaa8d0d0
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Alex G: rebase patch on top of PPE driver submission from 20250209.
Add the ppe_queue_priority_set() function and its
dependencies. They will be used in the edma support in
susequent changes.
ppe_queue_priority_set() used to be part of ppe_api.c, and
is hereby moved to ppe_config.c .
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
---
.../net/ethernet/qualcomm/ppe/ppe_config.c | 141 ++++++++++++++++++
.../net/ethernet/qualcomm/ppe/ppe_config.h | 5 +
2 files changed, 146 insertions(+)
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.c
@@ -864,6 +864,51 @@ static int ppe_scheduler_l0_queue_map_se
val);
}
+/* Get the first level scheduler configuration. */
+static int ppe_scheduler_l0_queue_map_get(struct ppe_device *ppe_dev,
+ int node_id, int *port,
+ struct ppe_scheduler_cfg *scheduler_cfg)
+{
+ u32 val, reg;
+ int ret;
+
+ reg = PPE_L0_FLOW_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_MAP_TBL_INC;
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ scheduler_cfg->flow_id = FIELD_GET(PPE_L0_FLOW_MAP_TBL_FLOW_ID, val);
+ scheduler_cfg->pri = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_PRI, val);
+ scheduler_cfg->drr_node_wt = FIELD_GET(PPE_L0_FLOW_MAP_TBL_C_NODE_WT, val);
+
+ reg = PPE_L0_C_FLOW_CFG_TBL_ADDR +
+ (scheduler_cfg->flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg->pri) *
+ PPE_L0_C_FLOW_CFG_TBL_INC;
+
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ scheduler_cfg->drr_node_id = FIELD_GET(PPE_L0_C_FLOW_CFG_TBL_NODE_ID, val);
+ scheduler_cfg->unit_is_packet = FIELD_GET(PPE_L0_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, val);
+
+ reg = PPE_L0_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L0_FLOW_PORT_MAP_TBL_INC;
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ *port = FIELD_GET(PPE_L0_FLOW_PORT_MAP_TBL_PORT_NUM, val);
+
+ reg = PPE_L0_COMP_CFG_TBL_ADDR + node_id * PPE_L0_COMP_CFG_TBL_INC;
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ scheduler_cfg->frame_mode = FIELD_GET(PPE_L0_COMP_CFG_TBL_NODE_METER_LEN, val);
+
+ return 0;
+}
+
/* Set the PPE flow level scheduler configuration. */
static int ppe_scheduler_l1_queue_map_set(struct ppe_device *ppe_dev,
int node_id, int port,
@@ -916,6 +961,50 @@ static int ppe_scheduler_l1_queue_map_se
return regmap_update_bits(ppe_dev->regmap, reg, PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val);
}
+/* Get the second level scheduler configuration. */
+static int ppe_scheduler_l1_queue_map_get(struct ppe_device *ppe_dev,
+ int node_id, int *port,
+ struct ppe_scheduler_cfg *scheduler_cfg)
+{
+ u32 val, reg;
+ int ret;
+
+ reg = PPE_L1_FLOW_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_MAP_TBL_INC;
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ scheduler_cfg->flow_id = FIELD_GET(PPE_L1_FLOW_MAP_TBL_FLOW_ID, val);
+ scheduler_cfg->pri = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_PRI, val);
+ scheduler_cfg->drr_node_wt = FIELD_GET(PPE_L1_FLOW_MAP_TBL_C_NODE_WT, val);
+
+ reg = PPE_L1_C_FLOW_CFG_TBL_ADDR +
+ (scheduler_cfg->flow_id * PPE_QUEUE_SCH_PRI_NUM + scheduler_cfg->pri) *
+ PPE_L1_C_FLOW_CFG_TBL_INC;
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ scheduler_cfg->drr_node_id = FIELD_GET(PPE_L1_C_FLOW_CFG_TBL_NODE_ID, val);
+ scheduler_cfg->unit_is_packet = FIELD_GET(PPE_L1_C_FLOW_CFG_TBL_NODE_CREDIT_UNIT, val);
+
+ reg = PPE_L1_FLOW_PORT_MAP_TBL_ADDR + node_id * PPE_L1_FLOW_PORT_MAP_TBL_INC;
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ *port = FIELD_GET(PPE_L1_FLOW_PORT_MAP_TBL_PORT_NUM, val);
+
+ reg = PPE_L1_COMP_CFG_TBL_ADDR + node_id * PPE_L1_COMP_CFG_TBL_INC;
+ ret = regmap_read(ppe_dev->regmap, reg, &val);
+ if (ret)
+ return ret;
+
+ scheduler_cfg->frame_mode = FIELD_GET(PPE_L1_COMP_CFG_TBL_NODE_METER_LEN, val);
+
+ return 0;
+}
+
/**
* ppe_queue_scheduler_set - Configure scheduler for PPE hardware queue
* @ppe_dev: PPE device
@@ -942,6 +1031,58 @@ int ppe_queue_scheduler_set(struct ppe_d
}
/**
+ * ppe_queue_scheduler_get - get QoS scheduler of PPE hardware queue
+ * @ppe_dev: PPE device
+ * @node_id: PPE node ID
+ * @flow_level: Flow level scheduler or queue level scheduler
+ * @port: PPE port ID to get scheduler config
+ * @scheduler_cfg: QoS scheduler configuration
+ *
+ * The hardware QoS function is supported by PPE, the current scheduler
+ * configuration can be acquired based on the queue ID of PPE port.
+ *
+ * Return 0 on success, negative error code on failure.
+ */
+int ppe_queue_scheduler_get(struct ppe_device *ppe_dev,
+ int node_id, bool flow_level, int *port,
+ struct ppe_scheduler_cfg *scheduler_cfg)
+{
+ if (flow_level)
+ return ppe_scheduler_l1_queue_map_get(ppe_dev, node_id,
+ port, scheduler_cfg);
+
+ return ppe_scheduler_l0_queue_map_get(ppe_dev, node_id,
+ port, scheduler_cfg);
+}
+
+
+/**
+ * ppe_queue_priority_set - set scheduler priority of PPE hardware queue
+ * @ppe_dev: PPE device
+ * @node_id: PPE hardware node ID, which is either queue ID or flow ID
+ * @priority: Qos scheduler priority
+ *
+ * Configure scheduler priority of PPE hardware queque, the maximum node
+ * ID supported is PPE_QUEUE_ID_NUM added by PPE_FLOW_ID_NUM, queue ID
+ * belongs to level 0, flow ID belongs to level 1 in the packet pipeline.
+ *
+ * Return 0 on success, negative error code on failure.
+ */
+int ppe_queue_priority_set(struct ppe_device *ppe_dev,
+ int node_id, int priority)
+{
+ struct ppe_scheduler_cfg sch_cfg;
+ int ret, port, level = 0;
+
+ ret = ppe_queue_scheduler_get(ppe_dev, node_id, level, &port, &sch_cfg);
+ if (ret)
+ return ret;
+
+ sch_cfg.pri = priority;
+ return ppe_queue_scheduler_set(ppe_dev, node_id, level, port, sch_cfg);
+}
+
+/**
* ppe_queue_ucast_base_set - Set PPE unicast queue base ID and profile ID
* @ppe_dev: PPE device
* @queue_dst: PPE queue destination configuration
--- a/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
+++ b/drivers/net/ethernet/qualcomm/ppe/ppe_config.h
@@ -291,6 +291,11 @@ int ppe_hw_config(struct ppe_device *ppe
int ppe_queue_scheduler_set(struct ppe_device *ppe_dev,
int node_id, bool flow_level, int port,
struct ppe_scheduler_cfg scheduler_cfg);
+int ppe_queue_scheduler_get(struct ppe_device *ppe_dev,
+ int node_id, bool flow_level, int *port,
+ struct ppe_scheduler_cfg *scheduler_cfg);
+int ppe_queue_priority_set(struct ppe_device *ppe_dev,
+ int queue_id, int priority);
int ppe_queue_ucast_base_set(struct ppe_device *ppe_dev,
struct ppe_queue_ucast_dest queue_dst,
int queue_base,