[][Add QDMA Per-Port-Per-Queue(PPPQ) mode]
[Description]
Add Panther QDMA Per-Port-Per-Queue(PPPQ) mode for solving
uplink pause frame issue.
After enabling PPPQ mode, each LAN port will be mapped into
a specified QDMA queue.
[Usage]
- echo 2 > /sys/kernel/debug/hnat/qos_toggle (PPPQ Mode)
- echo 1 > /sys/kernel/debug/hnat/qos_toggle (HQoS Mode)
- echo 0 > /sys/kernel/debug/hnat/qos_toggle (Disable QDMA)
[Release-log]
N/A
Change-Id: Ic554bce717d6384cbb31a4c44cdc7988e82719e7
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/5288809
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
index 5c7d67d..5646a3a 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat.c
@@ -745,7 +745,7 @@
}
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (IS_GMAC1_MODE)
+ if (qos_toggle && IS_GMAC1_MODE)
dev_add_pack(&mtk_pack_type);
#endif
err = hnat_roaming_enable();
@@ -789,7 +789,7 @@
del_timer_sync(&hnat_priv->hnat_reset_timestamp_timer);
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (IS_GMAC1_MODE)
+ if (qos_toggle && IS_GMAC1_MODE)
dev_remove_pack(&mtk_pack_type);
#endif
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 52c8419..19482e5 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
@@ -845,6 +845,8 @@
IS_IPV4_DSLITE(x) | IS_IPV4_MAPE(x) | IS_IPV4_MAPT(x))
#define IS_BOND_MODE (!strncmp(LAN_DEV_NAME, "bond", 4))
#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 es(entry) (entry_state[entry->bfib1.state])
#define ei(entry, end) (hnat_priv->foe_etry_num - (int)(end - entry))
@@ -886,20 +888,20 @@
extern struct mtk_hnat *hnat_priv;
#if defined(CONFIG_NET_DSA_MT7530)
-void hnat_dsa_fill_stag(const struct net_device *netdev,
- struct foe_entry *entry,
- struct flow_offload_hw_path *hw_path,
- u16 eth_proto, int mape);
+u32 hnat_dsa_fill_stag(const struct net_device *netdev,
+ struct foe_entry *entry,
+ struct flow_offload_hw_path *hw_path,
+ u16 eth_proto, int mape);
static inline bool hnat_dsa_is_enable(struct mtk_hnat *priv)
{
return (priv->wan_dsa_port != NONE_DSA_PORT);
}
#else
-static inline void hnat_dsa_fill_stag(const struct net_device *netdev,
- struct foe_entry *entry,
- struct flow_offload_hw_path *hw_path,
- u16 eth_proto, int mape)
+static inline u32 hnat_dsa_fill_stag(const struct net_device *netdev,
+ struct foe_entry *entry,
+ struct flow_offload_hw_path *hw_path,
+ u16 eth_proto, int mape)
{
}
@@ -920,6 +922,7 @@
extern int debug_level;
extern int hook_toggle;
extern int mape_toggle;
+extern int qos_toggle;
int ext_if_add(struct extdev_entry *ext_entry);
int ext_if_del(struct extdev_entry *ext_entry);
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 71df49c..4b9006a 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
@@ -27,6 +27,7 @@
int dbg_cpu_reason;
int hook_toggle;
int mape_toggle;
+int qos_toggle;
unsigned int dbg_cpu_reason_cnt[MAX_CRSN_NUM];
static const char * const entry_state[] = { "INVALID", "UNBIND", "BIND", "FIN" };
@@ -1957,6 +1958,49 @@
.release = single_release,
};
+static int hnat_qos_toggle_read(struct seq_file *m, void *private)
+{
+ pr_info("value=%d, HQoS is %s now!\n", qos_toggle, (qos_toggle) ? "enabled" : "disabled");
+
+ return 0;
+}
+
+static int hnat_qos_toggle_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, hnat_qos_toggle_read, file->private_data);
+}
+
+static ssize_t hnat_qos_toggle_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *data)
+{
+ char buf[8];
+ int len = count;
+
+ if ((len > 8) || copy_from_user(buf, buffer, len))
+ return -EFAULT;
+
+ if (buf[0] == '0' && qos_toggle != 0) {
+ pr_info("HQoS is going to be disabled !\n");
+ qos_toggle = 0;
+ } else if (buf[0] == '1' && qos_toggle != 1) {
+ pr_info("HQoS mode is going to be enabled !\n");
+ qos_toggle = 1;
+ } else if (buf[0] == '2' && qos_toggle != 2) {
+ pr_info("Per-port-per-queue mode is going to be enabled !\n");
+ qos_toggle = 2;
+ }
+
+ return len;
+}
+
+static const struct file_operations hnat_qos_toggle_fops = {
+ .open = hnat_qos_toggle_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .write = hnat_qos_toggle_write,
+ .release = single_release,
+};
+
static int hnat_version_read(struct seq_file *m, void *private)
{
pr_info("HNAT SW version : %s\nHNAT HW version : %d\n", HNAT_SW_VER, hnat_priv->data->version);
@@ -2119,6 +2163,8 @@
&hnat_hook_toggle_fops);
debugfs_create_file("mape_toggle", S_IRUGO | S_IRUGO, root, h,
&hnat_mape_toggle_fops);
+ debugfs_create_file("qos_toggle", S_IRUGO | S_IRUGO, root, h,
+ &hnat_qos_toggle_fops);
debugfs_create_file("hnat_version", S_IRUGO | S_IRUGO, root, h,
&hnat_version_fops);
debugfs_create_file("hnat_ppd_if", S_IRUGO | S_IRUGO, root, h,
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
index c76189d..c36ee98 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_nf_hook.c
@@ -475,7 +475,7 @@
skb->dev = get_dev_from_index(index);
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (eth_hdr(skb)->h_proto == HQOS_MAGIC_TAG) {
+ if (qos_toggle && eth_hdr(skb)->h_proto == HQOS_MAGIC_TAG) {
skb = skb_unshare(skb, GFP_ATOMIC);
if (!skb)
return NF_ACCEPT;
@@ -802,7 +802,7 @@
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
struct vlan_ethhdr *veth;
- if (hnat_priv->data->whnat) {
+ if (qos_toggle && hnat_priv->data->whnat) {
veth = (struct vlan_ethhdr *)skb_mac_header(skb);
if (eth_hdr(skb)->h_proto == HQOS_MAGIC_TAG) {
@@ -846,7 +846,8 @@
/* packets from external devices -> xxx ,step 2, learning stage */
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (do_ext2ge_fast_learn(state->in, skb) && (eth_hdr(skb)->h_proto != HQOS_MAGIC_TAG)) {
+ if (do_ext2ge_fast_learn(state->in, skb) && (!qos_toggle ||
+ (qos_toggle && eth_hdr(skb)->h_proto != HQOS_MAGIC_TAG))) {
#else
if (do_ext2ge_fast_learn(state->in, skb)) {
#endif
@@ -1094,6 +1095,7 @@
u32 gmac = NR_DISCARD;
int udp = 0;
u32 qid = 0;
+ u32 port_id = 0;
int mape = 0;
if (ipv6_hdr(skb)->nexthdr == NEXTHDR_IPIP)
@@ -1352,10 +1354,12 @@
entry.ipv4_hnapt.etype = htons(ETH_P_IP);
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- entry.ipv4_hnapt.iblk2.qid =
- (hnat_priv->data->version == MTK_HNAT_V4) ?
- skb->mark & 0x7f : skb->mark & 0xf;
- entry.ipv4_hnapt.iblk2.fqos = 1;
+ if (qos_toggle) {
+ entry.ipv4_hnapt.iblk2.qid =
+ (hnat_priv->data->version == MTK_HNAT_V4) ?
+ skb->mark & 0x7f : skb->mark & 0xf;
+ entry.ipv4_hnapt.iblk2.fqos = 1;
+ }
#endif
entry.ipv4_hnapt.bfib1.udp =
@@ -1421,8 +1425,9 @@
if (IS_LAN(dev)) {
if (IS_DSA_LAN(dev))
- hnat_dsa_fill_stag(dev, &entry, hw_path,
- ntohs(eth->h_proto), mape);
+ port_id = hnat_dsa_fill_stag(dev, &entry, hw_path,
+ ntohs(eth->h_proto),
+ mape);
if (IS_BOND_MODE)
gmac = ((skb_hnat_entry(skb) >> 1) % hnat_priv->gmac_num) ?
@@ -1431,8 +1436,9 @@
gmac = NR_GMAC1_PORT;
} else if (IS_WAN(dev)) {
if (IS_DSA_WAN(dev))
- hnat_dsa_fill_stag(dev, &entry, hw_path,
- ntohs(eth->h_proto), mape);
+ port_id = hnat_dsa_fill_stag(dev,&entry, hw_path,
+ ntohs(eth->h_proto),
+ mape);
if (mape_toggle && mape == 1) {
gmac = NR_PDMA_PORT;
/* Set act_dp = wan_dev */
@@ -1470,36 +1476,45 @@
return 0;
}
- qid = skb->mark & (MTK_QDMA_TX_MASK);
+ if (IS_HQOS_MODE)
+ qid = skb->mark & (MTK_QDMA_TX_MASK);
+ else if (IS_PPPQ_MODE)
+ qid = port_id & MTK_QDMA_TX_MASK;
+ else
+ qid = 0;
if (IS_IPV4_GRP(foe)) {
entry.ipv4_hnapt.iblk2.dp = gmac;
entry.ipv4_hnapt.iblk2.port_mg =
(hnat_priv->data->version == MTK_HNAT_V1) ? 0x3f : 0;
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (hnat_priv->data->version == MTK_HNAT_V4) {
- entry.ipv4_hnapt.iblk2.qid = qid & 0x7f;
- } else {
- /* qid[5:0]= port_mg[1:0]+ qid[3:0] */
- entry.ipv4_hnapt.iblk2.qid = qid & 0xf;
- if (hnat_priv->data->version != MTK_HNAT_V1)
- entry.ipv4_hnapt.iblk2.port_mg |=
- ((qid >> 4) & 0x3);
+ if (qos_toggle) {
+ if (hnat_priv->data->version == MTK_HNAT_V4) {
+ entry.ipv4_hnapt.iblk2.qid = qid & 0x7f;
+ } else {
+ /* qid[5:0]= port_mg[1:0]+ qid[3:0] */
+ entry.ipv4_hnapt.iblk2.qid = qid & 0xf;
+ if (hnat_priv->data->version != MTK_HNAT_V1)
+ entry.ipv4_hnapt.iblk2.port_mg |=
+ ((qid >> 4) & 0x3);
- if (((IS_EXT(dev) && (FROM_GE_LAN(skb) ||
- FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) ||
- ((mape_toggle && mape == 1) && !FROM_EXT(skb))) &&
- (!whnat)) {
- entry.ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
- entry.ipv4_hnapt.vlan1 = skb_hnat_entry(skb);
- entry.bfib1.vlan_layer = 1;
+ if (((IS_EXT(dev) && (FROM_GE_LAN(skb) ||
+ FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) ||
+ ((mape_toggle && mape == 1) && !FROM_EXT(skb))) &&
+ (!whnat)) {
+ entry.ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv4_hnapt.vlan1 = skb_hnat_entry(skb);
+ entry.bfib1.vlan_layer = 1;
+ }
}
- }
- if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT)
+ if (FROM_EXT(skb) || skb_hnat_sport(skb) == NR_QDMA_PORT)
+ entry.ipv4_hnapt.iblk2.fqos = 0;
+ else
+ entry.ipv4_hnapt.iblk2.fqos = 1;
+ } else {
entry.ipv4_hnapt.iblk2.fqos = 0;
- else
- entry.ipv4_hnapt.iblk2.fqos = 1;
+ }
#else
entry.ipv4_hnapt.iblk2.fqos = 0;
#endif
@@ -1508,28 +1523,32 @@
entry.ipv6_5t_route.iblk2.port_mg =
(hnat_priv->data->version == MTK_HNAT_V1) ? 0x3f : 0;
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (hnat_priv->data->version == MTK_HNAT_V4) {
- entry.ipv6_5t_route.iblk2.qid = qid & 0x7f;
- } else {
- /* qid[5:0]= port_mg[1:0]+ qid[3:0] */
- entry.ipv6_5t_route.iblk2.qid = qid & 0xf;
- if (hnat_priv->data->version != MTK_HNAT_V1)
- entry.ipv6_5t_route.iblk2.port_mg |=
- ((qid >> 4) & 0x3);
+ if (qos_toggle) {
+ if (hnat_priv->data->version == MTK_HNAT_V4) {
+ entry.ipv6_5t_route.iblk2.qid = qid & 0x7f;
+ } else {
+ /* qid[5:0]= port_mg[1:0]+ qid[3:0] */
+ entry.ipv6_5t_route.iblk2.qid = qid & 0xf;
+ if (hnat_priv->data->version != MTK_HNAT_V1)
+ entry.ipv6_5t_route.iblk2.port_mg |=
+ ((qid >> 4) & 0x3);
- if (IS_EXT(dev) && (FROM_GE_LAN(skb) ||
- FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb)) &&
- (!whnat)) {
- entry.ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
- entry.ipv6_5t_route.vlan1 = skb_hnat_entry(skb);
- entry.bfib1.vlan_layer = 1;
+ if (IS_EXT(dev) && (FROM_GE_LAN(skb) ||
+ FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb)) &&
+ (!whnat)) {
+ entry.ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
+ entry.ipv6_5t_route.vlan1 = skb_hnat_entry(skb);
+ entry.bfib1.vlan_layer = 1;
+ }
}
- }
- if (FROM_EXT(skb))
+ if (FROM_EXT(skb))
+ entry.ipv6_5t_route.iblk2.fqos = 0;
+ else
+ entry.ipv6_5t_route.iblk2.fqos = 1;
+ } else {
entry.ipv6_5t_route.iblk2.fqos = 0;
- else
- entry.ipv6_5t_route.iblk2.fqos = 1;
+ }
#else
entry.ipv6_5t_route.iblk2.fqos = 0;
#endif
@@ -1650,6 +1669,10 @@
entry->ipv4_hnapt.winfo.bssid = skb_hnat_bss_id(skb);
entry->ipv4_hnapt.winfo.wcid = skb_hnat_wc_id(skb);
#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
+ if (qos_toggle)
+ entry->ipv4_hnapt.iblk2.fqos = 1;
+#endif
entry->ipv4_hnapt.iblk2.rxid = skb_hnat_rx_id(skb);
entry->ipv4_hnapt.iblk2.winfoi = 1;
#else
@@ -1669,7 +1692,8 @@
}
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (FROM_GE_LAN(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb)) {
+ if (qos_toggle &&
+ (FROM_GE_LAN(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
entry->bfib1.vpm = 0;
entry->bfib1.vlan_layer = 1;
entry->ipv4_hnapt.etype = htons(HQOS_MAGIC_TAG);
@@ -1688,6 +1712,10 @@
entry->ipv6_5t_route.winfo.bssid = skb_hnat_bss_id(skb);
entry->ipv6_5t_route.winfo.wcid = skb_hnat_wc_id(skb);
#if defined(CONFIG_MEDIATEK_NETSYS_V2)
+#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
+ if (qos_toggle)
+ entry->ipv6_5t_route.iblk2.fqos = 1;
+#endif
entry->ipv6_5t_route.iblk2.rxid = skb_hnat_rx_id(skb);
entry->ipv6_5t_route.iblk2.winfoi = 1;
#else
@@ -1707,7 +1735,8 @@
}
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (FROM_GE_LAN(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb)) {
+ if (qos_toggle &&
+ (FROM_GE_LAN(skb) || FROM_GE_WAN(skb) || FROM_GE_VIRTUAL(skb))) {
entry->bfib1.vpm = 0;
entry->bfib1.vlan_layer = 1;
entry->ipv6_5t_route.etype = htons(HQOS_MAGIC_TAG);
@@ -2063,7 +2092,7 @@
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb);
- if (eth_hdr(skb)->h_proto == HQOS_MAGIC_TAG) {
+ if (qos_toggle && eth_hdr(skb)->h_proto == HQOS_MAGIC_TAG) {
skb_hnat_entry(skb) = ntohs(veth->h_vlan_TCI) & 0x3fff;
skb_hnat_reason(skb) = HIT_BIND_FORCE_TO_CPU;
}
@@ -2074,7 +2103,8 @@
/* packets from external devices -> xxx ,step 2, learning stage */
#if defined(CONFIG_NET_MEDIATEK_HW_QOS)
- if (do_ext2ge_fast_learn(state->in, skb) && (eth_hdr(skb)->h_proto != HQOS_MAGIC_TAG)) {
+ if (do_ext2ge_fast_learn(state->in, skb) && (!qos_toggle ||
+ (qos_toggle && eth_hdr(skb)->h_proto != HQOS_MAGIC_TAG))) {
#else
if (do_ext2ge_fast_learn(state->in, skb)) {
#endif
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
index b0fabfb..aa40d99 100644
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_hnat/hnat_stag.c
@@ -8,11 +8,11 @@
#include <net/netfilter/nf_flow_table.h>
#include "hnat.h"
-void hnat_dsa_fill_stag(const struct net_device *netdev,
- struct foe_entry *entry,
- struct flow_offload_hw_path *hw_path,
- u16 eth_proto,
- int mape)
+u32 hnat_dsa_fill_stag(const struct net_device *netdev,
+ struct foe_entry *entry,
+ struct flow_offload_hw_path *hw_path,
+ u16 eth_proto,
+ int mape)
{
const struct net_device *ndev;
const unsigned int *port_reg;
@@ -54,4 +54,6 @@
default:
pr_info("DSA + HNAT unsupport protocol\n");
}
+
+ return port_index;
}
diff --git a/target/linux/mediatek/modules.mk b/target/linux/mediatek/modules.mk
index 67a983a..2ce0201 100644
--- a/target/linux/mediatek/modules.mk
+++ b/target/linux/mediatek/modules.mk
@@ -70,7 +70,7 @@
CONFIG_BRIDGE_NETFILTER=y \
CONFIG_NETFILTER_FAMILY_BRIDGE=y \
CONFIG_NET_MEDIATEK_HNAT \
- CONFIG_NET_MEDIATEK_HW_QOS=n
+ CONFIG_NET_MEDIATEK_HW_QOS=y
FILES:= \
$(LINUX_DIR)/drivers/net/ethernet/mediatek/mtk_hnat/mtkhnat.ko
endef