@@ -850,6 +850,10 @@ ngbe_dev_start(struct rte_eth_dev *dev)
goto error;
}
+ /* Skip link setup if loopback mode is enabled. */
+ if (hw->is_pf && dev->data->dev_conf.lpbk_mode)
+ goto skip_link_setup;
+
err = hw->mac.check_link(hw, &speed, &link_up, 0);
if (err != 0)
goto error;
@@ -893,6 +897,8 @@ ngbe_dev_start(struct rte_eth_dev *dev)
if (err != 0)
goto error;
+skip_link_setup:
+
if (rte_intr_allow_others(intr_handle)) {
ngbe_dev_misc_interrupt_setup(dev);
/* check if lsc interrupt is enabled */
@@ -2420,6 +2420,17 @@ ngbe_dev_rx_init(struct rte_eth_dev *dev)
NGBE_FRMSZ_MAX(NGBE_FRAME_SIZE_DFT));
}
+ /*
+ * If loopback mode is configured, set LPBK bit.
+ */
+ hlreg0 = rd32(hw, NGBE_PSRCTL);
+ if (hw->is_pf && dev->data->dev_conf.lpbk_mode)
+ hlreg0 |= NGBE_PSRCTL_LBENA;
+ else
+ hlreg0 &= ~NGBE_PSRCTL_LBENA;
+
+ wr32(hw, NGBE_PSRCTL, hlreg0);
+
/*
* Assume no header split and no VLAN strip support
* on any Rx queue first .
@@ -2538,6 +2549,19 @@ ngbe_dev_tx_init(struct rte_eth_dev *dev)
}
}
+/*
+ * Set up link loopback mode Tx->Rx.
+ */
+static inline void
+ngbe_setup_loopback_link(struct ngbe_hw *hw)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ wr32m(hw, NGBE_MACRXCFG, NGBE_MACRXCFG_LB, NGBE_MACRXCFG_LB);
+
+ msec_delay(50);
+}
+
/*
* Start Transmit and Receive Units.
*/
@@ -2592,6 +2616,10 @@ ngbe_dev_rxtx_start(struct rte_eth_dev *dev)
rxctrl |= NGBE_PBRXCTL_ENA;
hw->mac.enable_rx_dma(hw, rxctrl);
+ /* If loopback mode is enabled, set up the link accordingly */
+ if (hw->is_pf && dev->data->dev_conf.lpbk_mode)
+ ngbe_setup_loopback_link(hw);
+
return 0;
}