[][Refine QDMA rate control shaper when running PPPQ]
[Description]
Refactor QDMA Per-Port-Per-Queue(PPPQ) mode.
Because QDMA scheduler has 1Gbps rate limitation, the rate control
shaper must be fine-tuned when activating PPPQ mode.
[Release-log]
N/A
Change-Id: Ie7a1c6292e8e3b302deb97e2e78145ce9171cf4d
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5355282
diff --git a/feed/mtkhnat_util/files/mtkhnat.config b/feed/mtkhnat_util/files/mtkhnat.config
index c971c59..f252a98 100755
--- a/feed/mtkhnat_util/files/mtkhnat.config
+++ b/feed/mtkhnat_util/files/mtkhnat.config
@@ -7,7 +7,7 @@
####################################################################
config global global
option enable 1
- option hqos 1
+ option hqos 0
option txq_num 16
option scheduling 'wrr'
option sch0_bw 1000000
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
index f10b169..0e1e91b 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.h
@@ -105,19 +105,24 @@
#define GDMA2_FWD_CFG 0x1500
/* QDMA Tx queue configuration */
-#define QTX_CFG(x) (QDMA_BASE + ((x) * 0x10))
-#define QTX_SCH(x) (QDMA_BASE + 0x4 + ((x) * 0x10))
-#define QTX_TX_SCH_SEL_OFFSET (30)
+#define QTX_CFG(x) (QDMA_BASE + ((x) * 0x10))
+#define QTX_CFG_HW_RESV_CNT_OFFSET (8)
+#define QTX_CFG_SW_RESV_CNT_OFFSET (0)
+
+#define QTX_SCH(x) (QDMA_BASE + 0x4 + ((x) * 0x10))
+#define QTX_SCH_MIN_RATE_EN BIT(27)
+#define QTX_SCH_MAX_RATE_EN BIT(11)
+#define QTX_SCH_MIN_RATE_MAN_OFFSET (20)
+#define QTX_SCH_MIN_RATE_EXP_OFFSET (16)
+#define QTX_SCH_MAX_RATE_WGHT_OFFSET (12)
+#define QTX_SCH_MAX_RATE_MAN_OFFSET (4)
+#define QTX_SCH_MAX_RATE_EXP_OFFSET (0)
/* QDMA Tx scheduler configuration */
-#define QDMA_PAGE (QDMA_BASE + 0x1f0)
-#define QDMA_TX_2SCH_BASE (QDMA_BASE + 0x214)
-#define QTX_MIB_IF (QDMA_BASE + 0x2bc)
-#define QDMA_TX_4SCH_BASE(x) (QDMA_BASE + 0x398 + (((x) >> 1) * 0x4))
-#define QDMA_TX_SCH_MAX_WFQ BIT(15)
-#define QDMA_TX_SCH_RATE_EN BIT(11)
-#define QDMA_RATE_MAN_OFFSET (4)
-#define QDMA_RATE_EXP_OFFSET (0)
+#define QDMA_PAGE (QDMA_BASE + 0x1f0)
+#define QDMA_TX_2SCH_BASE (QDMA_BASE + 0x214)
+#define QTX_MIB_IF (QDMA_BASE + 0x2bc)
+#define QDMA_TX_4SCH_BASE(x) (QDMA_BASE + 0x398 + (((x) >> 1) * 0x4))
/*--------------------------------------------------------------------------*/
/* Register Mask*/
@@ -855,6 +860,7 @@
#define IS_GMAC1_MODE ((hnat_priv->gmac_num == 1) ? 1 : 0)
#define IS_HQOS_MODE (qos_toggle == 1)
#define IS_PPPQ_MODE (qos_toggle == 2) /* Per Port Per Queue */
+#define MAX_PPPQ_PORT_NUM 6
#define es(entry) (entry_state[entry->bfib1.state])
#define ei(entry, end) (hnat_priv->foe_etry_num - (int)(end - entry))
@@ -948,6 +954,7 @@
int hnat_enable_hook(void);
int hnat_disable_hook(void);
void hnat_cache_ebl(int enable);
+void hnat_qos_shaper_ebl(u32 id, u32 enable);
void set_gmac_ppe_fwd(int gmac_no, int enable);
int entry_detail(u32 ppe_id, int index);
int entry_delete_by_mac(u8 *mac);
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
index c6978fa..a7453af 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_debugfs.c
@@ -1951,6 +1951,7 @@
{
char buf[8] = {0};
int len = count;
+ u32 id;
if ((len > 8) || copy_from_user(buf, buffer, len))
return -EFAULT;
@@ -1958,9 +1959,19 @@
if (buf[0] == '1' && !hook_toggle) {
pr_info("hook is going to be enabled !\n");
hnat_enable_hook();
+
+ if (IS_PPPQ_MODE) {
+ for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
+ hnat_qos_shaper_ebl(id, 1);
+ }
} else if (buf[0] == '0' && hook_toggle) {
pr_info("hook is going to be disabled !\n");
hnat_disable_hook();
+
+ if (IS_PPPQ_MODE) {
+ for (id = 0; id < MAX_PPPQ_PORT_NUM; id++)
+ hnat_qos_shaper_ebl(id, 0);
+ }
}
return len;
@@ -1986,26 +1997,67 @@
return single_open(file, hnat_qos_toggle_read, file->private_data);
}
+void hnat_qos_shaper_ebl(u32 id, u32 enable)
+{
+ struct mtk_hnat *h = hnat_priv;
+ u32 cfg;
+
+ if (enable) {
+ cfg = QTX_SCH_MIN_RATE_EN | QTX_SCH_MAX_RATE_EN;
+ cfg |= (1 << QTX_SCH_MIN_RATE_MAN_OFFSET) |
+ (4 << QTX_SCH_MIN_RATE_EXP_OFFSET) |
+ (25 << QTX_SCH_MAX_RATE_MAN_OFFSET) |
+ (5 << QTX_SCH_MAX_RATE_EXP_OFFSET) |
+ (4 << QTX_SCH_MAX_RATE_WGHT_OFFSET);
+
+ writel(cfg, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
+ } else {
+ writel(0, h->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
+ }
+}
+
+static void hnat_qos_disable(void)
+{
+ struct mtk_hnat *h = hnat_priv;
+ u32 id;
+
+ for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
+ hnat_qos_shaper_ebl(id, 0);
+ writel(0, h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
+ }
+
+ writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
+ (4 << QTX_CFG_SW_RESV_CNT_OFFSET), h->fe_base + QTX_CFG(0));
+
+ for (id = 0; id < h->data->num_of_sch; id += 2) {
+ if (h->data->num_of_sch == 4)
+ writel(0, h->fe_base + QDMA_TX_4SCH_BASE(id));
+ else
+ writel(0, h->fe_base + QDMA_TX_2SCH_BASE);
+ }
+}
+
static void hnat_qos_pppq_enable(void)
{
- u32 cfg, id;
+ struct mtk_hnat *h = hnat_priv;
+ u32 id;
- for (id = 0; id < hnat_priv->data->num_of_sch; id++) {
- writel(id << QTX_TX_SCH_SEL_OFFSET,
- hnat_priv->fe_base + QTX_SCH(id % NUM_OF_Q_PER_PAGE));
+ for (id = 0; id < MAX_PPPQ_PORT_NUM; id++) {
+ if (hook_toggle)
+ hnat_qos_shaper_ebl(id, 1);
+ else
+ hnat_qos_shaper_ebl(id, 0);
- if (id & 0x1) {
- cfg = 0;
- cfg |= QDMA_TX_SCH_MAX_WFQ | QDMA_TX_SCH_RATE_EN;
- cfg |= 25 << QDMA_RATE_MAN_OFFSET;
- cfg |= 5 << QDMA_RATE_EXP_OFFSET;
- cfg |= cfg << 16;
+ writel((4 << QTX_CFG_HW_RESV_CNT_OFFSET) |
+ (4 << QTX_CFG_SW_RESV_CNT_OFFSET),
+ h->fe_base + QTX_CFG(id % NUM_OF_Q_PER_PAGE));
+ }
- if (hnat_priv->data->num_of_sch == 4)
- writel(cfg, hnat_priv->fe_base + QDMA_TX_4SCH_BASE(id));
- else
- writel(cfg, hnat_priv->fe_base + QDMA_TX_2SCH_BASE);
- }
+ for (id = 0; id < h->data->num_of_sch; id+= 2) {
+ if (h->data->num_of_sch == 4)
+ writel(0, h->fe_base + QDMA_TX_4SCH_BASE(id));
+ else
+ writel(0, h->fe_base + QDMA_TX_2SCH_BASE);
}
}
@@ -2021,6 +2073,7 @@
if (buf[0] == '0') {
pr_info("HQoS is going to be disabled !\n");
qos_toggle = 0;
+ hnat_qos_disable();
} else if (buf[0] == '1') {
pr_info("HQoS mode is going to be enabled !\n");
qos_toggle = 1;