From 5781f6d07108a369208c7ceb4dfc7febe210f8a3 Mon Sep 17 00:00:00 2001
From: "Wu, Qiming" <qi-ming.wu@intel.com>
Date: Mon, 12 Feb 2018 07:45:01 +0100
Subject: [PATCH] Merge pull request #234 in SW_PON/linux from
 DRVLIB_SW-559-datapath-hw-capability-api-support to xrx500

* commit '8e05571678045e0a23b0aba4a598c0d2ba5c769a':
  Jira DRVLIB_SW-559: fix multiple dev_put issue in the proc
  Jira DRVLIB_SW-559: fix some memory leakage issue
  Jira DRVLIB_SW-559: implement datapath HW capability as requested
---
 .../ethernet/lantiq/datapath/datapath_api.c   | 45 +++++++++++----
 .../lantiq/datapath/datapath_instance.c       | 51 ++++++++++++++---
 .../ethernet/lantiq/datapath/datapath_proc.c  | 56 ++++++++++---------
 .../lantiq/datapath/gswip30/datapath_misc.c   | 19 ++++++-
 .../lantiq/datapath/gswip31/datapath_misc.c   | 18 +++++-
 .../lantiq/datapath/gswip31/datapath_ppv4.h   |  1 +
 include/net/datapath_api.h                    | 49 ++++++++++------
 include/net/datapath_inst.h                   |  1 +
 8 files changed, 175 insertions(+), 65 deletions(-)

diff --git a/drivers/net/ethernet/lantiq/datapath/datapath_api.c b/drivers/net/ethernet/lantiq/datapath/datapath_api.c
index 7b72b27bf..0ea926f34 100644
--- a/drivers/net/ethernet/lantiq/datapath/datapath_api.c
+++ b/drivers/net/ethernet/lantiq/datapath/datapath_api.c
@@ -160,7 +160,7 @@ static inline int parser_enabled(int ep, struct dma_rx_desc_1 *desc_1)
 
 struct pmac_port_info *get_port_info(int inst, int index)
 {
-	if (index < dp_port_prop[inst].info.max_ports)
+	if (index < dp_port_prop[inst].info.cap.max_num_dp_ports)
 		return &dp_port_info[inst][index];
 
 	return NULL;
@@ -168,7 +168,7 @@ struct pmac_port_info *get_port_info(int inst, int index)
 
 u32 *get_port_flag(int inst, int index)
 {
-	if (index < dp_port_prop[inst].info.max_ports)
+	if (index < dp_port_prop[inst].info.cap.max_num_dp_ports)
 		return &dp_port_info[inst][index].alloc_flags;
 
 	return NULL;
@@ -178,7 +178,7 @@ struct pmac_port_info *get_port_info_via_dp_port(int inst, int dp_port)
 {
 	int i;
 
-	for (i = 0; i < dp_port_prop[inst].info.max_ports; i++) {
+	for (i = 0; i < dp_port_prop[inst].info.cap.max_num_dp_ports; i++) {
 		if ((dp_port_info[inst][i].status & PORT_DEV_REGISTERED) &&
 		    (dp_port_info[inst][i].port_id == dp_port))
 			return &dp_port_info[inst][i];
@@ -192,7 +192,7 @@ struct pmac_port_info *get_port_info_via_dp_name(struct net_device *dev)
 	int i;
 	int inst = dp_get_inst_via_dev(dev, NULL, 0);
 
-	for (i = 0; i < dp_port_prop[inst].info.max_ports; i++) {
+	for (i = 0; i < dp_port_prop[inst].info.cap.max_num_dp_ports; i++) {
 		if ((dp_port_info[inst][i].status & PORT_DEV_REGISTERED) &&
 		    (dp_port_info[inst][i].dev == dev))
 			return &dp_port_info[inst][i];
@@ -1045,7 +1045,7 @@ int32_t dp_get_netif_subifid(struct net_device *netif, struct sk_buff *skb,
 		inst = dp_get_inst_via_dev(netif, NULL, 0);
 
 	DP_LIB_LOCK(&dp_lock);
-	for (k = 0; k < dp_port_prop[inst].info.max_ports; k++) {
+	for (k = 0; k < dp_port_prop[inst].info.cap.max_num_dp_ports; k++) {
 		if (dp_port_info[inst][k].status != PORT_SUBIF_REGISTERED)
 			continue;
 
@@ -1168,7 +1168,7 @@ int update_coc_up_sub_module(enum ltq_cpufreq_state new_state,
 	dp_coc_confirm_stat fn;
 	int inst = 0;
 
-	for (i = 0; i < dp_port_prop[inst].info.max_ports; i++) {
+	for (i = 0; i < dp_port_prop[inst].info.cap.max_num_dp_ports; i++) {
 		fn = dp_port_info[inst][i].cb.dp_coc_confirm_stat_fn;
 
 		if (fn)
@@ -1189,7 +1189,7 @@ int dp_get_port_subitf_via_dev_private(struct net_device *dev,
 	int inst;
 
 	inst = dp_get_inst_via_dev(dev, NULL, 0);
-	for (i = 0; i < dp_port_prop[inst].info.max_ports; i++)
+	for (i = 0; i < dp_port_prop[inst].info.cap.max_num_dp_ports; i++)
 		for (j = 0; j < dp_port_info[inst][i].ctp_max; j++) {
 			if (dp_port_info[inst][i].subif_info[j].netif != dev)
 				continue;
@@ -1224,7 +1224,7 @@ int dp_get_port_subitf_via_ifname_private(char *ifname, dp_subif_t *subif)
 
 	inst = dp_get_inst_via_dev(NULL, ifname, 0);
 
-	for (i = 0; i < dp_port_prop[inst].info.max_ports; i++) {
+	for (i = 0; i < dp_port_prop[inst].info.cap.max_num_dp_ports; i++) {
 		for (j = 0; j < dp_port_info[inst][i].ctp_max; j++) {
 			if (strcmp
 			    (dp_port_info[inst][i].subif_info[j].device_name,
@@ -1283,7 +1283,7 @@ int32_t dp_check_if_netif_fastpath_fn(struct net_device *netif,
 	}
 
 	if (tmp_subif.port_id <= 0 && tmp_subif.port_id >=
-	    dp_port_prop[tmp_subif.inst].info.max_ports)
+	    dp_port_prop[tmp_subif.inst].info.cap.max_num_dp_ports)
 		res = 0;
 	else if (!(dp_port_info[tmp_subif.inst][tmp_subif.port_id].alloc_flags &
 		 (DP_F_FAST_DSL || DP_F_FAST_ETH_LAN ||
@@ -1305,7 +1305,7 @@ struct module *dp_get_module_owner(int ep)
 		return NULL;
 	}
 
-	if ((ep >= 0) && (ep < dp_port_prop[inst].info.max_ports))
+	if ((ep >= 0) && (ep < dp_port_prop[inst].info.cap.max_num_dp_ports))
 		return dp_port_info[inst][ep].owner;
 
 	return NULL;
@@ -1764,7 +1764,8 @@ static inline int32_t dp_rx_one_skb(struct sk_buff *skb, uint32_t flags)
 		return DP_SUCCESS;
 	}
 
-	if (unlikely(port_id >= dp_port_prop[inst].info.max_ports - 1)) {
+	if (unlikely(port_id >=
+	    dp_port_prop[inst].info.cap.max_num_dp_ports - 1)) {
 		PR_ERR("Drop for wrong ep or src port id=%u ??\n",
 		       port_id);
 		goto RX_DROP;
@@ -1924,7 +1925,7 @@ int32_t dp_xmit(struct net_device *rx_if, dp_subif_t *rx_subif,
 	}
 #endif
 	ep = rx_subif->port_id;
-	if (unlikely(ep >= dp_port_prop[inst].info.max_ports)) {
+	if (unlikely(ep >= dp_port_prop[inst].info.cap.max_num_dp_ports)) {
 		err_ret = DP_XMIT_ERR_PORT_TOO_BIG;
 		goto lbl_err_ret;
 	}
@@ -2195,6 +2196,26 @@ uint32_t get_dp_dbg_flag(void)
 	return dp_dbg_flag;
 }
 
+/*!
+ *@brief  The API is for dp_get_cap
+ *@param[in,out] cap dp_cap pointer, caller must provide the buffer
+ *@param[in] flag for future
+ *@return 0 if OK / -1 if error
+ */
+int dp_get_cap(struct dp_cap *cap, int flag)
+{
+	if (!cap)
+		return DP_FAILURE;
+	if ((cap->inst < 0) || (cap->inst >= DP_MAX_INST))
+		return DP_FAILURE;
+	if (!hw_cap_list[cap->inst].valid)
+		return DP_FAILURE;
+	*cap = hw_cap_list[cap->inst].info.cap;
+
+	return DP_SUCCESS;
+}
+EXPORT_SYMBOL(dp_get_cap);
+
 #ifdef DP_TEST_EXAMPLE
 void test(void)
 {
diff --git a/drivers/net/ethernet/lantiq/datapath/datapath_instance.c b/drivers/net/ethernet/lantiq/datapath/datapath_instance.c
index ae431e007..02e4ca5d1 100644
--- a/drivers/net/ethernet/lantiq/datapath/datapath_instance.c
+++ b/drivers/net/ethernet/lantiq/datapath/datapath_instance.c
@@ -478,6 +478,40 @@ int proc_inst_dev_start(void)
 	return 0;
 }
 
+static void dump_cap(struct seq_file *s, struct dp_cap *cap)
+{
+	if (!s)
+		return;
+	seq_printf(s, "	HW TX checksum offloading: %s\n",
+		   cap->tx_hw_chksum ? "Yes" : "No");
+	seq_printf(s, "	HW RX checksum verification: %s\n",
+		   cap->rx_hw_chksum ? "Yes" : "No");
+	seq_printf(s, "	HW TSO: %s\n",
+		   cap->hw_tso ? "Yes" : "No");
+	seq_printf(s, "	HW GSO: %s\n",
+		   cap->hw_gso ? "Yes" : "No");
+	seq_printf(s, "	QOS Engine: %s\n",
+		   cap->qos_eng_name);
+	seq_printf(s, "	Pkt Engine: %s\n",
+		   cap->pkt_eng_name);
+	seq_printf(s, "	max_num_queues: %d\n",
+		   cap->max_num_queues);
+	seq_printf(s, "	max_num_scheds: %d\n",
+		   cap->max_num_scheds);
+	seq_printf(s, "	max_num_deq_ports: %d\n",
+		   cap->max_num_deq_ports);
+	seq_printf(s, "	max_num_qos_ports: %d\n",
+		   cap->max_num_qos_ports);
+	seq_printf(s, "	max_num_dp_ports: %d\n",
+		   cap->max_num_dp_ports);
+	seq_printf(s, "	max_num_subif_per_port: %d\n",
+		   cap->max_num_subif_per_port);
+	seq_printf(s, "	max_num_subif: %d\n",
+		   cap->max_num_subif);
+	seq_printf(s, "	max_num_bridge_port: %d\n",
+		   cap->max_num_bridge_port);
+}
+
 static u32 mod_hash_index;
 static struct dp_mod *dp_mod_proc;
 int proc_inst_mod_dump(struct seq_file *s, int pos)
@@ -508,14 +542,18 @@ int proc_inst_mod_dump(struct seq_file *s, int pos)
 
 int proc_inst_dump(struct seq_file *s, int pos)
 {
+	struct dp_cap cap;
+
 	if (!dp_port_prop[pos].valid)
 		goto NEXT;
-	seq_printf(s, "Inst[%d] Type=%u ver=%d ports=%d subifs=%d\n",
+	seq_printf(s, "Inst[%d] Type=%u ver=%d\n",
 		   pos,
 		   dp_port_prop[pos].info.type,
-		   dp_port_prop[pos].info.ver,
-		   dp_port_prop[pos].info.max_ports,
-		   dp_port_prop[pos].info.max_port_subifs);
+		   dp_port_prop[pos].info.ver);
+	/*dump_cap(s, &dp_port_prop[pos].info.cap);*/
+	cap.inst = pos;
+	dp_get_cap(&cap, 0);
+	dump_cap(s, &cap);
 
 NEXT:
 	pos++;
@@ -529,13 +567,12 @@ int proc_inst_hal_dump(struct seq_file *s, int pos)
 	if (!hw_cap_list[pos].valid)
 		goto NEXT;
 
-	seq_printf(s, "HAL[%d] Type=%u ver=%d ports=%d subifs=%d dp_cap_num=%d\n",
+	seq_printf(s, "HAL[%d] Type=%u ver=%d dp_cap_num=%d\n",
 		   pos,
 		   hw_cap_list[pos].info.type,
 		   hw_cap_list[pos].info.ver,
-		   hw_cap_list[pos].info.max_ports,
-		   hw_cap_list[pos].info.max_port_subifs,
 		   dp_cap_num);
+	dump_cap(s, &hw_cap_list[pos].info.cap);
 
 NEXT:
 	pos++;
diff --git a/drivers/net/ethernet/lantiq/datapath/datapath_proc.c b/drivers/net/ethernet/lantiq/datapath/datapath_proc.c
index 71712a386..ece8cb1d8 100644
--- a/drivers/net/ethernet/lantiq/datapath/datapath_proc.c
+++ b/drivers/net/ethernet/lantiq/datapath/datapath_proc.c
@@ -781,7 +781,7 @@ ssize_t proc_logical_dev_write(struct file *file, const char *buf,
 	char *param_list[20 * 4];
 	unsigned int num;
 	struct net_device *dev = NULL, *base = NULL;
-	dp_subif_t subif = {0};
+	dp_subif_t *subif = NULL;
 	struct pmac_port_info *port_info;
 
 	len = (sizeof(str) > count) ? count : sizeof(str) - 1;
@@ -790,6 +790,11 @@ ssize_t proc_logical_dev_write(struct file *file, const char *buf,
 	num = dp_split_buffer(str, param_list, ARRAY_SIZE(param_list));
 	if (num <= 1)
 		goto HELP;
+	subif = kmalloc(sizeof(*subif), GFP_KERNEL);
+	if (!subif) {
+		PR_INFO("kmalloc failed for %d bytes\n", sizeof(*subif));
+		goto EXIT1;
+	}
 	if (dp_strcmpi(param_list[0], "check") == 0) {
 		struct vlan_prop vlan_prop = {0};
 
@@ -798,17 +803,16 @@ ssize_t proc_logical_dev_write(struct file *file, const char *buf,
 		dev = dev_get_by_name(&init_net, param_list[1]);
 		if (!dev) {
 			PR_INFO("No such device:%s\n", param_list[1]);
-			return count;
+			goto EXIT1;
 		}
 		get_vlan_via_dev(dev, &vlan_prop);
-		dev_put(dev);
 		if (!vlan_prop.num) {
 			PR_INFO("No VLAN interface %s\n", param_list[1]);
-			return count;
+			goto EXIT1;
 		}
 		if (!vlan_prop.base) {
 			PR_INFO("No base found for %s\n", param_list[1]);
-			return count;
+			goto EXIT1;
 		}
 		if (vlan_prop.num > 0)
 			PR_INFO("outer VLAN proto=%x, vid=%d\n",
@@ -818,7 +822,7 @@ ssize_t proc_logical_dev_write(struct file *file, const char *buf,
 				vlan_prop.in_proto, vlan_prop.in_vid);
 		PR_INFO("base of %s: %s\n",
 			param_list[0], vlan_prop.base->name);
-		return count;
+		goto EXIT1;
 	} else if (dp_strcmpi(param_list[0], "set") == 0) {
 		u32 flag = DP_F_SUBIF_LOGICAL;
 
@@ -836,19 +840,19 @@ ssize_t proc_logical_dev_write(struct file *file, const char *buf,
 			base = dev;
 			flag = 0;
 		}
-		if (dp_get_netif_subifid(base, NULL, NULL, NULL, &subif, 0)) {
+		if (dp_get_netif_subifid(base, NULL, NULL, NULL, subif, 0)) {
 			PR_INFO("dp_get_netif_subifid fail:%s\n", base->name);
 			goto EXIT1;
 		}
-		port_info = get_port_info_via_dp_port(0, subif.port_id);
+		port_info = get_port_info_via_dp_port(0, subif->port_id);
 		if (!port_info) {
 			PR_INFO("get_port_info_via_dp_port fail: port_id:%d\n",
-				subif.port_id);
+				subif->port_id);
 			goto EXIT1;
 		}
-		subif.subif = -1;
+		subif->subif = -1;
 		if (dp_register_subif(port_info->owner, dev,
-				      dev->name, &subif, flag)) {
+				      dev->name, subif, flag)) {
 			PR_INFO("dp_register_subif fail: %s\n",
 				dev->name);
 			goto EXIT1;
@@ -870,27 +874,26 @@ ssize_t proc_logical_dev_write(struct file *file, const char *buf,
 		base = get_base_dev(dev, -1);
 		if (!base)
 			base = dev;
-		if (dp_get_netif_subifid(base, NULL, NULL, NULL, &subif, 0)) {
+		if (dp_get_netif_subifid(base, NULL, NULL, NULL, subif, 0)) {
 			PR_INFO("dp_get_netif_subifid fail:%s\n", base->name);
 			goto EXIT1;
 		}
-		port_info = get_port_info_via_dp_port(0, subif.port_id);
+		port_info = get_port_info_via_dp_port(0, subif->port_id);
 		if (!port_info) {
 			PR_INFO("get_port_info_via_dp_port fail: port_id:%d\n",
-				subif.port_id);
+				subif->port_id);
 			goto EXIT1;
 		}
 		if (dp_register_subif(port_info->owner, dev,
-				      dev->name, &subif, flag)) {
+				      dev->name, subif, flag)) {
 			PR_INFO("dp_deregister_subif fail: %s\n",
 				dev->name);
 			goto EXIT1;
 		}
 		PR_INFO("Deregister subif for %s ok with subif=%d\n",
 			param_list[1],
-			subif.subif);
+			subif->subif);
 	} else if (dp_strcmpi(param_list[0], "get") == 0) {
-		dp_subif_t subif = {0};
 		u32 flag = 0;
 		int i;
 
@@ -899,28 +902,29 @@ ssize_t proc_logical_dev_write(struct file *file, const char *buf,
 		dev = dev_get_by_name(&init_net, param_list[1]);
 		if (!dev) {
 			PR_INFO("No such device:%s\n", param_list[1]);
-			return count;
+			goto EXIT1;
 		}
 		/*flag = dp_atoi(param_list[2]); */
-		if (dp_get_netif_subifid(dev, NULL, NULL, NULL, &subif,
+		if (dp_get_netif_subifid(dev, NULL, NULL, NULL, subif,
 					 flag)) {
 			PR_INFO("dp_get_netif_subifid fail: %s\n",
 				param_list[1]);
-			return count;
+			goto EXIT1;
 		}
-		dev_put(dev);
 		PR_INFO("dev %s subif info:\n", param_list[1]);
 		PR_INFO("  inst=%d ep=%d bp=%d\n",
-			subif.inst, subif.port_id, subif.bport);
-		for (i = 0; i < subif.subif_num; i++)
+			subif->inst, subif->port_id, subif->bport);
+		for (i = 0; i < subif->subif_num; i++)
 			PR_INFO("  subif[%d]=%d\n",
-				i, subif.subif_list[i]);
+				i, subif->subif_list[i]);
 		PR_INFO("\n");
-		return count;
+		goto EXIT1;
 	}
 EXIT1:
 	if (dev)
 		dev_put(dev);
+	if (subif)
+		kfree(subif);
 	return count;
 
 HELP:
@@ -932,6 +936,8 @@ HELP:
 		DP_PROC_BASE, PROC_LOGICAL_DEV);
 	PR_INFO("Get dp_subif info: echo get dev_name > /proc/dp/%s\n",
 		PROC_LOGICAL_DEV);
+	if (subif)
+		kfree(subif);
 	return count;
 }
 
diff --git a/drivers/net/ethernet/lantiq/datapath/gswip30/datapath_misc.c b/drivers/net/ethernet/lantiq/datapath/gswip30/datapath_misc.c
index f03038867..2d47766a3 100644
--- a/drivers/net/ethernet/lantiq/datapath/gswip30/datapath_misc.c
+++ b/drivers/net/ethernet/lantiq/datapath/gswip30/datapath_misc.c
@@ -223,7 +223,6 @@ static void init_dma_pmac_template(int portid, u32 flags)
 		dp_info->pmac_template[TEMPL_NORMAL].port_map = 0xff;
 		dp_info->pmac_template[TEMPL_NORMAL].port_map2 = 0xff;
 		dp_info->pmac_template[TEMPL_NORMAL].class_en = 1;
-		//SET_PMAC_PORTMAP(&dp_info->pmac_template[TEMPL_NORMAL], portid);
 		dp_info->dma1_template[TEMPL_NORMAL].field.enc = 1;
 		dp_info->dma1_template[TEMPL_NORMAL].field.dec = 1;
 		dp_info->dma1_template[TEMPL_NORMAL].field.mpe2 = 0;
@@ -560,8 +559,6 @@ int register_dp_cap_gswip30(int flag)
 	memset(&cap, 0, sizeof(cap));
 	cap.info.type = GSWIP30_TYPE;
 	cap.info.ver = GSWIP30_VER;
-	cap.info.max_ports = PMAC_MAX_NUM;
-	cap.info.max_port_subifs = MAX_SUBIF_PER_PORT;
 	cap.info.dp_platform_set = dp_platform_set;
 	cap.info.port_platform_set = port_platform_set;
 	cap.info.subif_platform_set_unexplicit = subif_platform_set_unexplicit;
@@ -588,6 +585,22 @@ int register_dp_cap_gswip30(int flag)
 	cap.info.dp_get_port_vap_mib = dp_get_port_vap_mib_30;
 	cap.info.dp_clear_netif_mib = dp_clear_netif_mib_30;
 #endif
+	cap.info.cap.tx_hw_chksum = 1;
+	cap.info.cap.rx_hw_chksum = 1;
+	cap.info.cap.hw_tso = 1;
+	cap.info.cap.hw_gso = 1;
+	strncpy(cap.info.cap.qos_eng_name, "TMU",
+		sizeof(cap.info.cap.qos_eng_name));
+	strncpy(cap.info.cap.pkt_eng_name, "PAE/MPE",
+		sizeof(cap.info.cap.pkt_eng_name));
+	cap.info.cap.max_num_queues = 128;
+	cap.info.cap.max_num_scheds = 128;
+	cap.info.cap.max_num_deq_ports = 24;
+	cap.info.cap.max_num_qos_ports = 24;
+	cap.info.cap.max_num_dp_ports = PMAC_MAX_NUM;
+	cap.info.cap.max_num_subif_per_port = 16;
+	cap.info.cap.max_num_subif = 256;
+	cap.info.cap.max_num_bridge_port = 0;
 
 	if (register_dp_hw_cap(&cap, flag)) {
 		PR_ERR("Why register_dp_hw_cap fail\n");
diff --git a/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_misc.c b/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_misc.c
index 85ef2d1ce..b5992cdfa 100644
--- a/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_misc.c
+++ b/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_misc.c
@@ -923,8 +923,6 @@ int register_dp_cap_gswip31(int flag)
 	memset(&cap, 0, sizeof(cap));
 	cap.info.type = GSWIP31_TYPE;
 	cap.info.ver = GSWIP31_VER;
-	cap.info.max_ports = PMAC_MAX_NUM;
-	cap.info.max_port_subifs = MAX_SUBIF_PER_PORT;
 
 	cap.info.dp_platform_set = dp_platform_set;
 	cap.info.port_platform_set = port_platform_set;
@@ -964,6 +962,22 @@ int register_dp_cap_gswip31(int flag)
 	cap.info.dp_mac_set = dp_gswip_mac_entry_add;
 	cap.info.dp_mac_reset = dp_gswip_mac_entry_del;
 #endif
+	cap.info.cap.tx_hw_chksum = 0;
+	cap.info.cap.rx_hw_chksum = 0;
+	cap.info.cap.hw_tso = 0;
+	cap.info.cap.hw_gso = 0;
+	strncpy(cap.info.cap.qos_eng_name, "ppv4",
+		sizeof(cap.info.cap.qos_eng_name));
+	strncpy(cap.info.cap.pkt_eng_name, "mpe",
+		sizeof(cap.info.cap.pkt_eng_name));
+	cap.info.cap.max_num_queues = MAX_QUEUE;
+	cap.info.cap.max_num_scheds = MAX_SCHD;
+	cap.info.cap.max_num_deq_ports = MAX_CQM_DEQ;
+	cap.info.cap.max_num_qos_ports = MAX_CQM_DEQ;
+	cap.info.cap.max_num_dp_ports = PMAC_MAX_NUM;
+	cap.info.cap.max_num_subif_per_port = MAX_SUBIF_PER_PORT;
+	cap.info.cap.max_num_subif = 288;
+	cap.info.cap.max_num_bridge_port = 128;
 
 	if (register_dp_hw_cap(&cap, flag)) {
 		PR_ERR("Why register_dp_hw_cap fail\n");
diff --git a/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_ppv4.h b/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_ppv4.h
index 410191b04..5f9fc09d8 100644
--- a/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_ppv4.h
+++ b/drivers/net/ethernet/lantiq/datapath/gswip31/datapath_ppv4.h
@@ -71,6 +71,7 @@ struct pp_sch_list {
 
 #define MAX_CQM_DEQ 128 /*Need further check*/
 #define MAX_QUEUE 256 /*Need further check*/
+#define MAX_SCHD 128 /*Need further check*/
 
 #define MAX_PP_CHILD_PER_NODE  8 /*Maximum queue per scheduler*/
 
diff --git a/include/net/datapath_api.h b/include/net/datapath_api.h
index ac3740620..f7d58ae1a 100644
--- a/include/net/datapath_api.h
+++ b/include/net/datapath_api.h
@@ -232,6 +232,9 @@ typedef struct dp_subif {
 				*/
 		int32_t subif_list[DP_MAX_CTP_PER_DEV]; /*!< subif list */
 	};
+	int q_id[DP_MAX_CTP_PER_DEV]; /*!< queue per subif which created by DP.
+				       *   otherwise, it will be -1
+				       */
 	int bport;  /*!< output: valid only for API dp_get_netif_subifid in the
 		     *  GSWIP 3.1 or above
 		     */
@@ -239,6 +242,7 @@ typedef struct dp_subif {
 	int cqm_deq_port; /*!< output: the CBM/CQEM dequeue port id */
 	int qos_deq_port; /*!< output: the QOS engine dequeue port */
 	int lookup_mode; /*!< CQM lookup mode */
+	int subif_flag; /*!< the flag which used during dp_register_subif*/
 } dp_subif_t;
 
 typedef dp_subif_t PPA_SUBIF; /*!< @brief structure type dp_subif PPA_SUBIF*/
@@ -901,20 +905,27 @@ int dp_pmac_set(int inst, u32 port, dp_pmac_cfg_t *pmac_cfg);
 #define DP_MAX_NAME  20 /*!< max name length in character */
 /*! struct dp_cap: dp capability per instance */
 struct dp_cap {
-	int inst; /*!< input: dp instance. For SOC side, it is always zero */
-	int max_num_cqm_ports;  /*!< output: maximum number of supported cqm
-				 *     dequeue ports
-				 */
-	u32 tx_hw_chksum:1;    /*!< output: HW checksum offloading support flag
-				*   0 - not support
-				*   1: support
-				*/
+	int inst; /*!< Datapath instance id */
+
+	u32 tx_hw_chksum:1;  /*!< output: HW checksum offloading support flag
+			      *   for tx path
+			      *   0 - not support
+			      *   1: support
+			      */
+	u32 rx_hw_chksum:1;  /*!< output: HW checksum verification support flag
+			      *   for rx path
+			      *   0 - not support
+			      *   1: support
+			      */
+	u32 hw_tso: 1; /*!< output: HW TSO offload support for TX path */
+	u32 hw_gso: 1; /*!< output: HW GSO offload support for TX path */
+
 	char qos_eng_name[DP_MAX_NAME]; /*!< QOS engine name in string */
 	char pkt_eng_name[DP_MAX_NAME]; /*!< Packet Engine Name String */
-	int max_num_queues; /*!< max number of queue supported */
-	int max_num_scheds; /*!< max number of scheduler supported */
-	int max_num_deq_ports; /*!< max number of dequeue port */
-	int max_num_qos_ports; /*!< max number of dequeue port */
+	int max_num_queues; /*!< max number of QOS queue supported */
+	int max_num_scheds; /*!< max number of QOS scheduler supported */
+	int max_num_deq_ports; /*!< max number of CQM dequeue port */
+	int max_num_qos_ports; /*!< max number of QOS dequeue port */
 	int max_num_dp_ports; /*!< max number of dp port */
 	int max_num_subif_per_port; /*!< max number of subif per dp_port */
 	int max_num_subif; /*!< max number of subif supported. Maybe no meaning?
@@ -923,12 +934,18 @@ struct dp_cap {
 };
 
 /*!
- *@brief  The API is for dp_capability_get
- *@param[in,out] cap dp_cap pointer,
- *@param[in] flag flag
+ *@brief  The API is for dp_get_cap
+ *@param[in,out] cap dp_cap pointer, caller must provide the buffer
+ *@param[in] flag for future
  *@return 0 if OK / -1 if error
  */
-int dp_capability_get(struct dp_cap *cap, int flag);
+int dp_get_cap(struct dp_cap *cap, int flag);
+
+/*!
+ *@brief  The API is for dp_get_module_owner
+ *@param[in] ep dp_port ID
+ *@return module owner pointer if success, otherwise NULL
+ */
 struct module *dp_get_module_owner(int ep);
 #endif /*DATAPATH_API_H */
 
diff --git a/include/net/datapath_inst.h b/include/net/datapath_inst.h
index dc600a207..91b69d8a3 100644
--- a/include/net/datapath_inst.h
+++ b/include/net/datapath_inst.h
@@ -51,6 +51,7 @@ struct inst_info {
 	enum DP_HW_CAP_VER ver;
 	int max_ports;
 	int max_port_subifs;
+	struct dp_cap cap;
 	int (*dp_platform_set)(int inst, u32 flag);
 	int (*port_platform_set)(int inst, u8 ep, uint32_t flags);
 	int (*subif_platform_set_unexplicit)(int inst, int port_id,
-- 
GitLab