@@ -84,6 +84,35 @@ TXGBE PMD provides the following log types available for control:
Extra logging of the messages during PMD initialization.
+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
------------------------------
@@ -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
@@ -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, ®_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, ®_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;
@@ -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
@@ -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);
}
@@ -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:
@@ -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;
@@ -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,6 +5285,11 @@ 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);
@@ -51,4 +51,14 @@ extern int txgbe_logtype_tx_free;
#define PMD_INIT_FUNC_TRACE() TLOG_DEBUG(" >>")
#define DEBUGFUNC(fmt) TLOG_DEBUG(fmt)
+#define TXGBE_DEBUG_BP
+#ifdef TXGBE_DEBUG_BP
+#define BP_LOG(fmt, ...) \
+ RTE_LOG(CRIT, PMD, "[%lu.%lu]%s(%d): " fmt, \
+ usec_stamp() / 1000000, usec_stamp() % 1000000, \
+ __func__, __LINE__, ## __VA_ARGS__)
+#else
+#define BP_LOG(fmt, ...) do { } while (0)
+#endif
+
#endif /* _TXGBE_LOGS_H_ */