From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id E843D3F9 for ; Tue, 25 Nov 2014 12:20:56 +0100 (CET) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 25 Nov 2014 03:31:47 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.07,455,1413270000"; d="scan'208";a="613675188" Received: from pgsmsx108.gar.corp.intel.com ([10.221.44.103]) by orsmga001.jf.intel.com with ESMTP; 25 Nov 2014 03:31:44 -0800 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by PGSMSX108.gar.corp.intel.com (10.221.44.103) with Microsoft SMTP Server (TLS) id 14.3.195.1; Tue, 25 Nov 2014 19:31:43 +0800 Received: from shsmsx101.ccr.corp.intel.com ([169.254.1.110]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.240]) with mapi id 14.03.0195.001; Tue, 25 Nov 2014 19:31:42 +0800 From: "Qiu, Michael" To: "Zang, Zhida" , "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH v2] i40e: link flow control support Thread-Index: AQHQBKBoIKO+5XQgn0SxrqxDW8IkVw== Date: Tue, 25 Nov 2014 11:31:40 +0000 Message-ID: <533710CFB86FA344BFBF2D6802E60286C9A502@SHSMSX101.ccr.corp.intel.com> References: <1416473922-8314-1-git-send-email-zhida.zang@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v2] i40e: link flow control support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Nov 2014 11:20:57 -0000 On 11/20/2014 5:00 PM, zhida zang wrote:=0A= > From: zzang =0A= >=0A= > Add link flow control support for i40e=0A= >=0A= > Signed-off-by: zhida zang =0A= > ---=0A= > lib/librte_pmd_i40e/i40e_ethdev.c | 155 ++++++++++++++++++++++++++++++++= +++++-=0A= > lib/librte_pmd_i40e/i40e_ethdev.h | 10 +++=0A= > 2 files changed, 162 insertions(+), 3 deletions(-)=0A= >=0A= > diff --git a/lib/librte_pmd_i40e/i40e_ethdev.c b/lib/librte_pmd_i40e/i40e= _ethdev.c=0A= > index a860af7..183b0be 100644=0A= > --- a/lib/librte_pmd_i40e/i40e_ethdev.c=0A= > +++ b/lib/librte_pmd_i40e/i40e_ethdev.c=0A= > @@ -69,6 +69,18 @@=0A= > #define I40E_DEFAULT_TX_WTHRESH 0=0A= > #define I40E_DEFAULT_TX_RSBIT_THRESH 32=0A= > =0A= > +/* Flow control default timer */=0A= > +#define I40E_DEFAULT_PAUSE_TIME 0xFFFFU=0A= > +=0A= > +/* Flow control default high water */=0A= > +#define I40E_DEFAULT_HIGH_WATER 0x1C40=0A= > +=0A= > +/* Flow control default low water */=0A= > +#define I40E_DEFAULT_LOW_WATER 0x1A40=0A= > +=0A= > +/* Flow control enable fwd bit */=0A= > +#define I40E_PRTMAC_FWD_CTRL 0x00000001=0A= =0A= Here why so much zero? Can it just be 0x1 for simple?=0A= > +=0A= > /* Maximun number of MAC addresses */=0A= > #define I40E_NUM_MACADDR_MAX 64=0A= > #define I40E_CLEAR_PXE_WAIT_MS 200=0A= > @@ -98,6 +110,12 @@=0A= > =0A= > #define I40E_PRE_TX_Q_CFG_WAIT_US 10 /* 10 us */=0A= > =0A= > +/* Receive Packet Buffer size */=0A= > +#define I40E_RXPBSIZE (968 * 1024)=0A= > +=0A= > +/* Receive Average Packet Size in Byte*/=0A= > +#define I40E_PACKET_AVERAGE_SIZE 128=0A= > +=0A= > static int eth_i40e_dev_init(\=0A= > __attribute__((unused)) struct eth_driver *eth_drv,=0A= > struct rte_eth_dev *eth_dev);=0A= > @@ -131,6 +149,8 @@ static void i40e_vlan_strip_queue_set(struct rte_eth_= dev *dev,=0A= > static int i40e_vlan_pvid_set(struct rte_eth_dev *dev, uint16_t pvid, in= t on);=0A= > static int i40e_dev_led_on(struct rte_eth_dev *dev);=0A= > static int i40e_dev_led_off(struct rte_eth_dev *dev);=0A= > +static int i40e_flow_ctrl_get(struct rte_eth_dev *dev,=0A= > + struct rte_eth_fc_conf *fc_conf);=0A= > static int i40e_flow_ctrl_set(struct rte_eth_dev *dev,=0A= > struct rte_eth_fc_conf *fc_conf);=0A= > static int i40e_priority_flow_ctrl_set(struct rte_eth_dev *dev,=0A= > @@ -237,6 +257,7 @@ static struct eth_dev_ops i40e_eth_dev_ops =3D {=0A= > .tx_queue_release =3D i40e_dev_tx_queue_release,=0A= > .dev_led_on =3D i40e_dev_led_on,=0A= > .dev_led_off =3D i40e_dev_led_off,=0A= > + .flow_ctrl_get =3D i40e_flow_ctrl_get,=0A= > .flow_ctrl_set =3D i40e_flow_ctrl_set,=0A= > .priority_flow_ctrl_set =3D i40e_priority_flow_ctrl_set,=0A= > .mac_addr_add =3D i40e_macaddr_add,=0A= > @@ -358,6 +379,9 @@ eth_i40e_dev_init(__rte_unused struct eth_driver *eth= _drv,=0A= > pf->adapter =3D I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);=0A= > pf->adapter->eth_dev =3D dev;=0A= > pf->dev_data =3D dev->data;=0A= > + pf->fc_conf.pause_time =3D I40E_DEFAULT_PAUSE_TIME;=0A= > + pf->fc_conf.high_water[0] =3D I40E_DEFAULT_HIGH_WATER;=0A= > + pf->fc_conf.low_water[0] =3D I40E_DEFAULT_LOW_WATER;=0A= > =0A= > hw->back =3D I40E_PF_TO_ADAPTER(pf);=0A= > hw->hw_addr =3D (uint8_t *)(pci_dev->mem_resource[0].addr);=0A= > @@ -1516,12 +1540,137 @@ i40e_dev_led_off(struct rte_eth_dev *dev)=0A= > }=0A= > =0A= > static int=0A= > -i40e_flow_ctrl_set(__rte_unused struct rte_eth_dev *dev,=0A= > - __rte_unused struct rte_eth_fc_conf *fc_conf)=0A= > +i40e_flow_ctrl_get(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_c= onf)=0A= > {=0A= > + struct i40e_hw *hw =3D I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);= =0A= > + struct i40e_pf *pf =3D I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);= =0A= > +=0A= > + fc_conf->pause_time =3D pf->fc_conf.pause_time;=0A= > + fc_conf->high_water =3D (pf->fc_conf.high_water[0] *=0A= > + I40E_PACKET_AVERAGE_SIZE) >> 10;=0A= > + fc_conf->low_water =3D (pf->fc_conf.low_water[0] *=0A= > + I40E_PACKET_AVERAGE_SIZE) >> 10;=0A= > +=0A= > + /*=0A= > + * Return current mode according to actual setting=0A= > + */=0A= > + switch (hw->fc.current_mode) {=0A= > + case I40E_FC_FULL:=0A= > + fc_conf->mode =3D RTE_FC_FULL;=0A= > + break;=0A= > + case I40E_FC_TX_PAUSE:=0A= > + fc_conf->mode =3D I40E_FC_TX_PAUSE;=0A= > + break;=0A= > + case I40E_FC_RX_PAUSE:=0A= > + fc_conf->mode =3D I40E_FC_RX_PAUSE;=0A= > + break;=0A= > + case I40E_FC_NONE:=0A= > + fc_conf->mode =3D RTE_FC_NONE;=0A= > + break;=0A= > + default:=0A= > + break;=0A= > + };=0A= > +=0A= > + return 0;=0A= > +}=0A= > +=0A= > +static int=0A= > +i40e_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_fc_conf *fc_c= onf)=0A= > +{=0A= > + uint32_t mflcn_reg, fctrl_reg, reg;=0A= > + uint32_t max_high_water;=0A= > + uint8_t i, aq_failure;=0A= > + int err;=0A= > + enum i40e_fc_mode rte_fcmode_2_i40e_fcmode[] =3D {=0A= > + I40E_FC_NONE,=0A= > + I40E_FC_RX_PAUSE,=0A= > + I40E_FC_TX_PAUSE,=0A= > + I40E_FC_FULL=0A= > + };=0A= > +=0A= > + max_high_water =3D I40E_RXPBSIZE >> 10;=0A= > + if ((fc_conf->high_water > max_high_water) ||=0A= > + (fc_conf->high_water < fc_conf->low_water)) {=0A= > + PMD_INIT_LOG(ERR, "Invalid high/low water setup value in KB, "=0A= > + "High_water must <=3D %d.", max_high_water);=0A= > + return -EINVAL;=0A= > + }=0A= > +=0A= > + struct i40e_hw *hw =3D I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);= =0A= > + struct i40e_pf *pf =3D I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);= =0A= > + hw->fc.requested_mode =3D rte_fcmode_2_i40e_fcmode[fc_conf->mode];=0A= > +=0A= > + pf->fc_conf.pause_time =3D fc_conf->pause_time;=0A= > + pf->fc_conf.high_water[0] =3D (fc_conf->high_water << 10) /=0A= > + I40E_PACKET_AVERAGE_SIZE;=0A= > + pf->fc_conf.low_water[0] =3D (fc_conf->low_water << 10) /=0A= > + I40E_PACKET_AVERAGE_SIZE;=0A= > +=0A= > PMD_INIT_FUNC_TRACE();=0A= > =0A= > - return -ENOSYS;=0A= > + err =3D i40e_set_fc(hw, &aq_failure, true);=0A= > + if (err < 0) {=0A= > + PMD_INIT_LOG(ERR, "failed to set link flow control,"=0A= > + "err =3D %d", aq_failure);=0A= > + return err;=0A= > + }=0A= > +=0A= > + if (i40e_is_40G_device(hw->device_id)) {=0A= > +=0A= > + /*=0A= > + * Configure flow control refresh threshold,=0A= > + * the value for stat_tx_pause_refresh_timer[8]=0A= > + * is used for global pause operation.=0A= > + */=0A= > + I40E_WRITE_REG(hw,=0A= > + I40E_PRTMAC_HSEC_CTL_TX_PAUSE_REFRESH_TIMER(8),=0A= > + pf->fc_conf.pause_time);=0A= > +=0A= > + /* configure the timer value included in transmitted pause=0A= > + * frame,=0A= > + * the value for stat_tx_pause_quanta[8] is used for global=0A= > + * pause operation=0A= > + */=0A= > + I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_TX_PAUSE_QUANTA(8),=0A= > + pf->fc_conf.pause_time);=0A= > +=0A= > + fctrl_reg =3D I40E_READ_REG(hw,=0A= > + I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL);=0A= > +=0A= > + if (fc_conf->mac_ctrl_frame_fwd !=3D 0)=0A= > + fctrl_reg |=3D I40E_PRTMAC_FWD_CTRL;=0A= > + else=0A= > + fctrl_reg &=3D ~I40E_PRTMAC_FWD_CTRL;=0A= > +=0A= > + I40E_WRITE_REG(hw, I40E_PRTMAC_HSEC_CTL_RX_FORWARD_CONTROL,=0A= > + fctrl_reg);=0A= > + } else {=0A= > + /* Configure pause time (2 TCs per register) */=0A= > + reg =3D (uint32_t)pf->fc_conf.pause_time * (uint32_t)0x00010001;=0A= > + for (i =3D 0; i < I40E_MAX_TRAFFIC_CLASS / 2; i++)=0A= > + I40E_WRITE_REG(hw, I40E_PRTDCB_FCTTVN(i), reg);=0A= > +=0A= > + /* Configure flow control refresh threshold value */=0A= > + I40E_WRITE_REG(hw, I40E_PRTDCB_FCRTV,=0A= > + pf->fc_conf.pause_time / 2);=0A= > +=0A= > + mflcn_reg =3D I40E_READ_REG(hw, I40E_PRTDCB_MFLCN);=0A= > +=0A= > + /* set or clear MFLCN.PMCF bit depending on configuration */=0A= > + if (fc_conf->mac_ctrl_frame_fwd !=3D 0)=0A= > + mflcn_reg |=3D I40E_PRTDCB_MFLCN_PMCF_MASK;=0A= > + else=0A= > + mflcn_reg &=3D ~I40E_PRTDCB_MFLCN_PMCF_MASK;=0A= > +=0A= > + I40E_WRITE_REG(hw, I40E_PRTDCB_MFLCN, mflcn_reg);=0A= > + }=0A= > +=0A= > + I40E_WRITE_REG(hw, I40E_GLRPB_PHW, pf->fc_conf.high_water[0]);=0A= > + I40E_WRITE_REG(hw, I40E_GLRPB_PLW, pf->fc_conf.low_water[0]);=0A= > +=0A= > + I40E_WRITE_FLUSH(hw);=0A= > +=0A= > + return 0;=0A= > }=0A= > =0A= > static int=0A= > diff --git a/lib/librte_pmd_i40e/i40e_ethdev.h b/lib/librte_pmd_i40e/i40e= _ethdev.h=0A= > index e61d258..c793c2d 100644=0A= > --- a/lib/librte_pmd_i40e/i40e_ethdev.h=0A= > +++ b/lib/librte_pmd_i40e/i40e_ethdev.h=0A= > @@ -231,6 +231,14 @@ struct i40e_pf_vf {=0A= > uint16_t lan_nb_qps; /* Actual queues allocated */=0A= > uint16_t reset_cnt; /* Total vf reset times */=0A= > };=0A= > +/*=0A= > + * Structure to store private data for flow control.=0A= > + */=0A= > +struct i40e_fc_conf {=0A= > + uint16_t pause_time; /* Flow control pause timer */=0A= > + uint32_t high_water[I40E_MAX_TRAFFIC_CLASS]; /* FC high water */=0A= > + uint32_t low_water[I40E_MAX_TRAFFIC_CLASS]; /* FC low water */=0A= > +};=0A= > =0A= > /*=0A= > * Structure to store private data specific for PF instance.=0A= > @@ -264,6 +272,8 @@ struct i40e_pf {=0A= > /* store VXLAN UDP ports */=0A= > uint16_t vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];=0A= > uint16_t vxlan_bitmap; /* Vxlan bit mask */=0A= > +=0A= > + struct i40e_fc_conf fc_conf; /* Flow control conf */=0A= > };=0A= > =0A= > enum pending_msg {=0A= =0A=