aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@linux.vnet.ibm.com>2017-04-21 15:38:52 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-24 12:52:12 -0400
commit2f9de9bac625ae08e9ea132e8dc08cfbe9fb67d2 (patch)
tree64880cd4753c66bb88022449a2313d4468890519
parent6052d5e2a1961b59dd942b52d3bf2b395d023644 (diff)
ibmvnic: Only retrieve error info if present
When handling a fatal error in the driver, there can be additional error information provided by the vios. This information is not always present, so only retrieve the additional error information when present. Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/ibm/ibmvnic.c71
1 files changed, 51 insertions, 20 deletions
diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c
index 0f3595439293..cc34bf9be405 100644
--- a/drivers/net/ethernet/ibm/ibmvnic.c
+++ b/drivers/net/ethernet/ibm/ibmvnic.c
@@ -2361,25 +2361,22 @@ static void handle_error_info_rsp(union ibmvnic_crq *crq,
2361 kfree(error_buff); 2361 kfree(error_buff);
2362} 2362}
2363 2363
2364static void handle_error_indication(union ibmvnic_crq *crq, 2364static void request_error_information(struct ibmvnic_adapter *adapter,
2365 struct ibmvnic_adapter *adapter) 2365 union ibmvnic_crq *err_crq)
2366{ 2366{
2367 int detail_len = be32_to_cpu(crq->error_indication.detail_error_sz);
2368 struct device *dev = &adapter->vdev->dev; 2367 struct device *dev = &adapter->vdev->dev;
2368 struct net_device *netdev = adapter->netdev;
2369 struct ibmvnic_error_buff *error_buff; 2369 struct ibmvnic_error_buff *error_buff;
2370 union ibmvnic_crq new_crq; 2370 unsigned long timeout = msecs_to_jiffies(30000);
2371 union ibmvnic_crq crq;
2371 unsigned long flags; 2372 unsigned long flags;
2372 2373 int rc, detail_len;
2373 dev_err(dev, "Firmware reports %serror id %x, cause %d\n",
2374 crq->error_indication.
2375 flags & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
2376 be32_to_cpu(crq->error_indication.error_id),
2377 be16_to_cpu(crq->error_indication.error_cause));
2378 2374
2379 error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC); 2375 error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC);
2380 if (!error_buff) 2376 if (!error_buff)
2381 return; 2377 return;
2382 2378
2379 detail_len = be32_to_cpu(err_crq->error_indication.detail_error_sz);
2383 error_buff->buff = kmalloc(detail_len, GFP_ATOMIC); 2380 error_buff->buff = kmalloc(detail_len, GFP_ATOMIC);
2384 if (!error_buff->buff) { 2381 if (!error_buff->buff) {
2385 kfree(error_buff); 2382 kfree(error_buff);
@@ -2389,27 +2386,61 @@ static void handle_error_indication(union ibmvnic_crq *crq,
2389 error_buff->dma = dma_map_single(dev, error_buff->buff, detail_len, 2386 error_buff->dma = dma_map_single(dev, error_buff->buff, detail_len,
2390 DMA_FROM_DEVICE); 2387 DMA_FROM_DEVICE);
2391 if (dma_mapping_error(dev, error_buff->dma)) { 2388 if (dma_mapping_error(dev, error_buff->dma)) {
2392 if (!firmware_has_feature(FW_FEATURE_CMO)) 2389 netdev_err(netdev, "Couldn't map error buffer\n");
2393 dev_err(dev, "Couldn't map error buffer\n");
2394 kfree(error_buff->buff); 2390 kfree(error_buff->buff);
2395 kfree(error_buff); 2391 kfree(error_buff);
2396 return; 2392 return;
2397 } 2393 }
2398 2394
2399 error_buff->len = detail_len; 2395 error_buff->len = detail_len;
2400 error_buff->error_id = crq->error_indication.error_id; 2396 error_buff->error_id = err_crq->error_indication.error_id;
2401 2397
2402 spin_lock_irqsave(&adapter->error_list_lock, flags); 2398 spin_lock_irqsave(&adapter->error_list_lock, flags);
2403 list_add_tail(&error_buff->list, &adapter->errors); 2399 list_add_tail(&error_buff->list, &adapter->errors);
2404 spin_unlock_irqrestore(&adapter->error_list_lock, flags); 2400 spin_unlock_irqrestore(&adapter->error_list_lock, flags);
2405 2401
2406 memset(&new_crq, 0, sizeof(new_crq)); 2402 memset(&crq, 0, sizeof(crq));
2407 new_crq.request_error_info.first = IBMVNIC_CRQ_CMD; 2403 crq.request_error_info.first = IBMVNIC_CRQ_CMD;
2408 new_crq.request_error_info.cmd = REQUEST_ERROR_INFO; 2404 crq.request_error_info.cmd = REQUEST_ERROR_INFO;
2409 new_crq.request_error_info.ioba = cpu_to_be32(error_buff->dma); 2405 crq.request_error_info.ioba = cpu_to_be32(error_buff->dma);
2410 new_crq.request_error_info.len = cpu_to_be32(detail_len); 2406 crq.request_error_info.len = cpu_to_be32(detail_len);
2411 new_crq.request_error_info.error_id = crq->error_indication.error_id; 2407 crq.request_error_info.error_id = err_crq->error_indication.error_id;
2412 ibmvnic_send_crq(adapter, &new_crq); 2408
2409 rc = ibmvnic_send_crq(adapter, &crq);
2410 if (rc) {
2411 netdev_err(netdev, "failed to request error information\n");
2412 goto err_info_fail;
2413 }
2414
2415 if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
2416 netdev_err(netdev, "timeout waiting for error information\n");
2417 goto err_info_fail;
2418 }
2419
2420 return;
2421
2422err_info_fail:
2423 spin_lock_irqsave(&adapter->error_list_lock, flags);
2424 list_del(&error_buff->list);
2425 spin_unlock_irqrestore(&adapter->error_list_lock, flags);
2426
2427 kfree(error_buff->buff);
2428 kfree(error_buff);
2429}
2430
2431static void handle_error_indication(union ibmvnic_crq *crq,
2432 struct ibmvnic_adapter *adapter)
2433{
2434 struct device *dev = &adapter->vdev->dev;
2435
2436 dev_err(dev, "Firmware reports %serror id %x, cause %d\n",
2437 crq->error_indication.flags
2438 & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
2439 be32_to_cpu(crq->error_indication.error_id),
2440 be16_to_cpu(crq->error_indication.error_cause));
2441
2442 if (be32_to_cpu(crq->error_indication.error_id))
2443 request_error_information(adapter, crq);
2413} 2444}
2414 2445
2415static void handle_change_mac_rsp(union ibmvnic_crq *crq, 2446static void handle_change_mac_rsp(union ibmvnic_crq *crq,