Skip to content

Commit 476d96c

Browse files
tlfalcondavem330
authored andcommitted
ibmvnic: Bound waits for device queries
Create a wrapper for wait_for_completion calls with additional driver checks to ensure that the driver does not wait on a disabled device. In those cases or if the device does not respond in an extended amount of time, this will allow the driver an opportunity to recover. Signed-off-by: Thomas Falcon <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2147e3d commit 476d96c

File tree

1 file changed

+97
-15
lines changed

1 file changed

+97
-15
lines changed

drivers/net/ethernet/ibm/ibmvnic.c

Lines changed: 97 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,40 @@ static long h_reg_sub_crq(unsigned long unit_address, unsigned long token,
159159
return rc;
160160
}
161161

162+
/**
163+
* ibmvnic_wait_for_completion - Check device state and wait for completion
164+
* @adapter: private device data
165+
* @comp_done: completion structure to wait for
166+
* @timeout: time to wait in milliseconds
167+
*
168+
* Wait for a completion signal or until the timeout limit is reached
169+
* while checking that the device is still active.
170+
*/
171+
static int ibmvnic_wait_for_completion(struct ibmvnic_adapter *adapter,
172+
struct completion *comp_done,
173+
unsigned long timeout)
174+
{
175+
struct net_device *netdev;
176+
unsigned long div_timeout;
177+
u8 retry;
178+
179+
netdev = adapter->netdev;
180+
retry = 5;
181+
div_timeout = msecs_to_jiffies(timeout / retry);
182+
while (true) {
183+
if (!adapter->crq.active) {
184+
netdev_err(netdev, "Device down!\n");
185+
return -ENODEV;
186+
}
187+
if (retry--)
188+
break;
189+
if (wait_for_completion_timeout(comp_done, div_timeout))
190+
return 0;
191+
}
192+
netdev_err(netdev, "Operation timed out.\n");
193+
return -ETIMEDOUT;
194+
}
195+
162196
static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
163197
struct ibmvnic_long_term_buff *ltb, int size)
164198
{
@@ -183,7 +217,15 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
183217
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
184218
return rc;
185219
}
186-
wait_for_completion(&adapter->fw_done);
220+
221+
rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
222+
if (rc) {
223+
dev_err(dev,
224+
"Long term map request aborted or timed out,rc = %d\n",
225+
rc);
226+
dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
227+
return rc;
228+
}
187229

188230
if (adapter->fw_done_rc) {
189231
dev_err(dev, "Couldn't map long term buffer,rc = %d\n",
@@ -211,6 +253,7 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
211253
static int reset_long_term_buff(struct ibmvnic_adapter *adapter,
212254
struct ibmvnic_long_term_buff *ltb)
213255
{
256+
struct device *dev = &adapter->vdev->dev;
214257
int rc;
215258

216259
memset(ltb->buff, 0, ltb->size);
@@ -219,10 +262,16 @@ static int reset_long_term_buff(struct ibmvnic_adapter *adapter,
219262
rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
220263
if (rc)
221264
return rc;
222-
wait_for_completion(&adapter->fw_done);
265+
266+
rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
267+
if (rc) {
268+
dev_info(dev,
269+
"Reset failed, long term map request timed out or aborted\n");
270+
return rc;
271+
}
223272

224273
if (adapter->fw_done_rc) {
225-
dev_info(&adapter->vdev->dev,
274+
dev_info(dev,
226275
"Reset failed, attempting to free and reallocate buffer\n");
227276
free_long_term_buff(adapter, ltb);
228277
return alloc_long_term_buff(adapter, ltb, ltb->size);
@@ -949,7 +998,12 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
949998
rc = ibmvnic_send_crq(adapter, &crq);
950999
if (rc)
9511000
return rc;
952-
wait_for_completion(&adapter->fw_done);
1001+
1002+
rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
1003+
if (rc) {
1004+
dev_err(dev, "Could not retrieve VPD size, rc = %d\n", rc);
1005+
return rc;
1006+
}
9531007

9541008
if (!adapter->vpd->len)
9551009
return -ENODATA;
@@ -987,7 +1041,14 @@ static int ibmvnic_get_vpd(struct ibmvnic_adapter *adapter)
9871041
adapter->vpd->buff = NULL;
9881042
return rc;
9891043
}
990-
wait_for_completion(&adapter->fw_done);
1044+
1045+
rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
1046+
if (rc) {
1047+
dev_err(dev, "Unable to retrieve VPD, rc = %d\n", rc);
1048+
kfree(adapter->vpd->buff);
1049+
adapter->vpd->buff = NULL;
1050+
return rc;
1051+
}
9911052

9921053
return 0;
9931054
}
@@ -1696,9 +1757,9 @@ static int __ibmvnic_set_mac(struct net_device *netdev, u8 *dev_addr)
16961757
goto err;
16971758
}
16981759

1699-
wait_for_completion(&adapter->fw_done);
1760+
rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
17001761
/* netdev->dev_addr is changed in handle_change_mac_rsp function */
1701-
if (adapter->fw_done_rc) {
1762+
if (rc || adapter->fw_done_rc) {
17021763
rc = -EIO;
17031764
goto err;
17041765
}
@@ -2319,9 +2380,16 @@ static int wait_for_reset(struct ibmvnic_adapter *adapter)
23192380
reinit_completion(&adapter->reset_done);
23202381
adapter->wait_for_reset = true;
23212382
rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM);
2322-
if (rc)
2323-
return rc;
2324-
wait_for_completion(&adapter->reset_done);
2383+
2384+
if (rc) {
2385+
ret = rc;
2386+
goto out;
2387+
}
2388+
rc = ibmvnic_wait_for_completion(adapter, &adapter->reset_done, 60000);
2389+
if (rc) {
2390+
ret = -ENODEV;
2391+
goto out;
2392+
}
23252393

23262394
ret = 0;
23272395
if (adapter->reset_done_rc) {
@@ -2335,10 +2403,18 @@ static int wait_for_reset(struct ibmvnic_adapter *adapter)
23352403
reinit_completion(&adapter->reset_done);
23362404
adapter->wait_for_reset = true;
23372405
rc = ibmvnic_reset(adapter, VNIC_RESET_CHANGE_PARAM);
2338-
if (rc)
2339-
return ret;
2340-
wait_for_completion(&adapter->reset_done);
2406+
if (rc) {
2407+
ret = rc;
2408+
goto out;
2409+
}
2410+
rc = ibmvnic_wait_for_completion(adapter, &adapter->reset_done,
2411+
60000);
2412+
if (rc) {
2413+
ret = -ENODEV;
2414+
goto out;
2415+
}
23412416
}
2417+
out:
23422418
adapter->wait_for_reset = false;
23432419

23442420
return ret;
@@ -2607,7 +2683,9 @@ static void ibmvnic_get_ethtool_stats(struct net_device *dev,
26072683
rc = ibmvnic_send_crq(adapter, &crq);
26082684
if (rc)
26092685
return;
2610-
wait_for_completion(&adapter->stats_done);
2686+
rc = ibmvnic_wait_for_completion(adapter, &adapter->stats_done, 10000);
2687+
if (rc)
2688+
return;
26112689

26122690
for (i = 0; i < ARRAY_SIZE(ibmvnic_stats); i++)
26132691
data[i] = be64_to_cpu(IBMVNIC_GET_STAT(adapter,
@@ -4412,7 +4490,11 @@ static int send_query_phys_parms(struct ibmvnic_adapter *adapter)
44124490
rc = ibmvnic_send_crq(adapter, &crq);
44134491
if (rc)
44144492
return rc;
4415-
wait_for_completion(&adapter->fw_done);
4493+
4494+
rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000);
4495+
if (rc)
4496+
return rc;
4497+
44164498
return adapter->fw_done_rc ? -EIO : 0;
44174499
}
44184500

0 commit comments

Comments
 (0)