Hi Venky, Good point. Thus we avoid not only replacing all callbacks, but also adding lpbk field in struct ixgbe_hw. All loopback-aware operations will be then restricted to function ixgbe_dev_start and ixgbe_dev_rxtx_start.
The logic of ixgbe_dev_start will be sth. like: ... ... ixgbe_dev_tx_init(dev); ... ... if (loopback is configured) goto skip_setup_link; ... ... err = ixgbe_setup_link(hw, speed, negotiate, link_up); if (err) goto error; skip_setup_link: ... ... Meantime, as you suggested, the FLU bit will be set in ixgbe_dev_rxtx_start, if loopback is configured. I can send the patch later tomorrow if all agree with this proposal. thx & rgds, -qinglai On Wed, Sep 25, 2013 at 6:47 PM, Venkatesan, Venky <venky.venkatesan at intel.com> wrote: > Thanks a bunch. It does work. > > One more suggestion to think about; Once you set the FLU (force link up) bit > (bit 0) in the AUTOC (0x42A0) register, the auto-negotiation state will be > set to AN_GOOD, the link-up indication should be set regardless. Would you > still need the callbacks? You could then merge the setup_link code into > something like dev_rxtx_start() [ open to suggestions ]. > > Regards, > -Venky > > -----Original Message----- > From: jigsaw [mailto:jigsaw at gmail.com] > Sent: Wednesday, September 25, 2013 7:39 AM > To: Venkatesan, Venky > Cc: Ivan Boule; dev at dpdk.org > Subject: Re: [dpdk-dev] [PATCH] Add support for 82599 Tx->Rx loopback > operation. > > Hi Venky, > > Thanks for you comments. > >>>I for one would prefer that the changes not really modify any files in >>>the librte_pmd_ixgbe/ixgbe directory > > With this restriction it is gonna be little bit difficult but still feasible. > > The solution would be after calling ixgbe_init_shared_code in ixgbe_ethdev.c, > if the config is for loopback operation, we immediately replace the callbacks > of: > > mac->ops.get_link_capabilities > mac->ops.check_link > mac->ops.setup_link > > And of course the implementation of these callbacks can be in a new src file > under librte_pmd_ixgbe, thus keep the baseline untouched. > > Sounds like a plan? > > thx & > rgds, > -qinglai > > > On Wed, Sep 25, 2013 at 5:12 PM, Venkatesan, Venky <venky.venkatesan at > intel.com> wrote: >> Qinglai/Ivan, >> >> I for one would prefer that the changes not really modify any files in the >> librte_pmd_ixgbe/ixgbe directory. Those files are derived directly from the >> BSD driver baseline, and any changes will make future merges of newer code >> more challenging. The changes should be limited to files in the >> librte_pmd_ixgbe directory (and ethdev). >> >> Regards, >> -Venky >> >> >> -----Original Message----- >> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of jigsaw >> Sent: Wednesday, September 25, 2013 6:56 AM >> To: Ivan Boule >> Cc: dev at dpdk.org >> Subject: Re: [dpdk-dev] [PATCH] Add support for 82599 Tx->Rx loopback >> operation. >> >> Hi Ivan, >> >> Appreciations for your comments. >> I have one question regarding the new field, lpbk_mode, in struct >> rte_eth_conf. >> >> I was thinking how to define the values for this field, then I had a dilemma. >> >> 82599 has only two mode of loopback, either Tx->Rx or Rx->Tx. >> But other controller may have different ideas. For instance, I350 can be set >> as either MAC, PHY or SGMII loopback mode. >> So if we define loopback mode as a enum type in rte_ethdev.h, we then have >> to expose the driver level details. >> That is, the enum rte_loopback_mode will be sth. like: >> >> enum rte_loopback_mode { >> RTE_LOOPBACK_NONE, >> RTE_LOOPBACK_82599_TX_RX, >> RTE_LOOPBACK_I350_MAC, >> RTE_LOOPBACK_I350_PHY, >> /* will be more if we add support for other controllers */ }; >> >> IMO it doesn't look so nice coz the hardware specific details are exposed in >> a higher level API. >> >> However, if we don't expose these details here, like in the patch, the value >> is just a integer, user of the API may get confused, and he/she still has to >> be aware of what are possible values for his/her eth controller. >> >> There may be more subtle problems. It's not clear to me whether the loopback >> mode of certain controller is mutually exclusive. For instance, is it >> possible that the Rx-Tx and Tx-Rx can be activated at the same time for >> 82599? If so then the lpbk_mode has to be defined as bitfield. >> >> Having these questions in mind, I decided to expose just a uint32_t in >> rte_eth_conf, so that the solution is open for further changes. I should >> have stated my thoughts before sending the patch, and I hope it's not too >> late to open the discussion at this moment. >> >> Looking forward to your advice. >> >> thx & >> rgds, >> -qinglai >> >> >> On Wed, Sep 25, 2013 at 4:11 PM, Ivan Boule <ivan.boule at 6wind.com> wrote: >>> Hi Qinglai Xiao, >>> >>> See my remarks inline prefixed with IB> Best regards, Ivan >>> >>> On 09/23/2013 09:16 PM, Qinglai Xiao wrote: >>> >>> Signed-off-by: Qinglai Xiao <jigsaw at gmail.com> >>> --- >>> lib/librte_ether/rte_ethdev.h | 1 + >>> lib/librte_pmd_ixgbe/ixgbe/ixgbe_82599.c | 122 >>> +++++++++++++++++++++++++++++- >>> lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h | 7 ++ >>> lib/librte_pmd_ixgbe/ixgbe_ethdev.c | 8 ++ >>> lib/librte_pmd_ixgbe/ixgbe_rxtx.c | 6 ++ >>> 5 files changed, 141 insertions(+), 3 deletions(-) >>> >>> diff --git a/lib/librte_ether/rte_ethdev.h >>> b/lib/librte_ether/rte_ethdev.h index 2d7385f..f474e5b 100644 >>> --- a/lib/librte_ether/rte_ethdev.h >>> +++ b/lib/librte_ether/rte_ethdev.h >>> @@ -670,6 +670,7 @@ struct rte_eth_conf { >>> /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */ >>> uint16_t link_duplex; >>> /**< ETH_LINK_[HALF_DUPLEX|FULL_DUPLEX], or 0 for >>> autonegotation */ >>> + uint32_t lpbk; /**< Loopback operation. The value depends on >>> +ethernet >>> controller. */ >>> struct rte_eth_rxmode rxmode; /**< Port RX configuration. */ >>> struct rte_eth_txmode txmode; /**< Port TX configuration. */ >>> union { >>> >>> IB> As RX->TX loopback mode is not supported, only introduce the >>> configuration of the >>> TX->RX loopback mode in the DPDK API as follows: >>> >>> /** >>> * A set of flags to identify which loopback mode to use, if any. >>> */ >>> enum rte_loopback_mode { >>> RTE_LOOPBACK_NONE = 0, /**< No loopback */ >>> RTE_LOOPBACK_TX_RX, /**< TX->RX loopback mode */ >>> }; >>> >>> struct rte_eth_conf { >>> uint16_t link_speed; >>> >>> /**< ETH_LINK_SPEED_10[0|00|000], or 0 for autonegotation */ >>> uint16_t link_duplex; >>> /**< ETH_LINK_[HALF_DUPLEX|FULL_DUPLEX], or 0 for autonegotation */ >>> enum rte_loopback_mode lpbk_mode; /**< loopback mode. */ >>> ... >>> >>> }; >>> >>> diff --git a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_82599.c >>> b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_82599.c >>> index db07789..0416c01 100644 >>> --- a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_82599.c >>> +++ b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_82599.c >>> @@ -48,6 +48,17 @@ STATIC s32 ixgbe_read_eeprom_82599(struct ixgbe_hw >>> *hw, STATIC s32 ixgbe_read_eeprom_buffer_82599(struct ixgbe_hw *hw, u16 >>> offset, >>> u16 words, u16 *data); >>> >>> + >>> +STATIC s32 ixgbe_get_link_capabilities_82599_lpbk(struct ixgbe_hw *hw, >>> + ixgbe_link_speed *speed, >>> + bool *negotiation); STATIC s32 >>> +ixgbe_check_mac_link_82599_lpbk(struct ixgbe_hw *hw, >>> ixgbe_link_speed *speed, >>> + bool *link_up, bool >>> +link_up_wait_to_complete); STATIC s32 >>> ixgbe_setup_mac_link_82599_lpbk(struct ixgbe_hw *hw, >>> + ixgbe_link_speed speed, bool autoneg, >>> + bool autoneg_wait_to_complete); >>> + >>> + >>> void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) { >>> struct ixgbe_mac_info *mac = &hw->mac; @@ -68,7 +79,10 @@ void >>> ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw) >>> mac->ops.flap_tx_laser = NULL; >>> } >>> >>> - if (hw->phy.multispeed_fiber) { >>> + if (hw->lpbk == IXGBE_LPBK_82599_TX_RX) { >>> + /* Support for Tx->Rx loopback operation */ >>> + mac->ops.setup_link = &ixgbe_setup_mac_link_82599_lpbk; >>> + } else if (hw->phy.multispeed_fiber) { >>> /* Set up dual speed SFP+ support */ >>> mac->ops.setup_link = &ixgbe_setup_mac_link_multispeed_fiber; >>> } else { >>> @@ -266,8 +280,23 @@ s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw) >>> mac->ops.set_vlan_anti_spoofing = >>> &ixgbe_set_vlan_anti_spoofing; >>> >>> /* Link */ >>> - mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599; >>> - mac->ops.check_link = &ixgbe_check_mac_link_generic; >>> + >>> + /* 82599 has two loopback operations: Tx->Rx and Rx->Tx >>> + * Only Tx->Rx is supported for now. >>> + */ >>> + switch (hw->lpbk) { >>> + case IXGBE_LPBK_82599_TX_RX: >>> + mac->ops.get_link_capabilities = >>> &ixgbe_get_link_capabilities_82599_lpbk; >>> + mac->ops.check_link = &ixgbe_check_mac_link_82599_lpbk; >>> + break; >>> + >>> + case IXGBE_LPBK_82599_NONE: /* FALL THRU */ >>> + default: >>> + mac->ops.get_link_capabilities = >>> &ixgbe_get_link_capabilities_82599; >>> + mac->ops.check_link = &ixgbe_check_mac_link_generic; >>> + break; >>> + } >>> + >>> mac->ops.setup_rxpba = &ixgbe_set_rxpba_generic; >>> ixgbe_init_mac_link_ops_82599(hw); >>> >>> @@ -2370,5 +2399,92 @@ reset_pipeline_out: >>> return ret_val; >>> } >>> >>> +/** >>> + * ixgbe_get_link_capabilities_82599_lpbk - Determines link >>> +capabilities >>> for Tx->Rx loopback setting >>> + * @hw: pointer to hardware structure >>> + * @speed: pointer to link speed >>> + * @negotiation: always false >>> + * >>> + * For Tx->Rx loopback only. Rx->Tx loopback is not supported for now. >>> + * >>> + * @speed is always set to IXGBE_LINK_SPEED_10GB_FULL, >>> + * @negotiation is always set to false. >>> + **/ >>> +STATIC s32 ixgbe_get_link_capabilities_82599_lpbk(struct ixgbe_hw *hw, >>> + ixgbe_link_speed *speed, >>> + bool *negotiation) { >>> + DEBUGFUNC("ixgbe_get_link_capabilities_82599_lpbk"); >>> + >>> + *speed = IXGBE_LINK_SPEED_10GB_FULL; >>> + *negotiation = false; >>> + >>> + return IXGBE_SUCCESS; >>> +} >>> >>> +/** >>> + * ixgbe_check_mac_link_82599_lpbk - Determine link and speed >>> +status for >>> loopback Tx->Rx setting >>> + * @hw: pointer to hardware structure >>> + * @speed: pointer to link speed >>> + * @link_up: true when link is up >>> + * @link_up_wait_to_complete: bool used to wait for link up or not >>> + * >>> + * For Tx->Rx loopback only. Rx->Tx loopback is not supported for now. >>> + * >>> + * Regardless of link status (LINKS), always set @linkup to true, >>> + * and @speed to IXGBE_LINK_SPEED_10GB_FULL. >>> + **/ >>> +STATIC s32 ixgbe_check_mac_link_82599_lpbk(struct ixgbe_hw *hw, >>> ixgbe_link_speed *speed, >>> + bool *link_up, bool link_up_wait_to_complete) { >>> + DEBUGFUNC("ixgbe_check_mac_link_82599_lpbk"); >>> + >>> + *link_up = true; >>> + *speed = IXGBE_LINK_SPEED_10GB_FULL; >>> + >>> + return 0; >>> +} >>> + >>> +/** >>> + * ixgbe_setup_mac_link_82599_loopback - Set MAC link speed for >>> +Tx->Rx >>> loopback operation. >>> + * @hw: pointer to hardware structure >>> + * @speed: new link speed >>> + * @autoneg: true if autonegotiation enabled >>> + * @autoneg_wait_to_complete: true when waiting for completion is >>> +needed >>> + * >>> + * For Tx->Rx loopback only. Rx->Tx loopback is not supported for now. >>> + * >>> + * @speed, @autoneg and @autoneg_wait_to_complete are ignored. >>> + * Just set AUTOC to IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU. >>> + **/ >>> +STATIC s32 ixgbe_setup_mac_link_82599_lpbk(struct ixgbe_hw *hw, >>> + ixgbe_link_speed speed, bool autoneg, >>> + bool autoneg_wait_to_complete) { >>> + u32 autoc; >>> + u32 status = IXGBE_SUCCESS; >>> + >>> + DEBUGFUNC("ixgbe_setup_mac_link_82599_lpbk"); >>> + autoc = IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU; >>> + >>> + if (ixgbe_verify_lesm_fw_enabled_82599(hw)) { >>> + status = hw->mac.ops.acquire_swfw_sync(hw, >>> + IXGBE_GSSR_MAC_CSR_SM); >>> + if (status != IXGBE_SUCCESS) { >>> + status = IXGBE_ERR_SWFW_SYNC; >>> + goto out; >>> + } >>> + } >>> + >>> + /* Restart link */ >>> + IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc); >>> + ixgbe_reset_pipeline_82599(hw); >>> + >>> + hw->mac.ops.release_swfw_sync(hw, >>> + IXGBE_GSSR_MAC_CSR_SM); >>> + msec_delay(50); >>> + >>> +out: >>> + return status; >>> +} >>> >>> diff --git a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h >>> b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h >>> index 7fffd60..a31c9f7 100644 >>> --- a/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h >>> +++ b/lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h >>> @@ -2352,6 +2352,12 @@ enum ixgbe_fdir_pballoc_type { >>> #define FW_CEM_MAX_RETRIES 3 >>> #define FW_CEM_RESP_STATUS_SUCCESS 0x1 >>> >>> +/* Loopback operation types */ >>> +/* 82599 specific loopback operation types */ >>> +#define IXGBE_LPBK_82599_NONE 0x0 /* Default value. >>> Loopback is disabled. >>> */ >>> +#define IXGBE_LPBK_82599_TX_RX 0x1 /* Tx->Rx loopback >>> operation is >>> enabled. */ >>> +#define IXGBE_LPBK_82599_RX_TX 0x2 /* Rx->Tx loopback >>> operation is >>> enabled. */ >>> + >>> /* Host Interface Command Structures */ >>> >>> struct ixgbe_hic_hdr { >>> @@ -3150,6 +3156,7 @@ struct ixgbe_hw { >>> int api_version; >>> bool force_full_reset; >>> bool allow_unsupported_sfp; >>> + uint32_t lpbk; >>> >>> IB> A uint8_t is enough. >>> >>> }; >>> >>> >>> #define ixgbe_call_func(hw, func, params, error) \ diff --git >>> a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c >>> b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c >>> index 9235f9d..09600bc 100644 >>> --- a/lib/librte_pmd_ixgbe/ixgbe_ethdev.c >>> +++ b/lib/librte_pmd_ixgbe/ixgbe_ethdev.c >>> @@ -1137,6 +1137,14 @@ ixgbe_dev_configure(struct rte_eth_dev *dev) >>> >>> PMD_INIT_FUNC_TRACE(); >>> >>> + if (dev->data->dev_conf.lpbk) { >>> >>> IB> replace the line above by: >>> + if (dev->data->dev_conf.lpbk_mode != RTE_LOOPBACK_NONE) { >>> >>> + struct ixgbe_hw *hw = >>> + >>> + IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private); >>> + >>> + hw->lpbk = dev->data->dev_conf.lpbk; >>> >>> IB> replace the line above by: >>> + /* Only supports TX->RX loopback mode for now. */ >>> + hw->lpbk = IXGBE_LPBK_82599_TX_RX; >>> >>> + } >>> + >>> + >>> /* set flag to update link status after init */ >>> intr->flags |= IXGBE_FLAG_NEED_LINK_UPDATE; >>> >>> diff --git a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c >>> b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c >>> index 5fba01d..158da0e 100644 >>> --- a/lib/librte_pmd_ixgbe/ixgbe_rxtx.c >>> +++ b/lib/librte_pmd_ixgbe/ixgbe_rxtx.c >>> @@ -3252,6 +3252,12 @@ ixgbe_dev_rx_init(struct rte_eth_dev *dev) >>> } else >>> hlreg0 &= ~IXGBE_HLREG0_JUMBOEN; >>> >>> + /* >>> + * Both Tx->Rx and Rx->Tx requres IXGBE_HLREG0_LPBK to be set. >>> >>> IB> requres -> requires >>> >>> + */ >>> + if (hw->lpbk) >>> + hlreg0 |= IXGBE_HLREG0_LPBK; >>> + >>> IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0); >>> >>> /* Setup RX queues */ >>> >>> >>> >>> -- >>> Ivan Boule >>> 6WIND Development Engineer