* [dpdk-dev] [PATCH] i40e: support of link flow control
@ 2014-09-28 7:08 zzang
2014-11-13 9:46 ` Thomas Monjalon
0 siblings, 1 reply; 2+ messages in thread
From: zzang @ 2014-09-28 7:08 UTC (permalink / raw)
To: dev
From: Zhida Zang <zhida.zang@intel.com>
Add support of link flow control.
Signed-off-by: Zhida Zang <zhida.zang@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
---
lib/librte_pmd_i40e/i40e_ethdev.c | 216 +++++++++++++++++++++++++++++++++++++-
lib/librte_pmd_i40e/i40e_ethdev.h | 1 +
2 files changed, 214 insertions(+), 3 deletions(-)
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e_ethdev.c
index a00d6ca..02abcac 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.c
+++ b/lib/librte_pmd_i40e/i40e_ethdev.c
@@ -58,6 +58,14 @@
#include "i40e_rxtx.h"
#include "i40e_pf.h"
+/* Flow control default timer */
+#define I40E_DEFAULT_PAUSE_TIME 0xFFFFU
+
+/* Flow control bit */
+#define I40E_PRTMAC_ENABLE_RX 0x00000100
+#define I40E_PRTMAC_ENABLE_TX 0x00000100
+#define I40E_PRTMAC_FWD_CTRL 0x00000001
+
/* Maximun number of MAC addresses */
#define I40E_NUM_MACADDR_MAX 64
#define I40E_CLEAR_PXE_WAIT_MS 200
@@ -150,6 +158,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,
@@ -248,6 +258,7 @@ static 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,
@@ -366,6 +377,7 @@ eth_i40e_dev_init(__rte_unused struct eth_driver *eth_drv,
pf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
pf->adapter->eth_dev = dev;
pf->dev_data = dev->data;
+ pf->pause_time = I40E_DEFAULT_PAUSE_TIME;
hw->back = I40E_PF_TO_ADAPTER(pf);
hw->hw_addr = (uint8_t *)(pci_dev->mem_resource[0].addr);
@@ -1488,12 +1500,210 @@ 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)
+{
+ uint32_t mflcn_reg, fccfg_reg, rx_reg, tx_reg;
+ int rx_pause, tx_pause;
+ 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->pause_time;
+
+ if (i40e_is_40G_device(hw->device_id)) {
+ rx_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
+ tx_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
+
+ if (rx_reg & I40E_PRTMAC_ENABLE_RX)
+ rx_pause = 1;
+ else
+ rx_pause = 0;
+
+ if (tx_reg & I40E_PRTMAC_ENABLE_TX)
+ tx_pause = 1;
+ else
+ tx_pause = 0;
+ } else {
+ mflcn_reg = I40E_READ_REG(hw, I40E_PRTDCB_MFLCN);
+ if (mflcn_reg & (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT))
+ rx_pause = 1;
+ else
+ rx_pause = 0;
+
+ fccfg_reg = I40E_READ_REG(hw, I40E_PRTDCB_FCCFG);
+ if (fccfg_reg & (0x1 << I40E_PRTDCB_FCCFG_TFCE_SHIFT))
+ tx_pause = 1;
+ else
+ tx_pause = 0;
+ }
+
+ if (rx_pause && tx_pause)
+ fc_conf->mode = RTE_FC_FULL;
+ else if (rx_pause)
+ fc_conf->mode = RTE_FC_RX_PAUSE;
+ else if (tx_pause)
+ fc_conf->mode = RTE_FC_TX_PAUSE;
+ else
+ fc_conf->mode = RTE_FC_NONE;
+
+ return 0;
+}
+
+static int i40e_40g_fc_enable(struct i40e_hw *hw, uint16_t pause_time)
+{
+ uint32_t gpp_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP);
+ uint32_t ppp_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP);
+ uint32_t gcp_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP);
+ uint32_t rx_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE);
+ uint32_t tx_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE);
+
+ gpp_reg |=
+ I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP_HSEC_CTL_RX_ENABLE_GPP_MASK;
+ ppp_reg &=
+ ~I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP_HSEC_CTL_RX_ENABLE_PPP_MASK;
+ gcp_reg |=
+ I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP_HSEC_CTL_RX_ENABLE_GCP_MASK;
+
+ /* clear previous settings */
+ rx_reg &= ~I40E_PRTMAC_ENABLE_RX;
+ tx_reg &= ~I40E_PRTMAC_ENABLE_TX;
+
+ switch (hw->fc.current_mode) {
+ case I40E_FC_NONE:
+ break;
+ case I40E_FC_RX_PAUSE:
+ rx_reg |= I40E_PRTMAC_ENABLE_RX;
+ break;
+ case I40E_FC_TX_PAUSE:
+ tx_reg |= I40E_PRTMAC_ENABLE_TX;
+ break;
+ case I40E_FC_FULL:
+ rx_reg |= I40E_PRTMAC_ENABLE_RX;
+ tx_reg |= I40E_PRTMAC_ENABLE_TX;
+ break;
+ default:
+ PMD_INIT_LOG(ERR, "Flow control param set incorrectly\n");
+ return -EIO;
+ }
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GPP, gpp_reg);
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_PPP, ppp_reg);
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_RX_ENABLE_GCP, gcp_reg);
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE, rx_reg);
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE, tx_reg);
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(8),
+ pause_time / 2);
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(8), pause_time);
+
+ return 0;
+}
+
+static int i40e_10g_fc_enable(struct i40e_hw *hw, uint16_t pause_time)
+{
+ uint32_t mflcn_reg, fccfg_reg, reg;
+ int i;
+
+ /* Disable any previous flow control settings */
+ mflcn_reg = I40E_READ_REG(hw, I40E_PRTDCB_MFLCN);
+ mflcn_reg &= ~(I40E_PRTDCB_MFLCN_RPFCM_MASK |
+ I40E_PRTDCB_MFLCN_RFCE_MASK);
+
+ fccfg_reg = I40E_READ_REG(hw, I40E_PRTDCB_FCCFG);
+ fccfg_reg &= ~I40E_PRTDCB_FCCFG_TFCE_MASK;
+
+ switch (hw->fc.current_mode) {
+ case I40E_FC_NONE:
+ break;
+ case I40E_FC_RX_PAUSE:
+ mflcn_reg |= (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT);
+ break;
+ case I40E_FC_TX_PAUSE:
+ fccfg_reg |= (0x1 << I40E_PRTDCB_FCCFG_TFCE_SHIFT);
+ break;
+ case I40E_FC_FULL:
+ mflcn_reg |= (0x1 << I40E_PRTDCB_MFLCN_RFCE_SHIFT);
+ fccfg_reg |= (0x1 << I40E_PRTDCB_FCCFG_TFCE_SHIFT);
+ break;
+ default:
+ PMD_INIT_LOG(ERR, "Flow control param set incorrectly\n");
+ return -EIO;
+ }
+ mflcn_reg |= (0x1 << I40E_PRTDCB_MFLCN_DPF_SHIFT);
+ I40E_WRITE_REG(hw, I40E_PRTDCB_MFLCN, mflcn_reg);
+ I40E_WRITE_REG(hw, I40E_PRTDCB_FCCFG, fccfg_reg);
+
+ /* Configure pause time (2 TCs per register) */
+ reg = (uint32_t)pause_time * (uint32_t)0x00010001;
+ for (i = 0; i < 4; i++)
+ I40E_WRITE_REG(hw, I40E_PRTDCB_FCTTVN(i), reg);
+
+ /* Configure flow control refresh threshold value */
+ I40E_WRITE_REG(hw, I40E_PRTDCB_FCRTV, pause_time / 2);
+
+ 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;
+ u8 aq_failure;
+ int err;
+ enum i40e_fc_mode rte_fcmode_2_i40e_fcmode[] = {
+ I40E_FC_NONE,
+ I40E_FC_RX_PAUSE,
+ I40E_FC_TX_PAUSE,
+ I40E_FC_FULL
+ };
+ 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);
+ hw->fc.requested_mode = rte_fcmode_2_i40e_fcmode[fc_conf->mode];
+ pf->pause_time = fc_conf->pause_time;
+
PMD_INIT_FUNC_TRACE();
- return -ENOSYS;
+ err = i40e_set_fc(hw, &aq_failure, 1);
+ if (err < 0) {
+ PMD_INIT_LOG(ERR, "i40e_set_fc = %d\n", err);
+ return err;
+ }
+
+ if (i40e_is_40G_device(hw->device_id)) {
+ err = i40e_40g_fc_enable(hw, pf->pause_time);
+ if (err < 0)
+ return err;
+
+ fctrl_reg = I40E_READ_REG(hw,
+ I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL);
+ if (fc_conf->mac_ctrl_frame_fwd != 0)
+ fctrl_reg |= I40E_PRTMAC_FWD_CTRL;
+ else
+ fctrl_reg &= ~I40E_PRTMAC_FWD_CTRL;
+
+ I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL,
+ fctrl_reg);
+ } else {
+ err = i40e_10g_fc_enable(hw, pf->pause_time);
+ if (err < 0)
+ return err;
+
+ mflcn_reg = I40E_READ_REG(hw, I40E_PRTDCB_MFLCN);
+ /* set or clear MFLCN.PMCF bit depending on configuration */
+ if (fc_conf->mac_ctrl_frame_fwd != 0)
+ mflcn_reg |= I40E_PRTDCB_MFLCN_PMCF_MASK;
+ else
+ mflcn_reg &= ~I40E_PRTDCB_MFLCN_PMCF_MASK;
+
+ I40E_WRITE_REG(hw, I40E_PRTDCB_MFLCN, mflcn_reg);
+ }
+
+ I40E_WRITE_FLUSH(hw);
+
+ return 0;
}
static int
diff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e_ethdev.h
index 64deef2..676f70b 100644
--- a/lib/librte_pmd_i40e/i40e_ethdev.h
+++ b/lib/librte_pmd_i40e/i40e_ethdev.h
@@ -216,6 +216,7 @@ struct i40e_pf {
uint16_t vmdq_nb_qps; /* The number of queue pairs of VMDq */
uint16_t vf_nb_qps; /* The number of queue pairs of VF */
uint16_t fdir_nb_qps; /* The number of queue pairs of Flow Director */
+ uint16_t pause_time; /* Flow control pause timer */
};
enum pending_msg {
--
1.8.1.4
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [dpdk-dev] [PATCH] i40e: support of link flow control
2014-09-28 7:08 [dpdk-dev] [PATCH] i40e: support of link flow control zzang
@ 2014-11-13 9:46 ` Thomas Monjalon
0 siblings, 0 replies; 2+ messages in thread
From: Thomas Monjalon @ 2014-11-13 9:46 UTC (permalink / raw)
To: zzang; +Cc: dev
Hi Zhida,
> Add support of link flow control.
>
> Signed-off-by: Zhida Zang <zhida.zang@intel.com>
> Acked-by: Helin Zhang <helin.zhang@intel.com>
I think you are reworking this patch, right?
I won't review it myself because I don't i40e enough.
I just have some minor comments:
> +static int i40e_10g_fc_enable(struct i40e_hw *hw, uint16_t pause_time)
"static int" should be on a separate line.
> + PMD_INIT_LOG(ERR, "i40e_set_fc = %d\n", err);
Carriage return is already included in PMD_INIT_LOG now.
Thanks for keep us informed of the status of this patch.
--
Thomas
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-11-13 9:37 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-28 7:08 [dpdk-dev] [PATCH] i40e: support of link flow control zzang
2014-11-13 9:46 ` Thomas Monjalon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).