[dpdk-dev] [PATCH v2] i40e: add link flow control support for FVL

2015-10-29 Thread Zhe Tao
Feature Add: Rx/Tx flow control support for the i40e

All the Rx/Tx LFC enable/disable operation is done by the F/W, 
so PMD driver need to use the Set PHY Config AD command to trigger the PHY 
to do the auto-negotiation, after the Tx/Rx pause ability is negotiated, 
the F/W will help us to set the related LFC enable/disable registers.
PMD driver also need to configure the related registers to control 
how often to send the pause frame and what the value in the pause frame.

Signed-off-by: Zhe Tao 
---

PATCH V1: Add the LFC support for i40e

PATCH v2: move the LFC parameters init to the i40e_pf_parameter_init

 drivers/net/i40e/i40e_ethdev.c | 170 -
 drivers/net/i40e/i40e_ethdev.h |  12 +++
 2 files changed, 179 insertions(+), 3 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..e68e0b7 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -81,6 +81,27 @@

 #define I40E_PRE_TX_Q_CFG_WAIT_US   10 /* 10 us */

+/* Flow control default timer */
+#define I40E_DEFAULT_PAUSE_TIME 0xU
+
+/* Flow control default high water */
+#define I40E_DEFAULT_HIGH_WATER (0x1C40/1024)
+
+/* Flow control default low water */
+#define I40E_DEFAULT_LOW_WATER  (0x1A40/1024)
+
+/* Flow control enable fwd bit */
+#define I40E_PRTMAC_FWD_CTRL   0x0001
+
+/* Receive Packet Buffer size */
+#define I40E_RXPBSIZE (968 * 1024)
+
+/* Kilobytes shift */
+#define I40E_KILOSHIFT 10
+
+/* Receive Average Packet Size in Byte*/
+#define I40E_PACKET_AVERAGE_SIZE 128
+
 /* Mask of PF interrupt causes */
 #define I40E_PFINT_ICR0_ENA_MASK ( \
I40E_PFINT_ICR0_ENA_ECC_ERR_MASK | \
@@ -145,6 +166,8 @@ static void i40e_vlan_strip_queue_set(struct rte_eth_dev 
*dev,
 static int i40e_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid, int on);
 static int i40e_dev_led_on(struct rte_eth_dev *dev);
 static int i40e_dev_led_off(struct rte_eth_dev *dev);
+static int i40e_flow_ctrl_get(struct rte_eth_dev *dev,
+ struct rte_eth_fc_conf *fc_conf);
 static int i40e_flow_ctrl_set(struct rte_eth_dev *dev,
  struct rte_eth_fc_conf *fc_conf);
 static int i40e_priority_flow_ctrl_set(struct rte_eth_dev *dev,
@@ -272,6 +295,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.tx_queue_release = i40e_dev_tx_queue_release,
.dev_led_on   = i40e_dev_led_on,
.dev_led_off  = i40e_dev_led_off,
+   .flow_ctrl_get= i40e_flow_ctrl_get,
.flow_ctrl_set= i40e_flow_ctrl_set,
.priority_flow_ctrl_set   = i40e_priority_flow_ctrl_set,
.mac_addr_add = i40e_macaddr_add,
@@ -1782,12 +1806,148 @@ i40e_dev_led_off(struct rte_eth_dev *dev)
 }

 static int
-i40e_flow_ctrl_set(__rte_unused struct rte_eth_dev *dev,
-  __rte_unused struct rte_eth_fc_conf *fc_conf)
+i40e_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
 {
+   struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+   struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+
+   fc_conf->pause_time = pf->fc_conf.pause_time;
+   fc_conf->high_water =  pf->fc_conf.high_water[I40E_MAX_TRAFFIC_CLASS];
+   fc_conf->low_water = pf->fc_conf.low_water[I40E_MAX_TRAFFIC_CLASS];
+
+/* Return current mode according to actual setting*/
+   switch (hw->fc.current_mode) {
+   case I40E_FC_FULL:
+   fc_conf->mode = RTE_FC_FULL;
+   break;
+   case I40E_FC_TX_PAUSE:
+   fc_conf->mode = RTE_FC_TX_PAUSE;
+   break;
+   case I40E_FC_RX_PAUSE:
+   fc_conf->mode = RTE_FC_RX_PAUSE;
+   break;
+   case I40E_FC_NONE:
+   default:
+   fc_conf->mode = RTE_FC_NONE;
+   };
+
+   return 0;
+}
+
+static int
+i40e_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_conf)
+{
+   uint32_t mflcn_reg, fctrl_reg, reg;
+   uint32_t max_high_water;
+   uint8_t i, aq_failure;
+   int err;
+   struct i40e_hw *hw;
+   struct i40e_pf *pf;
+   enum i40e_fc_mode rte_fcmode_2_i40e_fcmode[] = {
+   [RTE_FC_NONE] = I40E_FC_NONE,
+   [RTE_FC_RX_PAUSE] = I40E_FC_RX_PAUSE,
+   [RTE_FC_TX_PAUSE] = I40E_FC_TX_PAUSE,
+   [RTE_FC_FULL] = I40E_FC_FULL
+   };
+
+   /* high_water field in the rte_eth_fc_conf using the kilobytes unit */
+
+   max_high_water = I40E_RXPBSIZE >> I40E_KILOSHIFT;
+   if ((fc_conf->high_water > max_high_water) ||
+   (fc_conf->high_water < fc_conf->low_water)) {
+   PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB, "
+   "High_water must <= %d.", max_high_water);
+   return -EINVAL;
+   }
+
+   hw = 

[dpdk-dev] [PATCH v2] i40e: add link flow control support for FVL

2015-10-29 Thread Wu, Jingjing

> -Original Message-
> From: Tao, Zhe
> Sent: Thursday, October 29, 2015 8:57 PM
> To: dev at dpdk.org
> Cc: Tao, Zhe; Wu, Jingjing
> Subject: [dpdk-dev][PATCH v2] i40e: add link flow control support for FVL
> 
> Feature Add: Rx/Tx flow control support for the i40e
> 
> All the Rx/Tx LFC enable/disable operation is done by the F/W,
> so PMD driver need to use the Set PHY Config AD command to trigger the PHY
> to do the auto-negotiation, after the Tx/Rx pause ability is negotiated,
> the F/W will help us to set the related LFC enable/disable registers.
> PMD driver also need to configure the related registers to control
> how often to send the pause frame and what the value in the pause frame.
> 
> Signed-off-by: Zhe Tao 

I think release note is missed.
> ---
> 
> PATCH V1: Add the LFC support for i40e
> 
> PATCH v2: move the LFC parameters init to the i40e_pf_parameter_init
> 
>  drivers/net/i40e/i40e_ethdev.c | 170 
> -
>  drivers/net/i40e/i40e_ethdev.h |  12 +++
>  2 files changed, 179 insertions(+), 3 deletions(-)
>