#include "txgbe_mbx.h"
#include "txgbe_phy.h"
#include "txgbe_dcb.h"
+#include "txgbe_vf.h"
#include "txgbe_eeprom.h"
#include "txgbe_mng.h"
#include "txgbe_hw.h"
break;
case txgbe_media_type_copper:
/* only some copper devices support flow control autoneg */
- switch (hw->device_id) {
- case TXGBE_DEV_ID_RAPTOR_XAUI:
- case TXGBE_DEV_ID_RAPTOR_SGMII:
+ switch (hw->subsystem_device_id & 0xFF) {
+ case TXGBE_DEV_ID_XAUI:
+ case TXGBE_DEV_ID_SGMII:
supported = true;
break;
default:
u16 reg_cu = 0;
u32 value = 0;
u64 reg_bp = 0;
- bool locked = false;
DEBUGFUNC("txgbe_setup_fc");
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
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:
/*
* 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:
*/
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 |
DEBUGFUNC("txgbe_init_hw");
+ /* Get firmware version */
+ hw->phy.get_fw_version(hw, &hw->fw_version);
+
/* Reset the hardware */
status = hw->mac.reset_hw(hw);
if (status == 0 || status == TXGBE_ERR_SFP_NOT_PRESENT) {
return 0;
}
+/**
+ * txgbe_led_on - Turns on the software controllable LEDs.
+ * @hw: pointer to hardware structure
+ * @index: led number to turn on
+ **/
+s32 txgbe_led_on(struct txgbe_hw *hw, u32 index)
+{
+ u32 led_reg = rd32(hw, TXGBE_LEDCTL);
+
+ DEBUGFUNC("txgbe_led_on");
+
+ if (index > 4)
+ return TXGBE_ERR_PARAM;
+
+ /* To turn on the LED, set mode to ON. */
+ led_reg |= TXGBE_LEDCTL_SEL(index);
+ led_reg |= TXGBE_LEDCTL_ORD(index);
+ wr32(hw, TXGBE_LEDCTL, led_reg);
+ txgbe_flush(hw);
+
+ return 0;
+}
+
+/**
+ * txgbe_led_off - Turns off the software controllable LEDs.
+ * @hw: pointer to hardware structure
+ * @index: led number to turn off
+ **/
+s32 txgbe_led_off(struct txgbe_hw *hw, u32 index)
+{
+ u32 led_reg = rd32(hw, TXGBE_LEDCTL);
+
+ DEBUGFUNC("txgbe_led_off");
+
+ if (index > 4)
+ return TXGBE_ERR_PARAM;
+
+ /* To turn off the LED, set mode to OFF. */
+ led_reg &= ~(TXGBE_LEDCTL_SEL(index));
+ led_reg &= ~(TXGBE_LEDCTL_ORD(index));
+ wr32(hw, TXGBE_LEDCTL, led_reg);
+ txgbe_flush(hw);
+
+ return 0;
+}
+
/**
* txgbe_validate_mac_addr - Validate MAC address
* @mac_addr: pointer to MAC address.
return err;
}
+/**
+ * txgbe_negotiate_fc - Negotiate flow control
+ * @hw: pointer to hardware structure
+ * @adv_reg: flow control advertised settings
+ * @lp_reg: link partner's flow control settings
+ * @adv_sym: symmetric pause bit in advertisement
+ * @adv_asm: asymmetric pause bit in advertisement
+ * @lp_sym: symmetric pause bit in link partner advertisement
+ * @lp_asm: asymmetric pause bit in link partner advertisement
+ *
+ * Find the intersection between advertised settings and link partner's
+ * advertised settings
+ **/
+s32 txgbe_negotiate_fc(struct txgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+ u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
+{
+ if ((!(adv_reg)) || (!(lp_reg))) {
+ DEBUGOUT("Local or link partner's advertised flow control "
+ "settings are NULL. Local: %x, link partner: %x\n",
+ adv_reg, lp_reg);
+ return TXGBE_ERR_FC_NOT_NEGOTIATED;
+ }
+
+ if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
+ /*
+ * Now we need to check if the user selected Rx ONLY
+ * of pause frames. In this case, we had to advertise
+ * FULL flow control because we could not advertise RX
+ * ONLY. Hence, we must now check to see if we need to
+ * turn OFF the TRANSMISSION of PAUSE frames.
+ */
+ if (hw->fc.requested_mode == txgbe_fc_full) {
+ hw->fc.current_mode = txgbe_fc_full;
+ DEBUGOUT("Flow Control = FULL.\n");
+ } else {
+ hw->fc.current_mode = txgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control=RX PAUSE frames only\n");
+ }
+ } else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ hw->fc.current_mode = txgbe_fc_tx_pause;
+ DEBUGOUT("Flow Control = TX PAUSE frames only.\n");
+ } else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+ !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+ hw->fc.current_mode = txgbe_fc_rx_pause;
+ DEBUGOUT("Flow Control = RX PAUSE frames only.\n");
+ } else {
+ hw->fc.current_mode = txgbe_fc_none;
+ DEBUGOUT("Flow Control = NONE.\n");
+ }
+ return 0;
+}
+
+/**
+ * txgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
+ * @hw: pointer to hardware structure
+ *
+ * Enable flow control according on 1 gig fiber.
+ **/
+STATIC s32 txgbe_fc_autoneg_fiber(struct txgbe_hw *hw)
+{
+ u32 pcs_anadv_reg, pcs_lpab_reg;
+ s32 err = TXGBE_ERR_FC_NOT_NEGOTIATED;
+
+ /*
+ * On multispeed fiber at 1g, bail out if
+ * - link is up but AN did not complete, or if
+ * - link is up and AN completed but timed out
+ */
+
+ pcs_anadv_reg = rd32_epcs(hw, SR_MII_MMD_AN_ADV);
+ pcs_lpab_reg = rd32_epcs(hw, SR_MII_MMD_LP_BABL);
+
+ err = txgbe_negotiate_fc(hw, pcs_anadv_reg,
+ pcs_lpab_reg,
+ SR_MII_MMD_AN_ADV_PAUSE_SYM,
+ SR_MII_MMD_AN_ADV_PAUSE_ASM,
+ SR_MII_MMD_AN_ADV_PAUSE_SYM,
+ SR_MII_MMD_AN_ADV_PAUSE_ASM);
+
+ return err;
+}
+
+/**
+ * txgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37
+ * @hw: pointer to hardware structure
+ *
+ * Enable flow control according to IEEE clause 37.
+ **/
+STATIC s32 txgbe_fc_autoneg_backplane(struct txgbe_hw *hw)
+{
+ u32 anlp1_reg, autoc_reg;
+ s32 err = TXGBE_ERR_FC_NOT_NEGOTIATED;
+
+ /*
+ * Read the 10g AN autoc and LP ability registers and resolve
+ * local flow control settings accordingly
+ */
+ autoc_reg = rd32_epcs(hw, SR_AN_MMD_ADV_REG1);
+ anlp1_reg = rd32_epcs(hw, SR_AN_MMD_LP_ABL1);
+
+ err = txgbe_negotiate_fc(hw, autoc_reg,
+ anlp1_reg,
+ SR_AN_MMD_ADV_REG1_PAUSE_SYM,
+ SR_AN_MMD_ADV_REG1_PAUSE_ASM,
+ SR_AN_MMD_ADV_REG1_PAUSE_SYM,
+ SR_AN_MMD_ADV_REG1_PAUSE_ASM);
+
+ return err;
+}
+
+/**
+ * txgbe_fc_autoneg_copper - Enable flow control IEEE clause 37
+ * @hw: pointer to hardware structure
+ *
+ * Enable flow control according to IEEE clause 37.
+ **/
+STATIC s32 txgbe_fc_autoneg_copper(struct txgbe_hw *hw)
+{
+ u16 technology_ability_reg = 0;
+ u16 lp_technology_ability_reg = 0;
+
+ hw->phy.read_reg(hw, TXGBE_MD_AUTO_NEG_ADVT,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &technology_ability_reg);
+ hw->phy.read_reg(hw, TXGBE_MD_AUTO_NEG_LP,
+ TXGBE_MD_DEV_AUTO_NEG,
+ &lp_technology_ability_reg);
+
+ return txgbe_negotiate_fc(hw, (u32)technology_ability_reg,
+ (u32)lp_technology_ability_reg,
+ TXGBE_TAF_SYM_PAUSE, TXGBE_TAF_ASM_PAUSE,
+ TXGBE_TAF_SYM_PAUSE, TXGBE_TAF_ASM_PAUSE);
+}
+
+/**
+ * txgbe_fc_autoneg - Configure flow control
+ * @hw: pointer to hardware structure
+ *
+ * Compares our advertised flow control capabilities to those advertised by
+ * our link partner, and determines the proper flow control mode to use.
+ **/
+void txgbe_fc_autoneg(struct txgbe_hw *hw)
+{
+ s32 err = TXGBE_ERR_FC_NOT_NEGOTIATED;
+ u32 speed;
+ bool link_up;
+
+ DEBUGFUNC("txgbe_fc_autoneg");
+
+ /*
+ * AN should have completed when the cable was plugged in.
+ * Look for reasons to bail out. Bail out if:
+ * - FC autoneg is disabled, or if
+ * - link is not up.
+ */
+ if (hw->fc.disable_fc_autoneg) {
+ DEBUGOUT("Flow control autoneg is disabled");
+ goto out;
+ }
+
+ hw->mac.check_link(hw, &speed, &link_up, false);
+ if (!link_up) {
+ DEBUGOUT("The link is down");
+ goto out;
+ }
+
+ switch (hw->phy.media_type) {
+ /* Autoneg flow control on fiber adapters */
+ case txgbe_media_type_fiber_qsfp:
+ case txgbe_media_type_fiber:
+ if (speed == TXGBE_LINK_SPEED_1GB_FULL)
+ err = txgbe_fc_autoneg_fiber(hw);
+ break;
+
+ /* Autoneg flow control on backplane adapters */
+ case txgbe_media_type_backplane:
+ err = txgbe_fc_autoneg_backplane(hw);
+ break;
+
+ /* Autoneg flow control on copper adapters */
+ case txgbe_media_type_copper:
+ if (txgbe_device_supports_autoneg_fc(hw))
+ err = txgbe_fc_autoneg_copper(hw);
+ break;
+
+ default:
+ break;
+ }
+
+out:
+ if (err == 0) {
+ hw->fc.fc_was_autonegged = true;
+ } else {
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ }
+}
+
/**
* txgbe_acquire_swfw_sync - Acquire SWFW semaphore
* @hw: pointer to hardware structure
case txgbe_mac_raptor:
status = txgbe_init_ops_pf(hw);
break;
+ case txgbe_mac_raptor_vf:
+ status = txgbe_init_ops_vf(hw);
+ break;
default:
status = TXGBE_ERR_DEVICE_NOT_SUPPORTED;
break;
}
switch (hw->device_id) {
- case TXGBE_DEV_ID_RAPTOR_KR_KX_KX4:
- hw->phy.media_type = txgbe_media_type_backplane;
+ case TXGBE_DEV_ID_SP1000:
+ case TXGBE_DEV_ID_WX1820:
hw->mac.type = txgbe_mac_raptor;
break;
- case TXGBE_DEV_ID_RAPTOR_XAUI:
- case TXGBE_DEV_ID_RAPTOR_SGMII:
- hw->phy.media_type = txgbe_media_type_copper;
- hw->mac.type = txgbe_mac_raptor;
- break;
- case TXGBE_DEV_ID_RAPTOR_SFP:
- case TXGBE_DEV_ID_WX1820_SFP:
- hw->phy.media_type = txgbe_media_type_fiber;
- hw->mac.type = txgbe_mac_raptor;
- break;
- case TXGBE_DEV_ID_RAPTOR_QSFP:
- hw->phy.media_type = txgbe_media_type_fiber_qsfp;
- hw->mac.type = txgbe_mac_raptor;
- break;
- case TXGBE_DEV_ID_RAPTOR_VF:
- case TXGBE_DEV_ID_RAPTOR_VF_HV:
+ case TXGBE_DEV_ID_SP1000_VF:
+ case TXGBE_DEV_ID_WX1820_VF:
hw->phy.media_type = txgbe_media_type_virtual;
hw->mac.type = txgbe_mac_raptor_vf;
break;
break;
}
- DEBUGOUT("found mac: %d media: %d, returns: %d\n",
- hw->mac.type, hw->phy.media_type, err);
+ DEBUGOUT("found mac: %d, returns: %d\n",
+ hw->mac.type, err);
return err;
}
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;
}
}
DEBUGFUNC("txgbe_init_phy_raptor");
- if (hw->device_id == TXGBE_DEV_ID_RAPTOR_QSFP) {
+ if ((hw->device_id & 0xFF) == TXGBE_DEV_ID_QSFP) {
/* Store flag indicating I2C bus access control unit. */
hw->phy.qsfp_shared_i2c_bus = TRUE;
txgbe_get_copper_link_capabilities;
}
+ if (phy->media_type == txgbe_media_type_backplane) {
+ mac->kr_handle = txgbe_kr_handle;
+ mac->bp_down_event = txgbe_bp_down_event;
+ }
+
/* Set necessary function pointers based on PHY type */
switch (hw->phy.type) {
case txgbe_phy_tn:
phy->write_reg_mdi = txgbe_write_phy_reg_mdi;
phy->setup_link = txgbe_setup_phy_link;
phy->setup_link_speed = txgbe_setup_phy_link_speed;
+ phy->get_fw_version = txgbe_get_phy_fw_version;
phy->read_i2c_byte = txgbe_read_i2c_byte;
phy->write_i2c_byte = txgbe_write_i2c_byte;
+ phy->read_i2c_sff8472 = txgbe_read_i2c_sff8472;
phy->read_i2c_eeprom = txgbe_read_i2c_eeprom;
phy->write_i2c_eeprom = txgbe_write_i2c_eeprom;
+ phy->identify_sfp = txgbe_identify_module;
+ phy->read_i2c_byte_unlocked = txgbe_read_i2c_byte_unlocked;
+ phy->write_i2c_byte_unlocked = txgbe_write_i2c_byte_unlocked;
phy->reset = txgbe_reset_phy;
/* MAC */
mac->acquire_swfw_sync = txgbe_acquire_swfw_sync;
mac->release_swfw_sync = txgbe_release_swfw_sync;
mac->reset_hw = txgbe_reset_hw;
+ mac->update_mc_addr_list = txgbe_update_mc_addr_list;
mac->disable_sec_rx_path = txgbe_disable_sec_rx_path;
mac->enable_sec_rx_path = txgbe_enable_sec_rx_path;
/* Flow Control */
mac->fc_enable = txgbe_fc_enable;
mac->setup_fc = txgbe_setup_fc;
+ mac->fc_autoneg = txgbe_fc_autoneg;
/* Link */
mac->get_link_capabilities = txgbe_get_link_capabilities_raptor;
DEBUGFUNC("txgbe_get_media_type_raptor");
+ if (hw->phy.ffe_set)
+ txgbe_bp_mode_set(hw);
+
/* Detect if there is a copper PHY attached. */
switch (hw->phy.type) {
case txgbe_phy_cu_unknown:
break;
}
- switch (hw->device_id) {
- case TXGBE_DEV_ID_RAPTOR_KR_KX_KX4:
+ switch (hw->subsystem_device_id & 0xFF) {
+ case TXGBE_DEV_ID_KR_KX_KX4:
+ case TXGBE_DEV_ID_MAC_SGMII:
+ case TXGBE_DEV_ID_MAC_XAUI:
/* Default device ID is mezzanine card KX/KX4 */
media_type = txgbe_media_type_backplane;
break;
- case TXGBE_DEV_ID_RAPTOR_SFP:
- case TXGBE_DEV_ID_WX1820_SFP:
+ case TXGBE_DEV_ID_SFP:
media_type = txgbe_media_type_fiber;
break;
- case TXGBE_DEV_ID_RAPTOR_QSFP:
+ case TXGBE_DEV_ID_QSFP:
media_type = txgbe_media_type_fiber_qsfp;
break;
- case TXGBE_DEV_ID_RAPTOR_XAUI:
- case TXGBE_DEV_ID_RAPTOR_SGMII:
+ case TXGBE_DEV_ID_XAUI:
+ case TXGBE_DEV_ID_SGMII:
media_type = txgbe_media_type_copper;
break;
+ case TXGBE_DEV_ID_SFI_XAUI:
+ if (hw->bus.lan_id == 0)
+ media_type = txgbe_media_type_fiber;
+ else
+ media_type = txgbe_media_type_copper;
+ break;
default:
media_type = txgbe_media_type_unknown;
break;
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,
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)
}
}
- 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);
/* 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);
}
*/
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;
}
+ if (hw->phy.ffe_set) {
+ /* Make sure phy power is up */
+ msec_delay(50);
+
+ /* A temporary solution to set phy */
+ txgbe_set_phy_temp(hw);
+ }
+
/* Store the permanent mac address */
hw->mac.get_mac_addr(hw, hw->mac.perm_addr);
return status;
}
+/**
+ * txgbe_fdir_check_cmd_complete - poll to check whether FDIRPICMD is complete
+ * @hw: pointer to hardware structure
+ * @fdircmd: current value of FDIRCMD register
+ */
+static s32 txgbe_fdir_check_cmd_complete(struct txgbe_hw *hw, u32 *fdircmd)
+{
+ int i;
+
+ for (i = 0; i < TXGBE_FDIRCMD_CMD_POLL; i++) {
+ *fdircmd = rd32(hw, TXGBE_FDIRPICMD);
+ if (!(*fdircmd & TXGBE_FDIRPICMD_OP_MASK))
+ return 0;
+ usec_delay(10);
+ }
+
+ return TXGBE_ERR_FDIR_CMD_INCOMPLETE;
+}
+
+/**
+ * txgbe_reinit_fdir_tables - Reinitialize Flow Director tables.
+ * @hw: pointer to hardware structure
+ **/
+s32 txgbe_reinit_fdir_tables(struct txgbe_hw *hw)
+{
+ s32 err;
+ int i;
+ u32 fdirctrl = rd32(hw, TXGBE_FDIRCTL);
+ u32 fdircmd;
+ fdirctrl &= ~TXGBE_FDIRCTL_INITDONE;
+
+ DEBUGFUNC("txgbe_reinit_fdir_tables");
+
+ /*
+ * Before starting reinitialization process,
+ * FDIRPICMD.OP must be zero.
+ */
+ err = txgbe_fdir_check_cmd_complete(hw, &fdircmd);
+ if (err) {
+ DEBUGOUT("Flow Director previous command did not complete, aborting table re-initialization.\n");
+ return err;
+ }
+
+ wr32(hw, TXGBE_FDIRFREE, 0);
+ txgbe_flush(hw);
+ /*
+ * adapters flow director init flow cannot be restarted,
+ * Workaround silicon errata by performing the following steps
+ * before re-writing the FDIRCTL control register with the same value.
+ * - write 1 to bit 8 of FDIRPICMD register &
+ * - write 0 to bit 8 of FDIRPICMD register
+ */
+ wr32m(hw, TXGBE_FDIRPICMD, TXGBE_FDIRPICMD_CLR, TXGBE_FDIRPICMD_CLR);
+ txgbe_flush(hw);
+ wr32m(hw, TXGBE_FDIRPICMD, TXGBE_FDIRPICMD_CLR, 0);
+ txgbe_flush(hw);
+ /*
+ * Clear FDIR Hash register to clear any leftover hashes
+ * waiting to be programmed.
+ */
+ wr32(hw, TXGBE_FDIRPIHASH, 0x00);
+ txgbe_flush(hw);
+
+ wr32(hw, TXGBE_FDIRCTL, fdirctrl);
+ txgbe_flush(hw);
+
+ /* Poll init-done after we write FDIRCTL register */
+ for (i = 0; i < TXGBE_FDIR_INIT_DONE_POLL; i++) {
+ if (rd32m(hw, TXGBE_FDIRCTL, TXGBE_FDIRCTL_INITDONE))
+ break;
+ msec_delay(1);
+ }
+ if (i >= TXGBE_FDIR_INIT_DONE_POLL) {
+ DEBUGOUT("Flow Director Signature poll time exceeded!\n");
+ return TXGBE_ERR_FDIR_REINIT_FAILED;
+ }
+
+ /* Clear FDIR statistics registers (read to clear) */
+ rd32(hw, TXGBE_FDIRUSED);
+ rd32(hw, TXGBE_FDIRFAIL);
+ rd32(hw, TXGBE_FDIRMATCH);
+ rd32(hw, TXGBE_FDIRMISS);
+ rd32(hw, TXGBE_FDIRLEN);
+
+ return 0;
+}
+
/**
* txgbe_start_hw_raptor - Prepare hardware for Tx/Rx
* @hw: pointer to hardware structure