net/hns3: fix typos on comments
[dpdk.git] / drivers / net / txgbe / base / txgbe_hw.c
index ab3f9b1..3e7f2f9 100644 (file)
@@ -6,6 +6,7 @@
 #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"
@@ -59,9 +60,9 @@ bool txgbe_device_supports_autoneg_fc(struct txgbe_hw *hw)
                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:
@@ -90,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");
 
@@ -108,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
@@ -144,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:
                /*
@@ -158,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:
@@ -181,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 |
@@ -322,6 +276,9 @@ s32 txgbe_init_hw(struct txgbe_hw *hw)
 
        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) {
@@ -560,6 +517,52 @@ s32 txgbe_stop_hw(struct txgbe_hw *hw)
        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.
@@ -2445,6 +2448,9 @@ s32 txgbe_init_shared_code(struct txgbe_hw *hw)
        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;
@@ -2475,26 +2481,12 @@ s32 txgbe_set_mac_type(struct txgbe_hw *hw)
        }
 
        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;
@@ -2504,8 +2496,8 @@ s32 txgbe_set_mac_type(struct txgbe_hw *hw)
                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;
 }
 
@@ -2536,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;
        }
 }
 
@@ -2563,7 +2551,7 @@ s32 txgbe_init_phy_raptor(struct txgbe_hw *hw)
 
        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;
 
@@ -2586,6 +2574,11 @@ s32 txgbe_init_phy_raptor(struct txgbe_hw *hw)
                                  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:
@@ -2738,6 +2731,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw)
        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;
@@ -2758,6 +2752,7 @@ s32 txgbe_init_ops_pf(struct txgbe_hw *hw)
        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;
@@ -2956,6 +2951,9 @@ u32 txgbe_get_media_type_raptor(struct txgbe_hw *hw)
 
        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:
@@ -2966,22 +2964,29 @@ u32 txgbe_get_media_type_raptor(struct txgbe_hw *hw)
                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;
@@ -3261,13 +3266,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,
@@ -3298,8 +3301,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)
@@ -3326,35 +3328,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);
 
@@ -3467,6 +3448,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);
 }
@@ -3560,12 +3542,19 @@ mac_reset_top:
         */
        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);
 
@@ -3603,6 +3592,93 @@ mac_reset_top:
        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