ixgbe/base: rework locking
authorJijiang Liu <jijiang.liu@intel.com>
Wed, 18 Jun 2014 17:53:49 +0000 (19:53 +0200)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Wed, 18 Jun 2014 21:31:41 +0000 (23:31 +0200)
Signed-off-by: Jijiang Liu <jijiang.liu@intel.com>
Acked-by: Helin Zhang <helin.zhang@intel.com>
Tested-by: Waterman Cao <waterman.cao@intel.com>
[Thomas: split code drop]

lib/librte_pmd_ixgbe/ixgbe/ixgbe_82598.c
lib/librte_pmd_ixgbe/ixgbe/ixgbe_82599.c
lib/librte_pmd_ixgbe/ixgbe/ixgbe_common.c
lib/librte_pmd_ixgbe/ixgbe/ixgbe_phy.c
lib/librte_pmd_ixgbe/ixgbe/ixgbe_phy.h
lib/librte_pmd_ixgbe/ixgbe/ixgbe_type.h
lib/librte_pmd_ixgbe/ixgbe/ixgbe_x540.c

index 311dd51..edbec95 100644 (file)
@@ -1122,10 +1122,19 @@ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
        u16 sfp_addr = 0;
        u16 sfp_data = 0;
        u16 sfp_stat = 0;
+       u16 gssr;
        u32 i;
 
        DEBUGFUNC("ixgbe_read_i2c_eeprom_82598");
 
+       if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+               gssr = IXGBE_GSSR_PHY1_SM;
+       else
+               gssr = IXGBE_GSSR_PHY0_SM;
+
+       if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != IXGBE_SUCCESS)
+               return IXGBE_ERR_SWFW_SYNC;
+
        if (hw->phy.type == ixgbe_phy_nl) {
                /*
                 * NetLogic phy SDA/SCL registers are at addresses 0xC30A to
@@ -1168,6 +1177,7 @@ s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
        }
 
 out:
+       hw->mac.ops.release_swfw_sync(hw, gssr);
        return status;
 }
 
index 2b95db5..6a1b263 100644 (file)
@@ -598,6 +598,10 @@ void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
        u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
 
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               return;
+
        /* Disable tx laser; allow 100us to go dark per spec */
        esdp_reg |= IXGBE_ESDP_SDP3;
        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
@@ -640,6 +644,10 @@ void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
        DEBUGFUNC("ixgbe_flap_tx_laser_multispeed_fiber");
 
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               return;
+
        if (hw->mac.autotry_restart) {
                ixgbe_disable_tx_laser_multispeed_fiber(hw);
                ixgbe_enable_tx_laser_multispeed_fiber(hw);
index 7b768fa..eb3bba7 100644 (file)
@@ -3160,44 +3160,41 @@ out:
  **/
 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
 {
-       u32 gssr;
+       u32 gssr = 0;
        u32 swmask = mask;
        u32 fwmask = mask << 5;
-       s32 timeout = 200;
+       u32 timeout = 200;
+       u32 i;
 
        DEBUGFUNC("ixgbe_acquire_swfw_sync");
 
-       while (timeout) {
+       for (i = 0; i < timeout; i++) {
                /*
-                * SW EEPROM semaphore bit is used for access to all
-                * SW_FW_SYNC/GSSR bits (not just EEPROM)
+                * SW NVM semaphore bit is used for access to all
+                * SW_FW_SYNC bits (not just NVM)
                 */
                if (ixgbe_get_eeprom_semaphore(hw))
                        return IXGBE_ERR_SWFW_SYNC;
 
                gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
-               if (!(gssr & (fwmask | swmask)))
-                       break;
-
-               /*
-                * Firmware currently using resource (fwmask) or other software
-                * thread currently using resource (swmask)
-                */
-               ixgbe_release_eeprom_semaphore(hw);
-               msec_delay(5);
-               timeout--;
-       }
-
-       if (!timeout) {
-               DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
-               return IXGBE_ERR_SWFW_SYNC;
+               if (!(gssr & (fwmask | swmask))) {
+                       gssr |= swmask;
+                       IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
+                       ixgbe_release_eeprom_semaphore(hw);
+                       return IXGBE_SUCCESS;
+               } else {
+                       /* Resource is currently in use by FW or SW */
+                       ixgbe_release_eeprom_semaphore(hw);
+                       msec_delay(5);
+               }
        }
 
-       gssr |= swmask;
-       IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
+       /* If time expired clear the bits holding the lock and retry */
+       if (gssr & (fwmask | swmask))
+               ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
 
-       ixgbe_release_eeprom_semaphore(hw);
-       return IXGBE_SUCCESS;
+       msec_delay(5);
+       return IXGBE_ERR_SWFW_SYNC;
 }
 
 /**
index 98a7b45..33d6551 100644 (file)
@@ -136,6 +136,35 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
        return status;
 }
 
+/**
+ * ixgbe_check_reset_blocked - check status of MNG FW veto bit
+ * @hw: pointer to the hardware structure
+ *
+ * This function checks the MMNGC.MNG_VETO bit to see if there are
+ * any constraints on link from manageability.  For MAC's that don't
+ * have this bit just return faluse since the link can not be blocked
+ * via this method.
+ **/
+s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw)
+{
+       u32 mmngc;
+
+       DEBUGFUNC("ixgbe_check_reset_blocked");
+
+       /* If we don't have this bit, it can't be blocking */
+       if (hw->mac.type == ixgbe_mac_82598EB)
+               return false;
+
+       mmngc = IXGBE_READ_REG(hw, IXGBE_MMNGC);
+       if (mmngc & IXGBE_MMNGC_MNG_VETO) {
+               ERROR_REPORT1(IXGBE_ERROR_SOFTWARE,
+                             "MNG_VETO bit detected.\n");
+               return true;
+       }
+
+       return false;
+}
+
 /**
  *  ixgbe_validate_phy_addr - Determines phy address is valid
  *  @hw: pointer to hardware structure
@@ -242,6 +271,10 @@ s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
            (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
                goto out;
 
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               goto out;
+
        /*
         * Perform soft PHY reset to the PHY_XS.
         * This will cause a soft reset to the PHY
@@ -535,6 +568,10 @@ s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
                                      autoneg_reg);
        }
 
+       /* Blocked by MNG FW so don't reset PHY */
+       if (ixgbe_check_reset_blocked(hw))
+               return status;
+
        /* Restart PHY autonegotiation and wait for completion */
        hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
                             IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
@@ -749,6 +786,10 @@ s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
                                      autoneg_reg);
        }
 
+       /* Blocked by MNG FW so don't reset PHY */
+       if (ixgbe_check_reset_blocked(hw))
+               return status;
+
        /* Restart PHY autonegotiation and wait for completion */
        hw->phy.ops.read_reg(hw, IXGBE_MDIO_AUTO_NEG_CONTROL,
                             IXGBE_MDIO_AUTO_NEG_DEV_TYPE, &autoneg_reg);
@@ -832,6 +873,10 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
 
        DEBUGFUNC("ixgbe_reset_phy_nl");
 
+       /* Blocked by MNG FW so bail */
+       if (ixgbe_check_reset_blocked(hw))
+               goto out;
+
        hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
                             IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
 
@@ -1484,9 +1529,9 @@ s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
                break;
 
 fail:
+               ixgbe_i2c_bus_clear(hw);
                hw->mac.ops.release_swfw_sync(hw, swfw_mask);
                msec_delay(100);
-               ixgbe_i2c_bus_clear(hw);
                retry++;
                if (retry < max_retry)
                        DEBUGOUT("I2C byte read error - Retrying.\n");
index 191e697..dfcd2ba 100644 (file)
@@ -117,6 +117,7 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
 s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
                                               ixgbe_link_speed *speed,
                                               bool *autoneg);
+s32 ixgbe_check_reset_blocked(struct ixgbe_hw *hw);
 
 /* PHY specific */
 s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
index b449242..991bc61 100644 (file)
@@ -1728,6 +1728,9 @@ enum {
 #define IXGBE_MACC_FS          0x00040000
 #define IXGBE_MAC_RX2TX_LPBK   0x00000002
 
+/* Veto Bit definiton */
+#define IXGBE_MMNGC_MNG_VETO   0x00000001
+
 /* LINKS Bit Masks */
 #define IXGBE_LINKS_KX_AN_COMP 0x80000000
 #define IXGBE_LINKS_UP         0x40000000
index b8826d6..1610f6c 100644 (file)
@@ -381,12 +381,13 @@ s32 ixgbe_read_eerd_X540(struct ixgbe_hw *hw, u16 offset, u16 *data)
 
        DEBUGFUNC("ixgbe_read_eerd_X540");
        if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
-           IXGBE_SUCCESS)
+           IXGBE_SUCCESS) {
                status = ixgbe_read_eerd_generic(hw, offset, data);
-       else
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+       } else {
                status = IXGBE_ERR_SWFW_SYNC;
+       }
 
-       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
        return status;
 }
 
@@ -406,13 +407,14 @@ s32 ixgbe_read_eerd_buffer_X540(struct ixgbe_hw *hw,
 
        DEBUGFUNC("ixgbe_read_eerd_buffer_X540");
        if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
-           IXGBE_SUCCESS)
+           IXGBE_SUCCESS) {
                status = ixgbe_read_eerd_buffer_generic(hw, offset,
                                                        words, data);
-       else
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+       } else {
                status = IXGBE_ERR_SWFW_SYNC;
+       }
 
-       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
        return status;
 }
 
@@ -430,12 +432,13 @@ s32 ixgbe_write_eewr_X540(struct ixgbe_hw *hw, u16 offset, u16 data)
 
        DEBUGFUNC("ixgbe_write_eewr_X540");
        if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
-           IXGBE_SUCCESS)
+           IXGBE_SUCCESS) {
                status = ixgbe_write_eewr_generic(hw, offset, data);
-       else
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+       } else {
                status = IXGBE_ERR_SWFW_SYNC;
+       }
 
-       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
        return status;
 }
 
@@ -455,13 +458,14 @@ s32 ixgbe_write_eewr_buffer_X540(struct ixgbe_hw *hw,
 
        DEBUGFUNC("ixgbe_write_eewr_buffer_X540");
        if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) ==
-           IXGBE_SUCCESS)
+           IXGBE_SUCCESS) {
                status = ixgbe_write_eewr_buffer_generic(hw, offset,
                                                         words, data);
-       else
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+       } else {
                status = IXGBE_ERR_SWFW_SYNC;
+       }
 
-       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
        return status;
 }
 
@@ -596,11 +600,11 @@ s32 ixgbe_validate_eeprom_checksum_X540(struct ixgbe_hw *hw,
                /* If the user cares, return the calculated checksum */
                if (checksum_val)
                        *checksum_val = checksum;
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
        } else {
                status = IXGBE_ERR_SWFW_SYNC;
        }
 
-       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 out:
        return status;
 }
@@ -641,14 +645,13 @@ s32 ixgbe_update_eeprom_checksum_X540(struct ixgbe_hw *hw)
                status = ixgbe_write_eewr_generic(hw, IXGBE_EEPROM_CHECKSUM,
                                                  checksum);
 
-       if (status == IXGBE_SUCCESS)
-               status = ixgbe_update_flash_X540(hw);
-       else
+               if (status == IXGBE_SUCCESS)
+                       status = ixgbe_update_flash_X540(hw);
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+       } else {
                status = IXGBE_ERR_SWFW_SYNC;
        }
 
-       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
-
        return status;
 }
 
@@ -810,6 +813,17 @@ s32 ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
                ixgbe_release_swfw_sync_semaphore(hw);
                msec_delay(5);
        }
+       /* If the resource is not released by other SW the SW can assume that
+        * the other SW malfunctions. In that case the SW should clear all SW
+        * flags that it does not own and then repeat the whole process once
+        * again.
+        */
+       else if (swfw_sync & swmask) {
+               ixgbe_release_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM |
+                       IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_PHY1_SM |
+                       IXGBE_GSSR_MAC_CSR_SM);
+               ret_val = IXGBE_ERR_SWFW_SYNC;
+       }
 
 out:
        return ret_val;