Commit 674c18b2ed65f9db04e5c2e9c9e4af8fa2af0f1b

Authored by Emil Tantilov
Committed by Jeff Kirsher
1 parent 9c432adaa8

ixgbe: clear semaphore bits on timeouts

This patch changes the error code path in ixgbe_acquire_swfw_sync() to deal
with cases where acquiring SW semaphore times out.

In cases where the SW/FW semaphore bits were set (i.e. due to a crash) the
driver will hang on load. With this patch the driver will clear
the stuck bits if the semaphore was not acquired in the allotted time.

Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Showing 1 changed file with 21 additions and 24 deletions Side-by-side Diff

drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
... ... @@ -2506,42 +2506,39 @@
2506 2506 **/
2507 2507 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
2508 2508 {
2509   - u32 gssr;
  2509 + u32 gssr = 0;
2510 2510 u32 swmask = mask;
2511 2511 u32 fwmask = mask << 5;
2512   - s32 timeout = 200;
  2512 + u32 timeout = 200;
  2513 + u32 i;
2513 2514  
2514   - while (timeout) {
  2515 + for (i = 0; i < timeout; i++) {
2515 2516 /*
2516   - * SW EEPROM semaphore bit is used for access to all
2517   - * SW_FW_SYNC/GSSR bits (not just EEPROM)
  2517 + * SW NVM semaphore bit is used for access to all
  2518 + * SW_FW_SYNC bits (not just NVM)
2518 2519 */
2519 2520 if (ixgbe_get_eeprom_semaphore(hw))
2520 2521 return IXGBE_ERR_SWFW_SYNC;
2521 2522  
2522 2523 gssr = IXGBE_READ_REG(hw, IXGBE_GSSR);
2523   - if (!(gssr & (fwmask | swmask)))
2524   - break;
2525   -
2526   - /*
2527   - * Firmware currently using resource (fwmask) or other software
2528   - * thread currently using resource (swmask)
2529   - */
2530   - ixgbe_release_eeprom_semaphore(hw);
2531   - usleep_range(5000, 10000);
2532   - timeout--;
  2524 + if (!(gssr & (fwmask | swmask))) {
  2525 + gssr |= swmask;
  2526 + IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
  2527 + ixgbe_release_eeprom_semaphore(hw);
  2528 + return 0;
  2529 + } else {
  2530 + /* Resource is currently in use by FW or SW */
  2531 + ixgbe_release_eeprom_semaphore(hw);
  2532 + usleep_range(5000, 10000);
  2533 + }
2533 2534 }
2534 2535  
2535   - if (!timeout) {
2536   - hw_dbg(hw, "Driver can't access resource, SW_FW_SYNC timeout.\n");
2537   - return IXGBE_ERR_SWFW_SYNC;
2538   - }
  2536 + /* If time expired clear the bits holding the lock and retry */
  2537 + if (gssr & (fwmask | swmask))
  2538 + ixgbe_release_swfw_sync(hw, gssr & (fwmask | swmask));
2539 2539  
2540   - gssr |= swmask;
2541   - IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
2542   -
2543   - ixgbe_release_eeprom_semaphore(hw);
2544   - return 0;
  2540 + usleep_range(5000, 10000);
  2541 + return IXGBE_ERR_SWFW_SYNC;
2545 2542 }
2546 2543  
2547 2544 /**