[v4,3/6] net/txgbe: update link setup process of backplane NICs

Message ID 20210329031724.1468339-4-jiawenwu@trustnetic.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers
Series txgbe backplane AN training |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Jiawen Wu March 29, 2021, 3:17 a.m. UTC
  Add device arguments to support runtime options.
And use these configuration to control the link setup flow, to adapt to
different NIC's construction. Use firmware version to control the impact
of firmware update. And fix some left bugs.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 doc/guides/nics/txgbe.rst             |  34 +++++++
 drivers/net/txgbe/base/txgbe_eeprom.h |   3 +
 drivers/net/txgbe/base/txgbe_hw.c     |  85 +---------------
 drivers/net/txgbe/base/txgbe_osdep.h  |   1 +
 drivers/net/txgbe/base/txgbe_phy.c    | 141 +++++++++++++++-----------
 drivers/net/txgbe/base/txgbe_phy.h    |  90 ++++++++++++++--
 drivers/net/txgbe/base/txgbe_type.h   |  23 ++++-
 drivers/net/txgbe/txgbe_ethdev.c      |  57 +++++++++++
 drivers/net/txgbe/txgbe_logs.h        |   9 ++
 9 files changed, 299 insertions(+), 144 deletions(-)
  

Patch

diff --git a/doc/guides/nics/txgbe.rst b/doc/guides/nics/txgbe.rst
index e520f13f3..14243079d 100644
--- a/doc/guides/nics/txgbe.rst
+++ b/doc/guides/nics/txgbe.rst
@@ -84,6 +84,40 @@  TXGBE PMD provides the following log types available for control:
 
   Extra logging of the messages during PMD initialization.
 
+- ``pmd.net.txgbe.bp`` (default level is **notice**)
+
+  Extra logging of auto-negtiation process for backplane NICs.
+  Supply ``--log-level=pmd.net.txgbe.bp:debug`` to view messages.
+
+Runtime Options
+~~~~~~~~~~~~~~~
+
+The following ``devargs`` options can be enabled at runtime. They must
+be passed as part of EAL arguments. For example,
+
+.. code-block:: console
+
+   dpdk-testpmd -a 01:00.0,auto_neg=1 -- -i
+
+Please note that following ``devargs`` are only set for backplane NICs.
+
+- ``auto_neg`` (default **1**)
+
+  Toggle behavior to use auto-negotiation mode or force mode to
+  link up backplane NICs.
+
+- ``poll`` (default **0**)
+
+  Toggle behavior to enable/disable polling mode to receive AN interrupt.
+
+- ``present`` (default **1**)
+
+  Toggle behavior to use present mode or init mode.
+
+- ``sgmii`` (default **0**)
+
+  Special treatment for KX SGMII cards.
+
 Driver compilation and testing
 ------------------------------
 
diff --git a/drivers/net/txgbe/base/txgbe_eeprom.h b/drivers/net/txgbe/base/txgbe_eeprom.h
index 78b8af978..3a5d7c621 100644
--- a/drivers/net/txgbe/base/txgbe_eeprom.h
+++ b/drivers/net/txgbe/base/txgbe_eeprom.h
@@ -9,6 +9,9 @@ 
 #define TXGBE_PBANUM_PTR_GUARD		0xFAFA
 #define TXGBE_EEPROM_SUM		0xBABA
 
+#define TXGBE_FW_VER_LEN	32
+#define TXGBE_FW_N_TXEQ		0x0002000A
+
 #define TXGBE_FW_PTR			0x0F
 #define TXGBE_PBANUM0_PTR		0x05
 #define TXGBE_PBANUM1_PTR		0x06
diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c
index 26562f50d..521cb4650 100644
--- a/drivers/net/txgbe/base/txgbe_hw.c
+++ b/drivers/net/txgbe/base/txgbe_hw.c
@@ -91,7 +91,6 @@  s32 txgbe_setup_fc(struct txgbe_hw *hw)
 	u16 reg_cu = 0;
 	u32 value = 0;
 	u64 reg_bp = 0;
-	bool locked = false;
 
 	DEBUGFUNC("txgbe_setup_fc");
 
@@ -109,29 +108,6 @@  s32 txgbe_setup_fc(struct txgbe_hw *hw)
 	if (hw->fc.requested_mode == txgbe_fc_default)
 		hw->fc.requested_mode = txgbe_fc_full;
 
-	/*
-	 * Set up the 1G and 10G flow control advertisement registers so the
-	 * HW will be able to do fc autoneg once the cable is plugged in.  If
-	 * we link at 10G, the 1G advertisement is harmless and vice versa.
-	 */
-	switch (hw->phy.media_type) {
-	case txgbe_media_type_backplane:
-		/* some MAC's need RMW protection on AUTOC */
-		err = hw->mac.prot_autoc_read(hw, &locked, &reg_bp);
-		if (err != 0)
-			goto out;
-
-		/* fall through - only backplane uses autoc */
-	case txgbe_media_type_fiber_qsfp:
-	case txgbe_media_type_fiber:
-	case txgbe_media_type_copper:
-		hw->phy.read_reg(hw, TXGBE_MD_AUTO_NEG_ADVT,
-				     TXGBE_MD_DEV_AUTO_NEG, &reg_cu);
-		break;
-	default:
-		break;
-	}
-
 	/*
 	 * The possible values of fc.requested_mode are:
 	 * 0: Flow control is completely disabled
@@ -145,13 +121,6 @@  s32 txgbe_setup_fc(struct txgbe_hw *hw)
 	switch (hw->fc.requested_mode) {
 	case txgbe_fc_none:
 		/* Flow control completely disabled by software override. */
-		reg &= ~(SR_MII_MMD_AN_ADV_PAUSE_SYM |
-			SR_MII_MMD_AN_ADV_PAUSE_ASM);
-		if (hw->phy.media_type == txgbe_media_type_backplane)
-			reg_bp &= ~(TXGBE_AUTOC_SYM_PAUSE |
-				    TXGBE_AUTOC_ASM_PAUSE);
-		else if (hw->phy.media_type == txgbe_media_type_copper)
-			reg_cu &= ~(TXGBE_TAF_SYM_PAUSE | TXGBE_TAF_ASM_PAUSE);
 		break;
 	case txgbe_fc_tx_pause:
 		/*
@@ -159,15 +128,6 @@  s32 txgbe_setup_fc(struct txgbe_hw *hw)
 		 * disabled by software override.
 		 */
 		reg |= SR_MII_MMD_AN_ADV_PAUSE_ASM;
-		reg &= ~SR_MII_MMD_AN_ADV_PAUSE_SYM;
-		if (hw->phy.media_type == txgbe_media_type_backplane) {
-			reg_bp |= TXGBE_AUTOC_ASM_PAUSE;
-			reg_bp &= ~TXGBE_AUTOC_SYM_PAUSE;
-		} else if (hw->phy.media_type == txgbe_media_type_copper) {
-			reg_cu |= TXGBE_TAF_ASM_PAUSE;
-			reg_cu &= ~TXGBE_TAF_SYM_PAUSE;
-		}
-		reg |= SR_MII_MMD_AN_ADV_PAUSE_ASM;
 		reg_bp |= SR_AN_MMD_ADV_REG1_PAUSE_ASM;
 		break;
 	case txgbe_fc_rx_pause:
@@ -182,13 +142,6 @@  s32 txgbe_setup_fc(struct txgbe_hw *hw)
 		 */
 	case txgbe_fc_full:
 		/* Flow control (both Rx and Tx) is enabled by SW override. */
-		reg |= SR_MII_MMD_AN_ADV_PAUSE_SYM |
-			SR_MII_MMD_AN_ADV_PAUSE_ASM;
-		if (hw->phy.media_type == txgbe_media_type_backplane)
-			reg_bp |= TXGBE_AUTOC_SYM_PAUSE |
-				  TXGBE_AUTOC_ASM_PAUSE;
-		else if (hw->phy.media_type == txgbe_media_type_copper)
-			reg_cu |= TXGBE_TAF_SYM_PAUSE | TXGBE_TAF_ASM_PAUSE;
 		reg |= SR_MII_MMD_AN_ADV_PAUSE_SYM |
 			SR_MII_MMD_AN_ADV_PAUSE_ASM;
 		reg_bp |= SR_AN_MMD_ADV_REG1_PAUSE_SYM |
@@ -2575,13 +2528,9 @@  void txgbe_init_mac_link_ops(struct txgbe_hw *hw)
 		mac->setup_link = txgbe_setup_mac_link_multispeed_fiber;
 		mac->setup_mac_link = txgbe_setup_mac_link;
 		mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed;
-	} else if ((hw->phy.media_type == txgbe_media_type_backplane) &&
-		    (hw->phy.smart_speed == txgbe_smart_speed_auto ||
-		     hw->phy.smart_speed == txgbe_smart_speed_on) &&
-		     !txgbe_verify_lesm_fw_enabled_raptor(hw)) {
-		mac->setup_link = txgbe_setup_mac_link_smartspeed;
 	} else {
 		mac->setup_link = txgbe_setup_mac_link;
+		mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed;
 	}
 }
 
@@ -3309,13 +3258,11 @@  s32 txgbe_setup_mac_link(struct txgbe_hw *hw,
 	u64 pma_pmd_10gs = autoc & TXGBE_AUTOC_10GS_PMA_PMD_MASK;
 	u64 pma_pmd_1g = autoc & TXGBE_AUTOC_1G_PMA_PMD_MASK;
 	u64 link_mode = autoc & TXGBE_AUTOC_LMS_MASK;
-	u64 current_autoc = autoc;
 	u64 orig_autoc = 0;
-	u32 links_reg;
-	u32 i;
 	u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN;
 
 	DEBUGFUNC("txgbe_setup_mac_link");
+	UNREFERENCED_PARAMETER(autoneg_wait_to_complete);
 
 	/* Check to see if speed passed in is supported. */
 	status = hw->mac.get_link_capabilities(hw,
@@ -3346,8 +3293,7 @@  s32 txgbe_setup_mac_link(struct txgbe_hw *hw,
 		if (speed & TXGBE_LINK_SPEED_10GB_FULL) {
 			if (orig_autoc & TXGBE_AUTOC_KX4_SUPP)
 				autoc |= TXGBE_AUTOC_KX4_SUPP;
-			if ((orig_autoc & TXGBE_AUTOC_KR_SUPP) &&
-			    !hw->phy.smart_speed_active)
+			if (orig_autoc & TXGBE_AUTOC_KR_SUPP)
 				autoc |= TXGBE_AUTOC_KR_SUPP;
 		}
 		if (speed & TXGBE_LINK_SPEED_1GB_FULL)
@@ -3374,35 +3320,14 @@  s32 txgbe_setup_mac_link(struct txgbe_hw *hw,
 		}
 	}
 
-	if (autoc == current_autoc)
-		return status;
-
 	autoc &= ~TXGBE_AUTOC_SPEED_MASK;
 	autoc |= TXGBE_AUTOC_SPEED(speed);
+	autoc &= ~TXGBE_AUTOC_AUTONEG;
 	autoc |= (autoneg ? TXGBE_AUTOC_AUTONEG : 0);
 
 	/* Restart link */
 	hw->mac.autoc_write(hw, autoc);
 
-	/* Only poll for autoneg to complete if specified to do so */
-	if (autoneg_wait_to_complete) {
-		if (link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR ||
-		    link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
-		    link_mode == TXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
-			links_reg = 0; /*Just in case Autoneg time=0*/
-			for (i = 0; i < TXGBE_AUTO_NEG_TIME; i++) {
-				links_reg = rd32(hw, TXGBE_PORTSTAT);
-				if (links_reg & TXGBE_PORTSTAT_UP)
-					break;
-				msec_delay(100);
-			}
-			if (!(links_reg & TXGBE_PORTSTAT_UP)) {
-				status = TXGBE_ERR_AUTONEG_NOT_COMPLETE;
-				DEBUGOUT("Autoneg did not complete.\n");
-			}
-		}
-	}
-
 	/* Add delay to filter out noises during initial link setup */
 	msec_delay(50);
 
@@ -3515,6 +3440,7 @@  txgbe_reset_misc(struct txgbe_hw *hw)
 	/* enable mac transmitter */
 	wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, TXGBE_MACTXCFG_TXE);
 
+	hw->mac.autoc = hw->mac.orig_autoc;
 	for (i = 0; i < 4; i++)
 		wr32m(hw, TXGBE_IVAR(i), 0x80808080, 0);
 }
@@ -3608,7 +3534,6 @@  s32 txgbe_reset_hw(struct txgbe_hw *hw)
 	 */
 	if (!hw->mac.orig_link_settings_stored) {
 		hw->mac.orig_autoc = hw->mac.autoc_read(hw);
-		hw->mac.autoc_write(hw, hw->mac.orig_autoc);
 		hw->mac.orig_link_settings_stored = true;
 	} else {
 		hw->mac.orig_autoc = autoc;
diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h
index e18e400af..074d7a306 100644
--- a/drivers/net/txgbe/base/txgbe_osdep.h
+++ b/drivers/net/txgbe/base/txgbe_osdep.h
@@ -36,6 +36,7 @@ 
 #define msec_delay(x) rte_delay_ms(x)
 #define usleep(x)     rte_delay_us(x)
 #define msleep(x)     rte_delay_ms(x)
+#define usec_stamp()    (rte_get_timer_cycles() * 1000000 / rte_get_timer_hz())
 
 #define FALSE               0
 #define TRUE                1
diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c
index 1ca6e35a4..33d3839ed 100644
--- a/drivers/net/txgbe/base/txgbe_phy.c
+++ b/drivers/net/txgbe/base/txgbe_phy.c
@@ -9,6 +9,7 @@ 
 
 static void txgbe_i2c_start(struct txgbe_hw *hw);
 static void txgbe_i2c_stop(struct txgbe_hw *hw);
+static s32 txgbe_set_link_to_sfi(struct txgbe_hw *hw, u32 speed);
 
 /**
  * txgbe_identify_extphy - Identify a single address for a PHY
@@ -1416,6 +1417,7 @@  static s32
 txgbe_set_link_to_kr(struct txgbe_hw *hw, bool autoneg)
 {
 	u32 i;
+	u16 value;
 	s32 err = 0;
 
 	/* 1. Wait xpcs power-up good */
@@ -1430,18 +1432,33 @@  txgbe_set_link_to_kr(struct txgbe_hw *hw, bool autoneg)
 		err = TXGBE_ERR_XPCS_POWER_UP_FAILED;
 		goto out;
 	}
+	BP_LOG("It is set to kr.\n");
+
+	wr32_epcs(hw, VR_AN_INTR_MSK, 0x7);
+	wr32_epcs(hw, TXGBE_PHY_TX_POWER_ST_CTL, 0x00FC);
+	wr32_epcs(hw, TXGBE_PHY_RX_POWER_ST_CTL, 0x00FC);
 
 	if (!autoneg) {
 		/* 2. Disable xpcs AN-73 */
-		wr32_epcs(hw, SR_AN_CTRL, 0x0);
-		/* Disable PHY MPLLA for eth mode change(after ECO) */
-		wr32_ephy(hw, 0x4, 0x243A);
-		txgbe_flush(hw);
-		msec_delay(1);
-		/* Set the eth change_mode bit first in mis_rst register
-		 * for corresponding LAN port
-		 */
-		wr32(hw, TXGBE_RST, TXGBE_RST_ETH(hw->bus.lan_id));
+		wr32_epcs(hw, SR_AN_CTRL,
+			SR_AN_CTRL_AN_EN | SR_AN_CTRL_EXT_NP);
+
+		wr32_epcs(hw, VR_AN_KR_MODE_CL, VR_AN_KR_MODE_CL_PDET);
+
+		if (!(hw->devarg.auto_neg == 1)) {
+			wr32_epcs(hw, SR_AN_CTRL, 0);
+			wr32_epcs(hw, VR_AN_KR_MODE_CL, 0);
+		}
+		if (hw->devarg.present  == 1) {
+			value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
+			value |= TXGBE_PHY_TX_EQ_CTL1_DEF;
+			wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+		}
+		if (hw->devarg.poll == 1) {
+			wr32_epcs(hw, VR_PMA_KRTR_TIMER_CTRL0,
+				VR_PMA_KRTR_TIMER_MAX_WAIT);
+			wr32_epcs(hw, VR_PMA_KRTR_TIMER_CTRL2, 0xA697);
+		}
 
 		/* 3. Set VR_XS_PMA_Gen5_12G_MPLLA_CTRL3 Register
 		 * Bit[10:0](MPLLA_BANDWIDTH) = 11'd123 (default: 11'd16)
@@ -1501,6 +1518,10 @@  txgbe_set_link_to_kx4(struct txgbe_hw *hw, bool autoneg)
 	if (hw->link_status == TXGBE_LINK_STATUS_KX4)
 		goto out;
 
+	BP_LOG("It is set to kx4.\n");
+	wr32_epcs(hw, TXGBE_PHY_TX_POWER_ST_CTL, 0);
+	wr32_epcs(hw, TXGBE_PHY_RX_POWER_ST_CTL, 0);
+
 	/* 1. Wait xpcs power-up good */
 	for (i = 0; i < 100; i++) {
 		if ((rd32_epcs(hw, VR_XS_OR_PCS_MMD_DIGI_STATUS) &
@@ -1545,16 +1566,13 @@  txgbe_set_link_to_kx4(struct txgbe_hw *hw, bool autoneg)
 	wr32_epcs(hw, SR_PMA_CTRL1,
 			SR_PMA_CTRL1_SS13_KX4);
 
-	value = (0xf5f0 & ~0x7F0) |  (0x5 << 8) | (0x7 << 5) | 0x10;
+	value = (0xf5f0 & ~0x7F0) |  (0x5 << 8) | (0x7 << 5) | 0xF0;
 	wr32_epcs(hw, TXGBE_PHY_TX_GENCTRL1, value);
 
-	wr32_epcs(hw, TXGBE_PHY_MISC_CTL0, 0x4F00);
-
-	value = (0x1804 & ~0x3F3F);
-	wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
-
-	value = (0x50 & ~0x7F) | 40 | (1 << 6);
-	wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+	if ((hw->subsystem_device_id & 0xFF) == TXGBE_DEV_ID_MAC_XAUI)
+		wr32_epcs(hw, TXGBE_PHY_MISC_CTL0, 0xCF00);
+	else
+		wr32_epcs(hw, TXGBE_PHY_MISC_CTL0, 0x4F00);
 
 	for (i = 0; i < 4; i++) {
 		if (i == 0)
@@ -1682,6 +1700,13 @@  txgbe_set_link_to_kx4(struct txgbe_hw *hw, bool autoneg)
 		goto out;
 	}
 
+	if (hw->fw_version <= TXGBE_FW_N_TXEQ) {
+		value = (0x1804 & ~0x3F3F);
+		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+		value = (0x50 & ~0x7F) | 40 | (1 << 6);
+		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+	}
 out:
 	return err;
 }
@@ -1700,6 +1725,10 @@  txgbe_set_link_to_kx(struct txgbe_hw *hw,
 	if (hw->link_status == TXGBE_LINK_STATUS_KX)
 		goto out;
 
+	BP_LOG("It is set to kx. speed =0x%x\n", speed);
+	wr32_epcs(hw, TXGBE_PHY_TX_POWER_ST_CTL, 0x00FC);
+	wr32_epcs(hw, TXGBE_PHY_RX_POWER_ST_CTL, 0x00FC);
+
 	/* 1. Wait xpcs power-up good */
 	for (i = 0; i < 100; i++) {
 		if ((rd32_epcs(hw, VR_XS_OR_PCS_MMD_DIGI_STATUS) &
@@ -1756,16 +1785,13 @@  txgbe_set_link_to_kx(struct txgbe_hw *hw,
 	wr32_epcs(hw, SR_MII_MMD_CTL,
 			wdata);
 
-	value = (0xf5f0 & ~0x710) |  (0x5 << 8);
+	value = (0xf5f0 & ~0x710) | (0x5 << 8) | 0x10;
 	wr32_epcs(hw, TXGBE_PHY_TX_GENCTRL1, value);
 
-	wr32_epcs(hw, TXGBE_PHY_MISC_CTL0, 0x4F00);
-
-	value = (0x1804 & ~0x3F3F) | (24 << 8) | 4;
-	wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
-
-	value = (0x50 & ~0x7F) | 16 | (1 << 6);
-	wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+	if (hw->devarg.sgmii == 1)
+		wr32_epcs(hw, TXGBE_PHY_MISC_CTL0, 0x4F00);
+	else
+		wr32_epcs(hw, TXGBE_PHY_MISC_CTL0, 0xCF00);
 
 	for (i = 0; i < 4; i++) {
 		if (i) {
@@ -1881,6 +1907,13 @@  txgbe_set_link_to_kx(struct txgbe_hw *hw,
 		goto out;
 	}
 
+	if (hw->fw_version <= TXGBE_FW_N_TXEQ) {
+		value = (0x1804 & ~0x3F3F) | (24 << 8) | 4;
+		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+		value = (0x50 & ~0x7F) | 16 | (1 << 6);
+		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+	}
 out:
 	return err;
 }
@@ -1977,18 +2010,7 @@  txgbe_set_link_to_sfi(struct txgbe_hw *hw,
 		 * MPLLA_DIV8_CLK_EN=0
 		 */
 		wr32_epcs(hw, TXGBE_PHY_MPLLA_CTL2, 0x0600);
-		/* 5. Set VR_XS_PMA_Gen5_12G_TX_EQ_CTRL0 Register
-		 * Bit[13:8](TX_EQ_MAIN) = 6'd30, Bit[5:0](TX_EQ_PRE) = 6'd4
-		 */
-		value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0);
-		value = (value & ~0x3F3F) | (24 << 8) | 4;
-		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
-		/* 6. Set VR_XS_PMA_Gen5_12G_TX_EQ_CTRL1 Register
-		 * Bit[6](TX_EQ_OVR_RIDE) = 1'b1, Bit[5:0](TX_EQ_POST) = 6'd36
-		 */
-		value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
-		value = (value & ~0x7F) | 16 | (1 << 6);
-		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+
 		if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 ||
 			hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) {
 			/* 7. Set VR_XS_PMA_Gen5_12G_RX_EQ_CTRL0 Register
@@ -2055,18 +2077,7 @@  txgbe_set_link_to_sfi(struct txgbe_hw *hw,
 		 * Bit[12:8](RX_VREF_CTRL) = 5'hF
 		 */
 		wr32_epcs(hw, TXGBE_PHY_MISC_CTL0, 0xCF00);
-		/* 5. Set VR_XS_PMA_Gen5_12G_TX_EQ_CTRL0 Register
-		 * Bit[13:8](TX_EQ_MAIN) = 6'd30, Bit[5:0](TX_EQ_PRE) = 6'd4
-		 */
-		value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0);
-		value = (value & ~0x3F3F) | (24 << 8) | 4;
-		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
-		/* 6. Set VR_XS_PMA_Gen5_12G_TX_EQ_CTRL1 Register Bit[6]
-		 * (TX_EQ_OVR_RIDE) = 1'b1, Bit[5:0](TX_EQ_POST) = 6'd36
-		 */
-		value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
-		value = (value & ~0x7F) | 16 | (1 << 6);
-		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+
 		if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 ||
 			hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) {
 			wr32_epcs(hw, TXGBE_PHY_RX_EQ_CTL0, 0x774F);
@@ -2123,6 +2134,15 @@  txgbe_set_link_to_sfi(struct txgbe_hw *hw,
 		goto out;
 	}
 
+	if (hw->fw_version <= TXGBE_FW_N_TXEQ) {
+		value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0);
+		value = (value & ~0x3F3F) | (24 << 8) | 4;
+		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL0, value);
+
+		value = rd32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1);
+		value = (value & ~0x7F) | 16 | (1 << 6);
+		wr32_epcs(hw, TXGBE_PHY_TX_EQ_CTL1, value);
+	}
 out:
 	return err;
 }
@@ -2133,13 +2153,15 @@  txgbe_set_link_to_sfi(struct txgbe_hw *hw,
  */
 u64 txgbe_autoc_read(struct txgbe_hw *hw)
 {
-	u64 autoc = 0;
+	u64 autoc;
 	u32 sr_pcs_ctl;
 	u32 sr_pma_ctl1;
 	u32 sr_an_ctl;
 	u32 sr_an_adv_reg2;
 	u8 type = hw->subsystem_device_id & 0xFF;
 
+	autoc = hw->mac.autoc;
+
 	if (hw->phy.multispeed_fiber) {
 		autoc |= TXGBE_AUTOC_LMS_10G;
 	} else if (type == TXGBE_DEV_ID_SFP) {
@@ -2195,11 +2217,11 @@  u64 txgbe_autoc_read(struct txgbe_hw *hw)
 	} else if ((sr_an_ctl & SR_AN_CTRL_AN_EN)) {
 		/* KX/KX4/KR backplane auto-negotiation enable */
 		if (sr_an_adv_reg2 & SR_AN_MMD_ADV_REG2_BP_TYPE_KR)
-			autoc |= TXGBE_AUTOC_10G_KR;
+			autoc |= TXGBE_AUTOC_KR_SUPP;
 		if (sr_an_adv_reg2 & SR_AN_MMD_ADV_REG2_BP_TYPE_KX4)
-			autoc |= TXGBE_AUTOC_10G_KX4;
+			autoc |= TXGBE_AUTOC_KX4_SUPP;
 		if (sr_an_adv_reg2 & SR_AN_MMD_ADV_REG2_BP_TYPE_KX)
-			autoc |= TXGBE_AUTOC_1G_KX;
+			autoc |= TXGBE_AUTOC_KX_SUPP;
 		autoc |= TXGBE_AUTOC_LMS_KX4_KX_KR;
 		hw->phy.link_mode = TXGBE_PHYSICAL_LAYER_10GBASE_KR |
 				TXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
@@ -2221,7 +2243,7 @@  void txgbe_autoc_write(struct txgbe_hw *hw, u64 autoc)
 	u32 mactxcfg = 0;
 	u8 device_type = hw->subsystem_device_id & 0xFF;
 
-	speed = TXGBE_AUTOC_SPEED(autoc);
+	speed = TXGBD_AUTOC_SPEED(autoc);
 	autoc &= ~TXGBE_AUTOC_SPEED_MASK;
 	autoneg = (autoc & TXGBE_AUTOC_AUTONEG ? true : false);
 	autoc &= ~TXGBE_AUTOC_AUTONEG;
@@ -2241,6 +2263,8 @@  void txgbe_autoc_write(struct txgbe_hw *hw, u64 autoc)
 			default:
 				return;
 			}
+		} else {
+			txgbe_set_link_to_kr(hw, !autoneg);
 		}
 	} else if (device_type == TXGBE_DEV_ID_XAUI ||
 		   device_type == TXGBE_DEV_ID_SGMII ||
@@ -2249,10 +2273,11 @@  void txgbe_autoc_write(struct txgbe_hw *hw, u64 autoc)
 		   (device_type == TXGBE_DEV_ID_SFI_XAUI &&
 		   hw->phy.media_type == txgbe_media_type_copper)) {
 		if (speed == TXGBE_LINK_SPEED_10GB_FULL) {
-			txgbe_set_link_to_kx4(hw, autoneg);
+			txgbe_set_link_to_kx4(hw, 0);
 		} else {
 			txgbe_set_link_to_kx(hw, speed, 0);
-			txgbe_set_sgmii_an37_ability(hw);
+			if (hw->devarg.auto_neg == 1)
+				txgbe_set_sgmii_an37_ability(hw);
 		}
 	} else if (hw->phy.media_type == txgbe_media_type_fiber) {
 		txgbe_set_link_to_sfi(hw, speed);
@@ -2264,6 +2289,8 @@  void txgbe_autoc_write(struct txgbe_hw *hw, u64 autoc)
 		mactxcfg = TXGBE_MACTXCFG_SPEED_1G;
 
 	/* enable mac transmitter */
-	wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_SPEED_MASK, mactxcfg);
+	wr32m(hw, TXGBE_MACTXCFG,
+		TXGBE_MACTXCFG_SPEED_MASK | TXGBE_MACTXCFG_TXE,
+		mactxcfg | TXGBE_MACTXCFG_TXE);
 }
 
diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h
index 4a5b90077..b804d2406 100644
--- a/drivers/net/txgbe/base/txgbe_phy.h
+++ b/drivers/net/txgbe/base/txgbe_phy.h
@@ -18,11 +18,27 @@ 
 #define   SR_PCS_CTRL2_TYPE_SEL_R       LS16(0, 0, 0x3)
 #define   SR_PCS_CTRL2_TYPE_SEL_X       LS16(1, 0, 0x3)
 #define   SR_PCS_CTRL2_TYPE_SEL_W       LS16(2, 0, 0x3)
+#define SR_XS_PCS_KR_STS1		0x030020
+#define   SR_XS_PCS_KR_STS1_PLU		MS16(12, 0x1)
 #define SR_PMA_CTRL1                    0x010000
 #define   SR_PMA_CTRL1_SS13             MS16(13, 0x1)
 #define   SR_PMA_CTRL1_SS13_KX          LS16(0, 13, 0x1)
 #define   SR_PMA_CTRL1_SS13_KX4         LS16(1, 13, 0x1)
 #define   SR_PMA_CTRL1_LB               MS16(0, 0x1)
+#define SR_PMA_KR_PMD_CTRL		0x010096
+#define   SR_PMA_KR_PMD_CTRL_EN_TR	MS16(1, 0x1)
+#define   SR_PMA_KR_PMD_CTRL_RS_TR	MS16(0, 0x1)
+#define SR_PMA_KR_PMD_STS		0x010097
+#define   SR_PMA_KR_PMD_STS_TR_FAIL	MS16(3, 0x1)
+#define   SR_PMA_KR_PMD_STS_RCV		MS16(0, 0x1)
+#define SR_PMA_KR_LP_CEU		0x010098
+#define SR_PMA_KR_LP_CESTS		0x010099
+#define   SR_PMA_KR_LP_CESTS_RR		MS16(15, 0x1)
+#define SR_PMA_KR_LD_CEU		0x01009A
+#define SR_PMA_KR_LD_CESTS		0x01009B
+#define   SR_PMA_KR_LD_CESTS_RR		MS16(15, 0x1)
+#define SR_PMA_KR_FEC_CTRL              0x0100AB
+#define   SR_PMA_KR_FEC_CTRL_EN		MS16(0, 0x1)
 #define SR_MII_MMD_CTL                  0x1F0000
 #define   SR_MII_MMD_CTL_AN_EN              0x1000
 #define   SR_MII_MMD_CTL_RESTART_AN         0x0200
@@ -33,26 +49,80 @@ 
 #define   SR_MII_MMD_AN_ADV_PAUSE_ASM   0x80
 #define   SR_MII_MMD_AN_ADV_PAUSE_SYM   0x100
 #define SR_MII_MMD_LP_BABL              0x1F0005
+
+#define BP_TYPE_KX		0x20
+#define BP_TYPE_KX4		0x40
+#define BP_TYPE_KX4_KX		0x60
+#define BP_TYPE_KR		0x80
+#define BP_TYPE_KR_KX		0xA0
+#define BP_TYPE_KR_KX4		0xC0
+#define BP_TYPE_KR_KX4_KX	0xE0
+
 #define SR_AN_CTRL                      0x070000
 #define   SR_AN_CTRL_RSTRT_AN           MS16(9, 0x1)
 #define   SR_AN_CTRL_AN_EN              MS16(12, 0x1)
+#define   SR_AN_CTRL_EXT_NP             MS16(13, 0x1)
 #define SR_AN_MMD_ADV_REG1                0x070010
 #define   SR_AN_MMD_ADV_REG1_PAUSE(v)      ((0x3 & (v)) << 10)
 #define   SR_AN_MMD_ADV_REG1_PAUSE_SYM      0x400
 #define   SR_AN_MMD_ADV_REG1_PAUSE_ASM      0x800
-#define SR_AN_MMD_ADV_REG2                0x070011
-#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KX4    0x40
-#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KX     0x20
-#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KR     0x80
-#define   SR_AN_MMD_ADV_REG2_BP_TYPE_MASK   0xFFFF
+#define   SR_AN_MMD_ADV_REG1_NP(v)	  RS16(v, 15, 0x1)
+#define SR_AN_MMD_ADV_REG2		  0x070011
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KX4	BP_TYPE_KX4
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KX		BP_TYPE_KX
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KR		BP_TYPE_KR
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KX4_KX	BP_TYPE_KX4_KX
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KR_KX	BP_TYPE_KR_KX
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KR_KX4	BP_TYPE_KR_KX4
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_KR_KX4_KX	BP_TYPE_KR_KX4_KX
+#define   SR_AN_MMD_ADV_REG2_BP_TYPE_MASK	0xFFFF
+#define SR_AN_MMD_ADV_REG3                0x070012
+#define   SR_AN_MMD_ADV_REG3_FCE(v)	  RS16(v, 14, 0x3)
 #define SR_AN_MMD_LP_ABL1                 0x070013
+#define   SR_MMD_LP_ABL1_ADV_NP(v)	  RS16(v, 15, 0x1)
+#define SR_AN_MMD_LP_ABL2		  0x070014
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_KX4		BP_TYPE_KX4
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_KX		BP_TYPE_KX
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_KR		BP_TYPE_KR
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_KX4_KX	BP_TYPE_KX4_KX
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_KR_KX	BP_TYPE_KR_KX
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_KR_KX4	BP_TYPE_KR_KX4
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_KR_KX4_KX	BP_TYPE_KR_KX4_KX
+#define   SR_AN_MMD_LP_ABL2_BP_TYPE_MASK	0xFFFF
+#define SR_AN_MMD_LP_ABL3		  0x070015
+#define   SR_AN_MMD_LP_ABL3_FCE(v)	  RS16(v, 14, 0x3)
+#define SR_AN_XNP_TX1			  0x070016
+#define   SR_AN_XNP_TX1_NP		  MS16(15, 0x1)
+#define SR_AN_LP_XNP_ABL1		  0x070019
+#define   SR_AN_LP_XNP_ABL1_NP(v)	  RS16(v, 15, 0x1)
+
+#define VR_AN_INTR_MSK			  0x078001
+#define   VR_AN_INTR_CMPLT_IE		  MS16(0, 0x1)
+#define   VR_AN_INTR_LINK_IE		  MS16(1, 0x1)
+#define   VR_AN_INTR_PG_RCV_IE		  MS16(2, 0x1)
+#define VR_AN_INTR			  0x078002
+#define   VR_AN_INTR_CMPLT		  MS16(0, 0x1)
+#define   VR_AN_INTR_LINK		  MS16(1, 0x1)
+#define   VR_AN_INTR_PG_RCV		  MS16(2, 0x1)
 #define VR_AN_KR_MODE_CL                  0x078003
+#define   VR_AN_KR_MODE_CL_PDET		  MS16(0, 0x1)
 #define VR_XS_OR_PCS_MMD_DIGI_CTL1        0x038000
 #define   VR_XS_OR_PCS_MMD_DIGI_CTL1_ENABLE 0x1000
 #define   VR_XS_OR_PCS_MMD_DIGI_CTL1_VR_RST 0x8000
+#define VR_XS_OR_PCS_MMD_DIGI_CTL2        0x038001
 #define VR_XS_OR_PCS_MMD_DIGI_STATUS      0x038010
 #define   VR_XS_OR_PCS_MMD_DIGI_STATUS_PSEQ_MASK            0x1C
 #define   VR_XS_OR_PCS_MMD_DIGI_STATUS_PSEQ_POWER_GOOD      0x10
+#define VR_PMA_KRTR_PRBS_CTRL0		  0x018003
+#define   VR_PMA_KRTR_PRBS31_EN		  MS16(1, 0x1)
+#define   VR_PMA_KRTR_PRBS_MODE_EN	  MS16(0, 0x1)
+#define VR_PMA_KRTR_PRBS_CTRL1		  0x018004
+#define   VR_PMA_KRTR_PRBS_TIME_LMT	  MS16(0, 0xFFFF)
+#define VR_PMA_KRTR_PRBS_CTRL2		  0x018005
+#define   VR_PMA_KRTR_PRBS_ERR_LIM	  MS16(0, 0x2FFF)
+#define VR_PMA_KRTR_TIMER_CTRL0		  0x018006
+#define   VR_PMA_KRTR_TIMER_MAX_WAIT	  MS16(0, 0xFFFF)
+#define VR_PMA_KRTR_TIMER_CTRL2		  0x018008
 
 #define TXGBE_PHY_MPLLA_CTL0                    0x018071
 #define TXGBE_PHY_MPLLA_CTL3                    0x018077
@@ -71,6 +141,7 @@ 
 #define TXGBE_PHY_RX_EQ_CTL                     0x01805C
 #define TXGBE_PHY_TX_EQ_CTL0                    0x018036
 #define TXGBE_PHY_TX_EQ_CTL1                    0x018037
+#define   TXGBE_PHY_TX_EQ_CTL1_DEF		MS16(7, 0x1)
 #define TXGBE_PHY_TX_RATE_CTL                   0x018034
 #define TXGBE_PHY_RX_RATE_CTL                   0x018054
 #define TXGBE_PHY_TX_GEN_CTL2                   0x018032
@@ -80,12 +151,14 @@ 
 #define TXGBE_PHY_RX_POWER_ST_CTL               0x018055
 #define TXGBE_PHY_TX_POWER_ST_CTL               0x018035
 #define TXGBE_PHY_TX_GENCTRL1                   0x018031
+#define TXGBE_PHY_EQ_INIT_CTL0			0x01803A
+#define TXGBE_PHY_EQ_INIT_CTL1			0x01803B
 
 #define TXGBE_PHY_MPLLA_CTL0_MULTIPLIER_1GBASEX_KX              32
 #define TXGBE_PHY_MPLLA_CTL0_MULTIPLIER_10GBASER_KR             33
 #define TXGBE_PHY_MPLLA_CTL0_MULTIPLIER_OTHER                   40
 #define TXGBE_PHY_MPLLA_CTL0_MULTIPLIER_MASK                    0xFF
-#define TXGBE_PHY_MPLLA_CTL3_MULTIPLIER_BW_1GBASEX_KX           0x46
+#define TXGBE_PHY_MPLLA_CTL3_MULTIPLIER_BW_1GBASEX_KX           0x56
 #define TXGBE_PHY_MPLLA_CTL3_MULTIPLIER_BW_10GBASER_KR          0x7B
 #define TXGBE_PHY_MPLLA_CTL3_MULTIPLIER_BW_OTHER                0x56
 #define TXGBE_PHY_MPLLA_CTL3_MULTIPLIER_BW_MASK                 0x7FF
@@ -151,6 +224,11 @@ 
 #define TXGBE_PHY_MPLLA_CTL2_DIV_CLK_EN_10                      0x200
 #define TXGBE_PHY_MPLLA_CTL2_DIV_CLK_EN_16P5                    0x400
 #define TXGBE_PHY_MPLLA_CTL2_DIV_CLK_EN_MASK                    0x700
+#define TXGBE_PHY_LANE0_TX_EQ_CTL1				0x100E
+#define   TXGBE_PHY_LANE0_TX_EQ_CTL1_MAIN(v)			RS16(v, 6, 0x3F)
+#define TXGBE_PHY_LANE0_TX_EQ_CTL2				0x100F
+#define   TXGBE_PHY_LANE0_TX_EQ_CTL2_PRE			MS16(0, 0x3F)
+#define   TXGBE_PHY_LANE0_TX_EQ_CTL2_POST(v)			RS16(v, 6, 0x3F)
 
 /******************************************************************************
  * SFP I2C Registers:
diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h
index 40c551697..33572cc3c 100644
--- a/drivers/net/txgbe/base/txgbe_type.h
+++ b/drivers/net/txgbe/base/txgbe_type.h
@@ -617,9 +617,10 @@  struct txgbe_mac_info {
 	u32 rx_pb_size;
 	u32 max_tx_queues;
 	u32 max_rx_queues;
+	u64 autoc;
+	u64 orig_autoc;  /* cached value of AUTOC */
 	u8  san_mac_rar_index;
 	bool get_link_status;
-	u64 orig_autoc;  /* cached value of AUTOC */
 	bool orig_link_settings_stored;
 	bool autotry_restart;
 	u8 flags;
@@ -685,6 +686,18 @@  struct txgbe_phy_info {
 	u32 link_mode;
 };
 
+#define TXGBE_DEVARG_BP_AUTO		"auto_neg"
+#define TXGBE_DEVARG_KR_POLL		"poll"
+#define TXGBE_DEVARG_KR_PRESENT		"present"
+#define TXGBE_DEVARG_KX_SGMII		"sgmii"
+
+static const char * const txgbe_valid_arguments[] = {
+	TXGBE_DEVARG_BP_AUTO,
+	TXGBE_DEVARG_KR_POLL,
+	TXGBE_DEVARG_KR_PRESENT,
+	TXGBE_DEVARG_KX_SGMII,
+};
+
 struct txgbe_mbx_stats {
 	u32 msgs_tx;
 	u32 msgs_rx;
@@ -721,6 +734,13 @@  enum txgbe_isb_idx {
 	TXGBE_ISB_MAX
 };
 
+struct txgbe_devargs {
+	u16 auto_neg;
+	u16 poll;
+	u16 present;
+	u16 sgmii;
+};
+
 struct txgbe_hw {
 	void IOMEM *hw_addr;
 	void *back;
@@ -742,6 +762,7 @@  struct txgbe_hw {
 	int api_version;
 	bool allow_unsupported_sfp;
 	bool need_crosstalk_fix;
+	struct txgbe_devargs devarg;
 
 	uint64_t isb_dma;
 	void IOMEM *isb_mem;
diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c
index 2a59a139c..447a511ca 100644
--- a/drivers/net/txgbe/txgbe_ethdev.c
+++ b/drivers/net/txgbe/txgbe_ethdev.c
@@ -16,6 +16,7 @@ 
 #include <rte_memory.h>
 #include <rte_eal.h>
 #include <rte_alarm.h>
+#include <rte_kvargs.h>
 
 #include "txgbe_logs.h"
 #include "base/txgbe.h"
@@ -469,6 +470,55 @@  txgbe_swfw_lock_reset(struct txgbe_hw *hw)
 	hw->mac.release_swfw_sync(hw, mask);
 }
 
+static int
+txgbe_handle_devarg(__rte_unused const char *key, const char *value,
+		  void *extra_args)
+{
+	uint16_t *n = extra_args;
+
+	if (value == NULL || extra_args == NULL)
+		return -EINVAL;
+
+	*n = (uint16_t)strtoul(value, NULL, 10);
+	if (*n == USHRT_MAX && errno == ERANGE)
+		return -1;
+
+	return 0;
+}
+
+static void
+txgbe_parse_devargs(struct txgbe_hw *hw, struct rte_devargs *devargs)
+{
+	struct rte_kvargs *kvlist;
+	u16 auto_neg = 1;
+	u16 poll = 0;
+	u16 present = 1;
+	u16 sgmii = 0;
+
+	if (devargs == NULL)
+		goto null;
+
+	kvlist = rte_kvargs_parse(devargs->args, txgbe_valid_arguments);
+	if (kvlist == NULL)
+		goto null;
+
+	rte_kvargs_process(kvlist, TXGBE_DEVARG_BP_AUTO,
+			   &txgbe_handle_devarg, &auto_neg);
+	rte_kvargs_process(kvlist, TXGBE_DEVARG_KR_POLL,
+			   &txgbe_handle_devarg, &poll);
+	rte_kvargs_process(kvlist, TXGBE_DEVARG_KR_PRESENT,
+			   &txgbe_handle_devarg, &present);
+	rte_kvargs_process(kvlist, TXGBE_DEVARG_KX_SGMII,
+			   &txgbe_handle_devarg, &sgmii);
+	rte_kvargs_free(kvlist);
+
+null:
+	hw->devarg.auto_neg = auto_neg;
+	hw->devarg.poll = poll;
+	hw->devarg.present = present;
+	hw->devarg.sgmii = sgmii;
+}
+
 static int
 eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 {
@@ -537,6 +587,7 @@  eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused)
 	hw->isb_dma = TMZ_PADDR(mz);
 	hw->isb_mem = TMZ_VADDR(mz);
 
+	txgbe_parse_devargs(hw, pci_dev->device.devargs);
 	/* Initialize the shared code (base driver) */
 	err = txgbe_init_shared_code(hw);
 	if (err != 0) {
@@ -5234,9 +5285,15 @@  static const struct eth_dev_ops txgbe_eth_dev_ops = {
 RTE_PMD_REGISTER_PCI(net_txgbe, rte_txgbe_pmd);
 RTE_PMD_REGISTER_PCI_TABLE(net_txgbe, pci_id_txgbe_map);
 RTE_PMD_REGISTER_KMOD_DEP(net_txgbe, "* igb_uio | uio_pci_generic | vfio-pci");
+RTE_PMD_REGISTER_PARAM_STRING(net_txgbe,
+			      TXGBE_DEVARG_BP_AUTO "=<0|1>"
+			      TXGBE_DEVARG_KR_POLL "=<0|1>"
+			      TXGBE_DEVARG_KR_PRESENT "=<0|1>"
+			      TXGBE_DEVARG_KX_SGMII "=<0|1>");
 
 RTE_LOG_REGISTER(txgbe_logtype_init, pmd.net.txgbe.init, NOTICE);
 RTE_LOG_REGISTER(txgbe_logtype_driver, pmd.net.txgbe.driver, NOTICE);
+RTE_LOG_REGISTER(txgbe_logtype_bp, pmd.net.txgbe.bp, NOTICE);
 
 #ifdef RTE_LIBRTE_TXGBE_DEBUG_RX
 	RTE_LOG_REGISTER(txgbe_logtype_rx, pmd.net.txgbe.rx, DEBUG);
diff --git a/drivers/net/txgbe/txgbe_logs.h b/drivers/net/txgbe/txgbe_logs.h
index f44ca06ee..6764466e2 100644
--- a/drivers/net/txgbe/txgbe_logs.h
+++ b/drivers/net/txgbe/txgbe_logs.h
@@ -5,6 +5,8 @@ 
 #ifndef _TXGBE_LOGS_H_
 #define _TXGBE_LOGS_H_
 
+#include <inttypes.h>
+
 /*
  * PMD_USER_LOG: for user
  */
@@ -51,4 +53,11 @@  extern int txgbe_logtype_tx_free;
 #define PMD_INIT_FUNC_TRACE()     TLOG_DEBUG(" >>")
 #define DEBUGFUNC(fmt)            TLOG_DEBUG(fmt)
 
+extern int txgbe_logtype_bp;
+#define BP_LOG(fmt, args...) \
+	rte_log(RTE_LOG_DEBUG, txgbe_logtype_bp, \
+		"[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \
+		usec_stamp() / 1000000, usec_stamp() % 1000000, \
+		__func__, __LINE__, ##args)
+
 #endif /* _TXGBE_LOGS_H_ */