[qca-ssdk] support port flowctrl forcemode

support port flowctrl forcemode.

Change-Id: Ic851c9770d4e34d82148e45006025d0a92f4fed1
Signed-off-by: esong <song@codeaurora.org>
diff --git a/include/adpt/adpt.h b/include/adpt/adpt.h
index a53d4ad..ce3f186 100644
--- a/include/adpt/adpt.h
+++ b/include/adpt/adpt.h
@@ -301,6 +301,10 @@
 		a_uint32_t port_id, a_bool_t enable);
 typedef sw_error_t (*adpt_port_interface_3az_status_get_func)(a_uint32_t dev_id,
 		a_uint32_t port_id, a_bool_t * enable);
+typedef sw_error_t (*adpt_port_flowctrl_forcemode_set_func) (a_uint32_t dev_id,
+		fal_port_t port_id, a_bool_t enable);
+typedef sw_error_t (*adpt_port_flowctrl_forcemode_get_func) (a_uint32_t dev_id,
+		fal_port_t port_id, a_bool_t * enable);
 
 // mirror
 typedef sw_error_t (*adpt_mirr_port_in_set_func)(a_uint32_t dev_id, fal_port_t port_id,
@@ -1021,6 +1025,8 @@
 	adpt_port_interface_mode_apply_func adpt_port_interface_mode_apply;
 	adpt_port_interface_3az_status_set_func adpt_port_interface_3az_status_set;
 	adpt_port_interface_3az_status_get_func adpt_port_interface_3az_status_get;
+	adpt_port_flowctrl_forcemode_set_func adpt_port_flowctrl_forcemode_set;
+	adpt_port_flowctrl_forcemode_get_func adpt_port_flowctrl_forcemode_get;
 
 // mirror
 	a_uint32_t adpt_mirror_func_bitmap;
diff --git a/include/fal/fal_port_ctrl.h b/include/fal/fal_port_ctrl.h
index b483e6d..b5d8c66 100755
--- a/include/fal/fal_port_ctrl.h
+++ b/include/fal/fal_port_ctrl.h
@@ -334,7 +334,8 @@
 	FUNC_ADPT_PORT_INTERFACE_MODE_APPLY,
 	FUNC_ADPT_PORT_INTERFACE_3AZ_STATUS_SET,
 	FUNC_ADPT_PORT_INTERFACE_3AZ_STATUS_GET,
-
+	FUNC_ADPT_PORT_FLOWCTRL_FORCEMODE_SET,
+	FUNC_ADPT_PORT_FLOWCTRL_FORCEMODE_GET,
 };
 
 typedef struct {
diff --git a/include/init/ssdk_plat.h b/include/init/ssdk_plat.h
index bfa35d0..cf1deb4 100755
--- a/include/init/ssdk_plat.h
+++ b/include/init/ssdk_plat.h
@@ -267,6 +267,8 @@
 	a_uint32_t port_qm_buf[SW_MAX_NR_PORT];
 	a_uint32_t port_old_tx_flowctrl[SW_MAX_NR_PORT];
 	a_uint32_t port_old_rx_flowctrl[SW_MAX_NR_PORT];
+	a_bool_t port_tx_flowctrl_forcemode[SW_MAX_NR_PORT];
+	a_bool_t port_rx_flowctrl_forcemode[SW_MAX_NR_PORT];
 	struct delayed_work qm_dwork_polling;
 	struct work_struct	 intr_workqueue;
 	/*qm_err_check end*/
diff --git a/src/adpt/hppe/adpt_hppe_portctrl.c b/src/adpt/hppe/adpt_hppe_portctrl.c
index 0f6fb84..19111b4 100755
--- a/src/adpt/hppe/adpt_hppe_portctrl.c
+++ b/src/adpt/hppe/adpt_hppe_portctrl.c
@@ -1588,18 +1588,31 @@
 adpt_hppe_port_txfc_status_set(a_uint32_t dev_id, fal_port_t port_id,
 				     a_bool_t enable)
 {
+	sw_error_t rv = SW_OK;
 	a_uint32_t port_mac_type;
+	struct qca_phy_priv *priv = ssdk_phy_priv_data_get(dev_id);
 
 	ADPT_DEV_ID_CHECK(dev_id);
 
+	if (!priv)
+		return SW_FAIL;
+
+	if ((port_id < PHYSICAL_PORT1) || (port_id > PHYSICAL_PORT6))
+		return SW_BAD_VALUE;
+
 	port_mac_type =qca_hppe_port_mac_type_get(dev_id, port_id);
 	if (port_mac_type == PORT_XGMAC_TYPE)
-		_adpt_xgmac_port_txfc_status_set( dev_id, port_id, enable);
+		rv = _adpt_xgmac_port_txfc_status_set( dev_id, port_id, enable);
 	else if (port_mac_type == PORT_GMAC_TYPE)
-		_adpt_gmac_port_txfc_status_set( dev_id, port_id, enable);
+		rv = _adpt_gmac_port_txfc_status_set( dev_id, port_id, enable);
 	else
 		return SW_BAD_VALUE;
 
+	if (rv != SW_OK)
+		return rv;
+
+	priv->port_old_tx_flowctrl[port_id - 1] = enable;
+
 	return SW_OK;
 }
 sw_error_t
@@ -2702,18 +2715,31 @@
 adpt_hppe_port_rxfc_status_set(a_uint32_t dev_id, fal_port_t port_id,
 				     a_bool_t enable)
 {
+	sw_error_t rv = SW_OK;
 	a_uint32_t port_mac_type;
+	struct qca_phy_priv *priv = ssdk_phy_priv_data_get(dev_id);
 
 	ADPT_DEV_ID_CHECK(dev_id);
 
+	if (!priv)
+		return SW_FAIL;
+
+	if ((port_id < PHYSICAL_PORT1) || (port_id > PHYSICAL_PORT6))
+		return SW_BAD_VALUE;
+
 	port_mac_type =qca_hppe_port_mac_type_get(dev_id, port_id);
 	if(port_mac_type == PORT_XGMAC_TYPE)
-		_adpt_xgmac_port_rxfc_status_set( dev_id, port_id, enable);
+		rv = _adpt_xgmac_port_rxfc_status_set( dev_id, port_id, enable);
 	else if (port_mac_type == PORT_GMAC_TYPE)
-		_adpt_gmac_port_rxfc_status_set( dev_id, port_id, enable);
+		rv = _adpt_gmac_port_rxfc_status_set( dev_id, port_id, enable);
 	else
 		return SW_BAD_VALUE;
 
+	if (rv != SW_OK)
+		return rv;
+
+	priv->port_old_rx_flowctrl[port_id - 1] = enable;
+
 	return SW_OK;
 }
 sw_error_t
@@ -2721,12 +2747,23 @@
 				  a_bool_t enable)
 {
 	sw_error_t rv = SW_OK;
+	struct qca_phy_priv *priv = ssdk_phy_priv_data_get(dev_id);
+
+	if (!priv)
+		return SW_FAIL;
+
+	if ((port_id < PHYSICAL_PORT1) || (port_id > PHYSICAL_PORT6))
+		return SW_BAD_VALUE;
 
 	rv = adpt_hppe_port_txfc_status_set(dev_id, port_id, enable);
 	rv |= adpt_hppe_port_rxfc_status_set(dev_id, port_id, enable);
+
 	if(rv != SW_OK)
 		return rv;
 
+	priv->port_old_tx_flowctrl[port_id - 1] = enable;
+	priv->port_old_rx_flowctrl[port_id - 1] = enable;
+
 	return SW_OK;
 }
 sw_error_t
@@ -3037,6 +3074,49 @@
 }
 
 static sw_error_t
+adpt_hppe_port_flowctrl_forcemode_set(a_uint32_t dev_id,
+		fal_port_t port_id, a_bool_t enable)
+{
+	sw_error_t rv = SW_OK;
+	struct qca_phy_priv *priv = ssdk_phy_priv_data_get(dev_id);
+
+	ADPT_DEV_ID_CHECK(dev_id);
+
+	if (!priv)
+		return SW_FAIL;
+
+	if ((port_id < PHYSICAL_PORT1) || (port_id > PHYSICAL_PORT6))
+		return SW_BAD_VALUE;
+
+	priv->port_tx_flowctrl_forcemode[port_id - 1] = enable;
+	priv->port_rx_flowctrl_forcemode[port_id - 1] = enable;
+
+	return rv;
+}
+static sw_error_t
+adpt_hppe_port_flowctrl_forcemode_get(a_uint32_t dev_id,
+		fal_port_t port_id, a_bool_t *enable)
+{
+	sw_error_t rv = SW_OK;
+	struct qca_phy_priv *priv = ssdk_phy_priv_data_get(dev_id);
+
+
+	ADPT_DEV_ID_CHECK(dev_id);
+	ADPT_NULL_POINT_CHECK(enable);
+
+	if ((port_id < PHYSICAL_PORT1) || (port_id > PHYSICAL_PORT6))
+		return SW_BAD_VALUE;
+
+	if (!priv)
+		return SW_FAIL;
+
+	*enable = (priv->port_tx_flowctrl_forcemode[port_id - 1] &
+		priv->port_rx_flowctrl_forcemode[port_id - 1]);
+
+	return rv;
+}
+
+static sw_error_t
 _adpt_hppe_phy_status_convert(a_uint32_t speed, a_uint32_t duplex,
 				struct port_phy_status *phy_status)
 {
@@ -3750,21 +3830,27 @@
 					SSDK_DEBUG("Port %d is link up and duplex change to %d\n", port_id,
 								priv->port_old_duplex[port_id - 1]);
 				}
-				if (phy_status.tx_flowctrl != priv->port_old_tx_flowctrl[port_id - 1])
+				if (priv->port_tx_flowctrl_forcemode[port_id - 1] != A_TRUE)
 				{
-					adpt_hppe_port_txfc_status_set(priv->device_id, port_id, (a_bool_t)phy_status.tx_flowctrl);
-					priv->port_old_tx_flowctrl[port_id - 1] = phy_status.tx_flowctrl;
+					if (phy_status.tx_flowctrl != priv->port_old_tx_flowctrl[port_id - 1])
+					{
+						adpt_hppe_port_txfc_status_set(priv->device_id, port_id, (a_bool_t)phy_status.tx_flowctrl);
+						priv->port_old_tx_flowctrl[port_id - 1] = phy_status.tx_flowctrl;
 
-					SSDK_DEBUG("Port %d is link up and tx flowctrl change to %d\n", port_id,
-								priv->port_old_tx_flowctrl[port_id - 1]);
+						SSDK_DEBUG("Port %d is link up and tx flowctrl change to %d\n", port_id,
+									priv->port_old_tx_flowctrl[port_id - 1]);
+					}
 				}
-				if (phy_status.rx_flowctrl != priv->port_old_rx_flowctrl[port_id - 1])
+				if (priv->port_rx_flowctrl_forcemode[port_id - 1] != A_TRUE)
 				{
-					adpt_hppe_port_rxfc_status_set(priv->device_id, port_id, (a_bool_t)phy_status.rx_flowctrl);
-					priv->port_old_rx_flowctrl[port_id - 1] = phy_status.rx_flowctrl;
+					if (phy_status.rx_flowctrl != priv->port_old_rx_flowctrl[port_id - 1])
+					{
+						adpt_hppe_port_rxfc_status_set(priv->device_id, port_id, (a_bool_t)phy_status.rx_flowctrl);
+						priv->port_old_rx_flowctrl[port_id - 1] = phy_status.rx_flowctrl;
 
-					SSDK_DEBUG("Port %d is link up and rx flowctrl change to %d\n", port_id,
-								priv->port_old_rx_flowctrl[port_id - 1]);
+						SSDK_DEBUG("Port %d is link up and rx flowctrl change to %d\n", port_id,
+									priv->port_old_rx_flowctrl[port_id - 1]);
+					}
 				}
 				adpt_hppe_gcc_mac_clock_status_set(priv->device_id, port_id, A_TRUE);
 				adpt_hppe_gcc_uniphy_clock_status_set(priv->device_id, port_id, A_TRUE);
@@ -3859,7 +3945,9 @@
 
 	p_adpt_api->adpt_port_ctrl_func_bitmap[2] = ((1 << (FUNC_ADPT_PORT_INTERFACE_MODE_APPLY% 32))|
 						(1 << (FUNC_ADPT_PORT_INTERFACE_3AZ_STATUS_SET% 32))|
-						(1 << (FUNC_ADPT_PORT_INTERFACE_3AZ_STATUS_GET% 32)));
+						(1 << (FUNC_ADPT_PORT_INTERFACE_3AZ_STATUS_GET% 32))|
+						(1 << (FUNC_ADPT_PORT_FLOWCTRL_FORCEMODE_SET% 32))|
+						(1 << (FUNC_ADPT_PORT_FLOWCTRL_FORCEMODE_GET% 32)));
 
 	return;
 
@@ -3937,6 +4025,8 @@
 	p_adpt_api->adpt_port_source_filter_set = NULL;
 	p_adpt_api->adpt_port_interface_3az_status_set = NULL;
 	p_adpt_api->adpt_port_interface_3az_status_get = NULL;
+	p_adpt_api->adpt_port_flowctrl_forcemode_set = NULL;
+	p_adpt_api->adpt_port_flowctrl_forcemode_get = NULL;
 
 	return;
 
@@ -4223,6 +4313,14 @@
 	{
 		p_adpt_api->adpt_port_interface_3az_status_get = adpt_hppe_port_interface_3az_get;
 	}
+	if(p_adpt_api->adpt_port_ctrl_func_bitmap[2] & (1 <<  (FUNC_ADPT_PORT_FLOWCTRL_FORCEMODE_SET% 32)))
+	{
+		p_adpt_api->adpt_port_flowctrl_forcemode_set = adpt_hppe_port_flowctrl_forcemode_set;
+	}
+	if(p_adpt_api->adpt_port_ctrl_func_bitmap[2] & (1 <<  (FUNC_ADPT_PORT_FLOWCTRL_FORCEMODE_GET% 32)))
+	{
+		p_adpt_api->adpt_port_flowctrl_forcemode_get = adpt_hppe_port_flowctrl_forcemode_get;
+	}
 
 	p_adpt_api->adpt_port_mux_mac_type_set = adpt_hppe_port_mux_mac_type_set;
 	p_adpt_api->adpt_port_mac_speed_set = adpt_hppe_port_mac_speed_set;
diff --git a/src/fal/fal_port_ctrl.c b/src/fal/fal_port_ctrl.c
index 5f7bbbd..384e5c3 100755
--- a/src/fal/fal_port_ctrl.c
+++ b/src/fal/fal_port_ctrl.c
@@ -106,6 +106,15 @@
 {
   sw_error_t rv;
   hsl_api_t *p_api;
+  adpt_api_t *p_adpt_api;
+
+  if((p_adpt_api = adpt_api_ptr_get(dev_id)) != NULL) {
+    if (NULL == p_adpt_api->adpt_port_flowctrl_forcemode_set)
+      return SW_NOT_SUPPORTED;
+
+  rv = p_adpt_api->adpt_port_flowctrl_forcemode_set(dev_id, port_id, enable);
+  return rv;
+  }
 
   SW_RTN_ON_NULL (p_api = hsl_api_ptr_get (dev_id));
 
@@ -356,6 +365,15 @@
 {
   sw_error_t rv;
   hsl_api_t *p_api;
+  adpt_api_t *p_adpt_api;
+
+  if((p_adpt_api = adpt_api_ptr_get(dev_id)) != NULL) {
+    if (NULL == p_adpt_api->adpt_port_flowctrl_forcemode_get)
+      return SW_NOT_SUPPORTED;
+
+  rv = p_adpt_api->adpt_port_flowctrl_forcemode_get(dev_id, port_id, enable);
+  return rv;
+  }
 
   SW_RTN_ON_NULL (p_api = hsl_api_ptr_get (dev_id));
 
@@ -3489,4 +3507,6 @@
 EXPORT_SYMBOL(fal_port_max_frame_size_set);
 EXPORT_SYMBOL(fal_port_max_frame_size_get);
 EXPORT_SYMBOL(fal_port_interface_3az_status_set);
-EXPORT_SYMBOL(fal_port_interface_3az_status_get);
\ No newline at end of file
+EXPORT_SYMBOL(fal_port_interface_3az_status_get);
+EXPORT_SYMBOL(fal_port_flowctrl_forcemode_set);
+EXPORT_SYMBOL(fal_port_flowctrl_forcemode_get);
diff --git a/src/init/ssdk_init.c b/src/init/ssdk_init.c
index fe8998c..6ad48c5 100755
--- a/src/init/ssdk_init.c
+++ b/src/init/ssdk_init.c
@@ -1382,6 +1382,8 @@
 		qca_phy_priv_global[dev_id]->port_old_duplex[port_id - 1] = FAL_DUPLEX_BUTT;
 		qca_phy_priv_global[dev_id]->port_old_tx_flowctrl[port_id - 1] = 1;
 		qca_phy_priv_global[dev_id]->port_old_rx_flowctrl[port_id - 1] = 1;
+		qca_phy_priv_global[dev_id]->port_tx_flowctrl_forcemode[port_id - 1] = A_FALSE;
+		qca_phy_priv_global[dev_id]->port_rx_flowctrl_forcemode[port_id - 1] = A_FALSE;
 	}
 }
 void