[dpdk-dev] [PATCH] Add support for 82599 Tx->Rx loopback operation.
Qinglai Xiao
jigsaw at gmail.com
Mon Sep 23 21:16:20 CEST 2013
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 {
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;
};
#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) {
+ struct ixgbe_hw *hw =
+ IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ hw->lpbk = dev->data->dev_conf.lpbk;
+ }
+
+
/* 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.
+ */
+ if (hw->lpbk)
+ hlreg0 |= IXGBE_HLREG0_LPBK;
+
IXGBE_WRITE_REG(hw, IXGBE_HLREG0, hlreg0);
/* Setup RX queues */
--
1.7.10.4
More information about the dev
mailing list