static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
 {
        u32 swsm;
-       s32 ret_val = E1000_SUCCESS;
        s32 timeout = hw->nvm.word_size + 1;
        s32 i = 0;
 
+       /* Get the SW semaphore */
+       while (i < timeout) {
+               swsm = rd32(E1000_SWSM);
+               if (!(swsm & E1000_SWSM_SMBI))
+                       break;
+
+               udelay(50);
+               i++;
+       }
+
+       if (i == timeout) {
+               /* In rare circumstances, the SW semaphore may already be held
+                * unintentionally. Clear the semaphore once before giving up.
+                */
+               if (hw->dev_spec._82575.clear_semaphore_once) {
+                       hw->dev_spec._82575.clear_semaphore_once = false;
+                       igb_put_hw_semaphore(hw);
+                       for (i = 0; i < timeout; i++) {
+                               swsm = rd32(E1000_SWSM);
+                               if (!(swsm & E1000_SWSM_SMBI))
+                                       break;
+
+                               udelay(50);
+                       }
+               }
+
+               /* If we do not have the semaphore here, we have to give up. */
+               if (i == timeout) {
+                       hw_dbg("Driver can't access device - SMBI bit is set.\n");
+                       return -E1000_ERR_NVM;
+               }
+       }
+
        /* Get the FW semaphore. */
        for (i = 0; i < timeout; i++) {
                swsm = rd32(E1000_SWSM);
                /* Release semaphores */
                igb_put_hw_semaphore(hw);
                hw_dbg("Driver can't access the NVM\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return -E1000_ERR_NVM;
        }
 
-out:
-       return ret_val;
+       return E1000_SUCCESS;
 }
 
 /**
        igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
 }
 
-/**
- *  igb_put_hw_semaphore_i210 - Release hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Release hardware semaphore used to access the PHY or NVM
- **/
-static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
-{
-       u32 swsm;
-
-       swsm = rd32(E1000_SWSM);
-
-       swsm &= ~E1000_SWSM_SWESMBI;
-
-       wr32(E1000_SWSM, swsm);
-}
-
 /**
  *  igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
  *  @hw: pointer to the HW structure
                }
 
                swfw_sync = rd32(E1000_SW_FW_SYNC);
-               if (!(swfw_sync & fwmask))
+               if (!(swfw_sync & (fwmask | swmask)))
                        break;
 
                /* Firmware currently using resource (fwmask) */
-               igb_put_hw_semaphore_i210(hw);
+               igb_put_hw_semaphore(hw);
                mdelay(5);
                i++;
        }
        swfw_sync |= swmask;
        wr32(E1000_SW_FW_SYNC, swfw_sync);
 
-       igb_put_hw_semaphore_i210(hw);
+       igb_put_hw_semaphore(hw);
 out:
        return ret_val;
 }
        swfw_sync &= ~mask;
        wr32(E1000_SW_FW_SYNC, swfw_sync);
 
-       igb_put_hw_semaphore_i210(hw);
+       igb_put_hw_semaphore(hw);
 }
 
 /**