Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ibmvnic: retry reset if there are no other resets

Normally, if a reset fails due to failover or other communication error
there is another reset (eg: FAILOVER) in the queue and we would process
that reset. But if we are unable to communicate with PHYP or VIOS after
H_FREE_CRQ, there would be no other resets in the queue and the adapter
would be in an undefined state even though it was in the OPEN state
earlier. While starting the reset we set the carrier to off state so
we won't even get the timeout resets.

If the last queued reset fails, retry it as a hard reset (after the
usual 60 second settling time).

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.ibm.com>
Reviewed-by: Dany Madden <drt@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Sukadev Bhattiprolu and committed by
David S. Miller
4f408e1f b2bc8148

+19 -3
+19 -3
drivers/net/ethernet/ibm/ibmvnic.c
··· 2420 2420 2421 2421 static void __ibmvnic_reset(struct work_struct *work) 2422 2422 { 2423 - struct ibmvnic_rwi *rwi; 2424 2423 struct ibmvnic_adapter *adapter; 2425 2424 bool saved_state = false; 2425 + struct ibmvnic_rwi *tmprwi; 2426 + struct ibmvnic_rwi *rwi; 2426 2427 unsigned long flags; 2427 2428 u32 reset_state; 2428 2429 int rc = 0; ··· 2490 2489 } else { 2491 2490 rc = do_reset(adapter, rwi, reset_state); 2492 2491 } 2493 - kfree(rwi); 2492 + tmprwi = rwi; 2494 2493 adapter->last_reset_time = jiffies; 2495 2494 2496 2495 if (rc) ··· 2498 2497 2499 2498 rwi = get_next_rwi(adapter); 2500 2499 2500 + /* 2501 + * If there is another reset queued, free the previous rwi 2502 + * and process the new reset even if previous reset failed 2503 + * (the previous reset could have failed because of a fail 2504 + * over for instance, so process the fail over). 2505 + * 2506 + * If there are no resets queued and the previous reset failed, 2507 + * the adapter would be in an undefined state. So retry the 2508 + * previous reset as a hard reset. 2509 + */ 2510 + if (rwi) 2511 + kfree(tmprwi); 2512 + else if (rc) 2513 + rwi = tmprwi; 2514 + 2501 2515 if (rwi && (rwi->reset_reason == VNIC_RESET_FAILOVER || 2502 - rwi->reset_reason == VNIC_RESET_MOBILITY)) 2516 + rwi->reset_reason == VNIC_RESET_MOBILITY || rc)) 2503 2517 adapter->force_reset_recovery = true; 2504 2518 } 2505 2519