Skip to content

Commit 2770a79

Browse files
tlfalcondavem330
authored andcommitted
ibmvnic: Introduce hard reset recovery
Introduce a recovery hard reset to handle reset failure as a result of change of device context following a transport event, such as a backing device failover or partition migration. These operations reset the device context to its initial state. If this occurs during a reset, any initialization commands are likely to fail with an invalid state error as backing device firmware requests reinitialization. When this happens, make one more attempt by performing a hard reset, which frees any resources currently allocated and performs device initialization. If a transport event occurs during a device reset, a flag is set which will trigger a new hard reset following the completionof the current reset event. Signed-off-by: Thomas Falcon <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 06e43d7 commit 2770a79

File tree

2 files changed

+98
-4
lines changed

2 files changed

+98
-4
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,6 +1878,85 @@ static int do_reset(struct ibmvnic_adapter *adapter,
18781878
return 0;
18791879
}
18801880

1881+
static int do_hard_reset(struct ibmvnic_adapter *adapter,
1882+
struct ibmvnic_rwi *rwi, u32 reset_state)
1883+
{
1884+
struct net_device *netdev = adapter->netdev;
1885+
int rc;
1886+
1887+
netdev_dbg(adapter->netdev, "Hard resetting driver (%d)\n",
1888+
rwi->reset_reason);
1889+
1890+
netif_carrier_off(netdev);
1891+
adapter->reset_reason = rwi->reset_reason;
1892+
1893+
ibmvnic_cleanup(netdev);
1894+
release_resources(adapter);
1895+
release_sub_crqs(adapter, 0);
1896+
release_crq_queue(adapter);
1897+
1898+
/* remove the closed state so when we call open it appears
1899+
* we are coming from the probed state.
1900+
*/
1901+
adapter->state = VNIC_PROBED;
1902+
1903+
rc = init_crq_queue(adapter);
1904+
if (rc) {
1905+
netdev_err(adapter->netdev,
1906+
"Couldn't initialize crq. rc=%d\n", rc);
1907+
return rc;
1908+
}
1909+
1910+
rc = ibmvnic_init(adapter);
1911+
if (rc)
1912+
return rc;
1913+
1914+
/* If the adapter was in PROBE state prior to the reset,
1915+
* exit here.
1916+
*/
1917+
if (reset_state == VNIC_PROBED)
1918+
return 0;
1919+
1920+
rc = ibmvnic_login(netdev);
1921+
if (rc) {
1922+
adapter->state = VNIC_PROBED;
1923+
return 0;
1924+
}
1925+
/* netif_set_real_num_xx_queues needs to take rtnl lock here
1926+
* unless wait_for_reset is set, in which case the rtnl lock
1927+
* has already been taken before initializing the reset
1928+
*/
1929+
if (!adapter->wait_for_reset) {
1930+
rtnl_lock();
1931+
rc = init_resources(adapter);
1932+
rtnl_unlock();
1933+
} else {
1934+
rc = init_resources(adapter);
1935+
}
1936+
if (rc)
1937+
return rc;
1938+
1939+
ibmvnic_disable_irqs(adapter);
1940+
adapter->state = VNIC_CLOSED;
1941+
1942+
if (reset_state == VNIC_CLOSED)
1943+
return 0;
1944+
1945+
rc = __ibmvnic_open(netdev);
1946+
if (rc) {
1947+
if (list_empty(&adapter->rwi_list))
1948+
adapter->state = VNIC_CLOSED;
1949+
else
1950+
adapter->state = reset_state;
1951+
1952+
return 0;
1953+
}
1954+
1955+
netif_carrier_on(netdev);
1956+
1957+
return 0;
1958+
}
1959+
18811960
static struct ibmvnic_rwi *get_next_rwi(struct ibmvnic_adapter *adapter)
18821961
{
18831962
struct ibmvnic_rwi *rwi;
@@ -1923,9 +2002,15 @@ static void __ibmvnic_reset(struct work_struct *work)
19232002

19242003
rwi = get_next_rwi(adapter);
19252004
while (rwi) {
1926-
rc = do_reset(adapter, rwi, reset_state);
2005+
if (adapter->force_reset_recovery) {
2006+
adapter->force_reset_recovery = false;
2007+
rc = do_hard_reset(adapter, rwi, reset_state);
2008+
} else {
2009+
rc = do_reset(adapter, rwi, reset_state);
2010+
}
19272011
kfree(rwi);
1928-
if (rc && rc != IBMVNIC_INIT_FAILED)
2012+
if (rc && rc != IBMVNIC_INIT_FAILED &&
2013+
!adapter->force_reset_recovery)
19292014
break;
19302015

19312016
rwi = get_next_rwi(adapter);
@@ -1951,9 +2036,9 @@ static void __ibmvnic_reset(struct work_struct *work)
19512036
static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
19522037
enum ibmvnic_reset_reason reason)
19532038
{
2039+
struct list_head *entry, *tmp_entry;
19542040
struct ibmvnic_rwi *rwi, *tmp;
19552041
struct net_device *netdev = adapter->netdev;
1956-
struct list_head *entry;
19572042
int ret;
19582043

19592044
if (adapter->state == VNIC_REMOVING ||
@@ -1989,7 +2074,13 @@ static int ibmvnic_reset(struct ibmvnic_adapter *adapter,
19892074
ret = ENOMEM;
19902075
goto err;
19912076
}
1992-
2077+
/* if we just received a transport event,
2078+
* flush reset queue and process this reset
2079+
*/
2080+
if (adapter->force_reset_recovery && !list_empty(&adapter->rwi_list)) {
2081+
list_for_each_safe(entry, tmp_entry, &adapter->rwi_list)
2082+
list_del(entry);
2083+
}
19932084
rwi->reset_reason = reason;
19942085
list_add_tail(&rwi->list, &adapter->rwi_list);
19952086
mutex_unlock(&adapter->rwi_lock);
@@ -4271,6 +4362,8 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
42714362
case IBMVNIC_CRQ_XPORT_EVENT:
42724363
netif_carrier_off(netdev);
42734364
adapter->crq.active = false;
4365+
if (adapter->resetting)
4366+
adapter->force_reset_recovery = true;
42744367
if (gen_crq->cmd == IBMVNIC_PARTITION_MIGRATED) {
42754368
dev_info(dev, "Migrated, re-enabling adapter\n");
42764369
ibmvnic_reset(adapter, VNIC_RESET_MOBILITY);

drivers/net/ethernet/ibm/ibmvnic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,6 +1109,7 @@ struct ibmvnic_adapter {
11091109

11101110
bool mac_change_pending;
11111111
bool failover_pending;
1112+
bool force_reset_recovery;
11121113

11131114
struct ibmvnic_tunables desired;
11141115
struct ibmvnic_tunables fallback;

0 commit comments

Comments
 (0)