net/ixgbe/base: add PHY read and write
authorQiming Yang <qiming.yang@intel.com>
Wed, 10 Jan 2018 16:04:34 +0000 (00:04 +0800)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 16 Jan 2018 17:47:49 +0000 (18:47 +0100)
This patch adds lockless read/write support for clause 22 PHY,
together with some enhancements for link speed and return value
handling.

Signed-off-by: Qiming Yang <qiming.yang@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
drivers/net/ixgbe/base/ixgbe_common.c
drivers/net/ixgbe/base/ixgbe_x550.c

index 8401dc1..7e99d7e 100644 (file)
@@ -4246,10 +4246,17 @@ s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
                break;
        case IXGBE_LINKS_SPEED_10_X550EM_A:
                *speed = IXGBE_LINK_SPEED_UNKNOWN;
+#ifdef PREBOOT_SUPPORT
                if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
-                   hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L) {
+                   hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L ||
+                   hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
+                   hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
                        *speed = IXGBE_LINK_SPEED_10_FULL;
-               }
+#else
+               if (hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T ||
+                   hw->device_id == IXGBE_DEV_ID_X550EM_A_1G_T_L)
+                       *speed = IXGBE_LINK_SPEED_10_FULL;
+#endif /* PREBOOT_SUPPORT */
                break;
        default:
                *speed = IXGBE_LINK_SPEED_UNKNOWN;
@@ -4669,10 +4676,10 @@ s32 ixgbe_set_fw_drv_ver_generic(struct ixgbe_hw *hw, u8 maj, u8 min,
        fw_cmd.ver_build = build;
        fw_cmd.ver_sub = sub;
        fw_cmd.hdr.checksum = 0;
-       fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
-                               (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
        fw_cmd.pad = 0;
        fw_cmd.pad2 = 0;
+       fw_cmd.hdr.checksum = ixgbe_calculate_checksum((u8 *)&fw_cmd,
+                               (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
 
        for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
                ret_val = ixgbe_host_interface_command(hw, (u32 *)&fw_cmd,
@@ -5165,8 +5172,8 @@ bool ixgbe_mng_present(struct ixgbe_hw *hw)
                return false;
 
        fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM_BY_MAC(hw));
-       fwsm &= IXGBE_FWSM_MODE_MASK;
-       return fwsm == IXGBE_FWSM_FW_MODE_PT;
+
+       return !!(fwsm & IXGBE_FWSM_FW_MODE_PT);
 }
 
 /**
index f7401c0..6445440 100644 (file)
@@ -335,98 +335,6 @@ STATIC void ixgbe_setup_mux_ctl(struct ixgbe_hw *hw)
        IXGBE_WRITE_FLUSH(hw);
 }
 
-/**
- * ixgbe_read_phy_reg_mdi_22 - Read from a clause 22 PHY register without lock
- * @hw: pointer to hardware structure
- * @reg_addr: 32 bit address of PHY register to read
- * @dev_type: always unused
- * @phy_data: Pointer to read data from PHY register
- */
-STATIC s32 ixgbe_read_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr,
-                                    u32 dev_type, u16 *phy_data)
-{
-       u32 i, data, command;
-       UNREFERENCED_1PARAMETER(dev_type);
-
-       /* Setup and write the read command */
-       command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-                 (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
-                 IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC |
-                 IXGBE_MSCA_MDI_COMMAND;
-
-       IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
-
-       /* Check every 10 usec to see if the access completed.
-        * The MDI Command bit will clear when the operation is
-        * complete
-        */
-       for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
-               usec_delay(10);
-
-               command = IXGBE_READ_REG(hw, IXGBE_MSCA);
-               if (!(command & IXGBE_MSCA_MDI_COMMAND))
-                       break;
-       }
-
-       if (command & IXGBE_MSCA_MDI_COMMAND) {
-               ERROR_REPORT1(IXGBE_ERROR_POLLING,
-                             "PHY read command did not complete.\n");
-               return IXGBE_ERR_PHY;
-       }
-
-       /* Read operation is complete.  Get the data from MSRWD */
-       data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
-       data >>= IXGBE_MSRWD_READ_DATA_SHIFT;
-       *phy_data = (u16)data;
-
-       return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_write_phy_reg_mdi_22 - Write to a clause 22 PHY register without lock
- * @hw: pointer to hardware structure
- * @reg_addr: 32 bit PHY register to write
- * @dev_type: always unused
- * @phy_data: Data to write to the PHY register
- */
-STATIC s32 ixgbe_write_phy_reg_mdi_22(struct ixgbe_hw *hw, u32 reg_addr,
-                                     u32 dev_type, u16 phy_data)
-{
-       u32 i, command;
-       UNREFERENCED_1PARAMETER(dev_type);
-
-       /* Put the data in the MDI single read and write data register*/
-       IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data);
-
-       /* Setup and write the write command */
-       command = (reg_addr << IXGBE_MSCA_DEV_TYPE_SHIFT) |
-                 (hw->phy.addr << IXGBE_MSCA_PHY_ADDR_SHIFT) |
-                 IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
-                 IXGBE_MSCA_MDI_COMMAND;
-
-       IXGBE_WRITE_REG(hw, IXGBE_MSCA, command);
-
-       /* Check every 10 usec to see if the access completed.
-        * The MDI Command bit will clear when the operation is
-        * complete
-        */
-       for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) {
-               usec_delay(10);
-
-               command = IXGBE_READ_REG(hw, IXGBE_MSCA);
-               if (!(command & IXGBE_MSCA_MDI_COMMAND))
-                       break;
-       }
-
-       if (command & IXGBE_MSCA_MDI_COMMAND) {
-               ERROR_REPORT1(IXGBE_ERROR_POLLING,
-                             "PHY write cmd didn't complete\n");
-               return IXGBE_ERR_PHY;
-       }
-
-       return IXGBE_SUCCESS;
-}
-
 /**
  * ixgbe_identify_phy_x550em - Get PHY type based on device id
  * @hw: pointer to hardware structure
@@ -467,14 +375,10 @@ STATIC s32 ixgbe_identify_phy_x550em(struct ixgbe_hw *hw)
                return ixgbe_identify_phy_generic(hw);
        case IXGBE_DEV_ID_X550EM_X_1G_T:
                hw->phy.type = ixgbe_phy_ext_1g_t;
-               hw->phy.ops.read_reg = NULL;
-               hw->phy.ops.write_reg = NULL;
                break;
        case IXGBE_DEV_ID_X550EM_A_1G_T:
        case IXGBE_DEV_ID_X550EM_A_1G_T_L:
                hw->phy.type = ixgbe_phy_fw;
-               hw->phy.ops.read_reg = NULL;
-               hw->phy.ops.write_reg = NULL;
                if (hw->bus.lan_id)
                        hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
                else
@@ -854,7 +758,7 @@ static s32 ixgbe_fc_autoneg_fw(struct ixgbe_hw *hw)
 
 /**
  * ixgbe_setup_eee_fw - Enable/disable EEE support
- * @hw: pointer to the HW structure
+ * @hw: pointer to the HW structurewrite_reg_mdi
  * @enable_eee: boolean flag to enable EEE
  *
  * Enable/disable EEE based on enable_eee flag.
@@ -1764,9 +1668,12 @@ STATIC s32 ixgbe_restart_an_internal_phy_x550em(struct ixgbe_hw *hw)
        return status;
 }
 
+#ifndef PREBOOT_SUPPORT
 /**
  * ixgbe_setup_sgmii - Set up link for sgmii
  * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait: true when waiting for completion is needed
  */
 STATIC s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed,
                             bool autoneg_wait)
@@ -1831,9 +1738,12 @@ STATIC s32 ixgbe_setup_sgmii(struct ixgbe_hw *hw, ixgbe_link_speed speed,
        return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
 }
 
+#endif /* PREBOOT_SUPPORT */
 /**
- * ixgbe_setup_sgmii_fw - Set up link for sgmii with firmware-controlled PHYs
+ * ixgbe_setup_sgmii_fw - Set up link for internal PHY SGMII auto-negotiation
  * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait: true when waiting for completion is needed
  */
 STATIC s32 ixgbe_setup_sgmii_fw(struct ixgbe_hw *hw, ixgbe_link_speed speed,
                                bool autoneg_wait)
@@ -1953,7 +1863,11 @@ void ixgbe_init_mac_link_ops_X550em(struct ixgbe_hw *hw)
        case ixgbe_media_type_backplane:
                if (hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII ||
                    hw->device_id == IXGBE_DEV_ID_X550EM_A_SGMII_L)
+#ifdef PREBOOT_SUPPORT
+                       mac->ops.setup_link = ixgbe_setup_sgmii_fw;
+#else
                        mac->ops.setup_link = ixgbe_setup_sgmii;
+#endif /* PREBOOT_SUPPORT */
                break;
        default:
                break;
@@ -2003,8 +1917,18 @@ s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
        } else {
                switch (hw->phy.type) {
                case ixgbe_phy_ext_1g_t:
+#ifdef PREBOOT_SUPPORT
+                       *speed = IXGBE_LINK_SPEED_1GB_FULL;
+                       break;
+#endif /* PREBOOT_SUPPORT */
                case ixgbe_phy_sgmii:
+#ifdef PREBOOT_SUPPORT
+                       *speed = IXGBE_LINK_SPEED_1GB_FULL |
+                                IXGBE_LINK_SPEED_100_FULL |
+                                IXGBE_LINK_SPEED_10_FULL;
+#else
                        *speed = IXGBE_LINK_SPEED_1GB_FULL;
+#endif /* PREBOOT_SUPPORT */
                        break;
                case ixgbe_phy_x550em_kr:
                        if (hw->mac.type == ixgbe_mac_X550EM_a) {
@@ -2376,10 +2300,10 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
        switch (hw->device_id) {
        case IXGBE_DEV_ID_X550EM_A_1G_T:
        case IXGBE_DEV_ID_X550EM_A_1G_T_L:
-               phy->ops.read_reg_mdi = ixgbe_read_phy_reg_mdi_22;
-               phy->ops.write_reg_mdi = ixgbe_write_phy_reg_mdi_22;
-               hw->phy.ops.read_reg = ixgbe_read_phy_reg_x550a;
-               hw->phy.ops.write_reg = ixgbe_write_phy_reg_x550a;
+               phy->ops.read_reg_mdi = NULL;
+               phy->ops.write_reg_mdi = NULL;
+               hw->phy.ops.read_reg = NULL;
+               hw->phy.ops.write_reg = NULL;
                phy->ops.check_overtemp = ixgbe_check_overtemp_fw;
                if (hw->bus.lan_id)
                        hw->phy.phy_semaphore_mask |= IXGBE_GSSR_PHY1_SM;
@@ -2400,6 +2324,9 @@ s32 ixgbe_init_phy_ops_X550em(struct ixgbe_hw *hw)
                /* set up for CS4227 usage */
                hw->phy.phy_semaphore_mask = IXGBE_GSSR_SHARED_I2C_SM;
                break;
+       case IXGBE_DEV_ID_X550EM_X_1G_T:
+               phy->ops.read_reg_mdi = NULL;
+               phy->ops.write_reg_mdi = NULL;
        default:
                break;
        }
@@ -2536,7 +2463,8 @@ s32 ixgbe_reset_hw_X550em(struct ixgbe_hw *hw)
                DEBUGOUT1("Failed to initialize PHY ops, STATUS = %d\n",
                          status);
 
-       if (status == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+       if (status == IXGBE_ERR_SFP_NOT_SUPPORTED ||
+           status == IXGBE_ERR_PHY_ADDR_INVALID) {
                DEBUGOUT("Returning from reset HW due to PHY init failure\n");
                return status;
        }
@@ -3211,6 +3139,8 @@ s32 ixgbe_read_ee_hostif_X550(struct ixgbe_hw *hw, u16 offset, u16 *data)
        buffer.address = IXGBE_CPU_TO_BE32(offset * 2);
        /* one word */
        buffer.length = IXGBE_CPU_TO_BE16(sizeof(u16));
+       buffer.pad2 = 0;
+       buffer.pad3 = 0;
 
        status = hw->mac.ops.acquire_swfw_sync(hw, mask);
        if (status)
@@ -3269,6 +3199,8 @@ s32 ixgbe_read_ee_hostif_buffer_X550(struct ixgbe_hw *hw,
                /* convert offset from words to bytes */
                buffer.address = IXGBE_CPU_TO_BE32((offset + current_word) * 2);
                buffer.length = IXGBE_CPU_TO_BE16(words_to_read * 2);
+               buffer.pad2 = 0;
+               buffer.pad3 = 0;
 
                status = ixgbe_hic_unlocked(hw, (u32 *)&buffer, sizeof(buffer),
                                            IXGBE_HI_COMMAND_TIMEOUT);
@@ -3740,7 +3672,13 @@ u64 ixgbe_get_supported_physical_layer_X550em(struct ixgbe_hw *hw)
                        physical_layer |= IXGBE_PHYSICAL_LAYER_10BASE_T;
                break;
        case ixgbe_phy_sgmii:
+#ifdef PREBOOT_SUPPORT
+               physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
+                                IXGBE_PHYSICAL_LAYER_100BASE_TX |
+                                IXGBE_PHYSICAL_LAYER_10BASE_T;
+#else
                physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+#endif /* PREBOOT_SUPPORT */
                break;
        case ixgbe_phy_ext_1g_t:
                physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;