#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.
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;
- 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;
+ case TXGBE_DEV_ID_SP1000:
+ case TXGBE_DEV_ID_WX1820:
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;
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;
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