|
@@ -718,23 +718,6 @@ static int init_tx_pools(struct net_device *netdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void release_error_buffers(struct ibmvnic_adapter *adapter)
|
|
|
-{
|
|
|
- struct device *dev = &adapter->vdev->dev;
|
|
|
- struct ibmvnic_error_buff *error_buff, *tmp;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- spin_lock_irqsave(&adapter->error_list_lock, flags);
|
|
|
- list_for_each_entry_safe(error_buff, tmp, &adapter->errors, list) {
|
|
|
- list_del(&error_buff->list);
|
|
|
- dma_unmap_single(dev, error_buff->dma, error_buff->len,
|
|
|
- DMA_FROM_DEVICE);
|
|
|
- kfree(error_buff->buff);
|
|
|
- kfree(error_buff);
|
|
|
- }
|
|
|
- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
|
|
|
-}
|
|
|
-
|
|
|
static void ibmvnic_napi_enable(struct ibmvnic_adapter *adapter)
|
|
|
{
|
|
|
int i;
|
|
@@ -896,7 +879,6 @@ static void release_resources(struct ibmvnic_adapter *adapter)
|
|
|
release_tx_pools(adapter);
|
|
|
release_rx_pools(adapter);
|
|
|
|
|
|
- release_error_buffers(adapter);
|
|
|
release_napi(adapter);
|
|
|
release_login_rsp_buffer(adapter);
|
|
|
}
|
|
@@ -3843,132 +3825,41 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter)
|
|
|
ibmvnic_send_crq(adapter, &crq);
|
|
|
}
|
|
|
|
|
|
-static void handle_error_info_rsp(union ibmvnic_crq *crq,
|
|
|
- struct ibmvnic_adapter *adapter)
|
|
|
-{
|
|
|
- struct device *dev = &adapter->vdev->dev;
|
|
|
- struct ibmvnic_error_buff *error_buff, *tmp;
|
|
|
- unsigned long flags;
|
|
|
- bool found = false;
|
|
|
- int i;
|
|
|
-
|
|
|
- if (!crq->request_error_rsp.rc.code) {
|
|
|
- dev_info(dev, "Request Error Rsp returned with rc=%x\n",
|
|
|
- crq->request_error_rsp.rc.code);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- spin_lock_irqsave(&adapter->error_list_lock, flags);
|
|
|
- list_for_each_entry_safe(error_buff, tmp, &adapter->errors, list)
|
|
|
- if (error_buff->error_id == crq->request_error_rsp.error_id) {
|
|
|
- found = true;
|
|
|
- list_del(&error_buff->list);
|
|
|
- break;
|
|
|
- }
|
|
|
- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
|
|
|
-
|
|
|
- if (!found) {
|
|
|
- dev_err(dev, "Couldn't find error id %x\n",
|
|
|
- be32_to_cpu(crq->request_error_rsp.error_id));
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- dev_err(dev, "Detailed info for error id %x:",
|
|
|
- be32_to_cpu(crq->request_error_rsp.error_id));
|
|
|
-
|
|
|
- for (i = 0; i < error_buff->len; i++) {
|
|
|
- pr_cont("%02x", (int)error_buff->buff[i]);
|
|
|
- if (i % 8 == 7)
|
|
|
- pr_cont(" ");
|
|
|
- }
|
|
|
- pr_cont("\n");
|
|
|
-
|
|
|
- dma_unmap_single(dev, error_buff->dma, error_buff->len,
|
|
|
- DMA_FROM_DEVICE);
|
|
|
- kfree(error_buff->buff);
|
|
|
- kfree(error_buff);
|
|
|
-}
|
|
|
-
|
|
|
-static void request_error_information(struct ibmvnic_adapter *adapter,
|
|
|
- union ibmvnic_crq *err_crq)
|
|
|
-{
|
|
|
- struct device *dev = &adapter->vdev->dev;
|
|
|
- struct net_device *netdev = adapter->netdev;
|
|
|
- struct ibmvnic_error_buff *error_buff;
|
|
|
- unsigned long timeout = msecs_to_jiffies(30000);
|
|
|
- union ibmvnic_crq crq;
|
|
|
- unsigned long flags;
|
|
|
- int rc, detail_len;
|
|
|
-
|
|
|
- error_buff = kmalloc(sizeof(*error_buff), GFP_ATOMIC);
|
|
|
- if (!error_buff)
|
|
|
- return;
|
|
|
-
|
|
|
- detail_len = be32_to_cpu(err_crq->error_indication.detail_error_sz);
|
|
|
- error_buff->buff = kmalloc(detail_len, GFP_ATOMIC);
|
|
|
- if (!error_buff->buff) {
|
|
|
- kfree(error_buff);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- error_buff->dma = dma_map_single(dev, error_buff->buff, detail_len,
|
|
|
- DMA_FROM_DEVICE);
|
|
|
- if (dma_mapping_error(dev, error_buff->dma)) {
|
|
|
- netdev_err(netdev, "Couldn't map error buffer\n");
|
|
|
- kfree(error_buff->buff);
|
|
|
- kfree(error_buff);
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- error_buff->len = detail_len;
|
|
|
- error_buff->error_id = err_crq->error_indication.error_id;
|
|
|
-
|
|
|
- spin_lock_irqsave(&adapter->error_list_lock, flags);
|
|
|
- list_add_tail(&error_buff->list, &adapter->errors);
|
|
|
- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
|
|
|
-
|
|
|
- memset(&crq, 0, sizeof(crq));
|
|
|
- crq.request_error_info.first = IBMVNIC_CRQ_CMD;
|
|
|
- crq.request_error_info.cmd = REQUEST_ERROR_INFO;
|
|
|
- crq.request_error_info.ioba = cpu_to_be32(error_buff->dma);
|
|
|
- crq.request_error_info.len = cpu_to_be32(detail_len);
|
|
|
- crq.request_error_info.error_id = err_crq->error_indication.error_id;
|
|
|
-
|
|
|
- rc = ibmvnic_send_crq(adapter, &crq);
|
|
|
- if (rc) {
|
|
|
- netdev_err(netdev, "failed to request error information\n");
|
|
|
- goto err_info_fail;
|
|
|
- }
|
|
|
-
|
|
|
- if (!wait_for_completion_timeout(&adapter->init_done, timeout)) {
|
|
|
- netdev_err(netdev, "timeout waiting for error information\n");
|
|
|
- goto err_info_fail;
|
|
|
+static const char *ibmvnic_fw_err_cause(u16 cause)
|
|
|
+{
|
|
|
+ switch (cause) {
|
|
|
+ case ADAPTER_PROBLEM:
|
|
|
+ return "adapter problem";
|
|
|
+ case BUS_PROBLEM:
|
|
|
+ return "bus problem";
|
|
|
+ case FW_PROBLEM:
|
|
|
+ return "firmware problem";
|
|
|
+ case DD_PROBLEM:
|
|
|
+ return "device driver problem";
|
|
|
+ case EEH_RECOVERY:
|
|
|
+ return "EEH recovery";
|
|
|
+ case FW_UPDATED:
|
|
|
+ return "firmware updated";
|
|
|
+ case LOW_MEMORY:
|
|
|
+ return "low Memory";
|
|
|
+ default:
|
|
|
+ return "unknown";
|
|
|
}
|
|
|
-
|
|
|
- return;
|
|
|
-
|
|
|
-err_info_fail:
|
|
|
- spin_lock_irqsave(&adapter->error_list_lock, flags);
|
|
|
- list_del(&error_buff->list);
|
|
|
- spin_unlock_irqrestore(&adapter->error_list_lock, flags);
|
|
|
-
|
|
|
- kfree(error_buff->buff);
|
|
|
- kfree(error_buff);
|
|
|
}
|
|
|
|
|
|
static void handle_error_indication(union ibmvnic_crq *crq,
|
|
|
struct ibmvnic_adapter *adapter)
|
|
|
{
|
|
|
struct device *dev = &adapter->vdev->dev;
|
|
|
+ u16 cause;
|
|
|
|
|
|
- dev_err(dev, "Firmware reports %serror id %x, cause %d\n",
|
|
|
- crq->error_indication.flags
|
|
|
- & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
|
|
|
- be32_to_cpu(crq->error_indication.error_id),
|
|
|
- be16_to_cpu(crq->error_indication.error_cause));
|
|
|
+ cause = be16_to_cpu(crq->error_indication.error_cause);
|
|
|
|
|
|
- if (be32_to_cpu(crq->error_indication.error_id))
|
|
|
- request_error_information(adapter, crq);
|
|
|
+ dev_warn_ratelimited(dev,
|
|
|
+ "Firmware reports %serror, cause: %s. Starting recovery...\n",
|
|
|
+ crq->error_indication.flags
|
|
|
+ & IBMVNIC_FATAL_ERROR ? "FATAL " : "",
|
|
|
+ ibmvnic_fw_err_cause(cause));
|
|
|
|
|
|
if (crq->error_indication.flags & IBMVNIC_FATAL_ERROR)
|
|
|
ibmvnic_reset(adapter, VNIC_RESET_FATAL);
|
|
@@ -4468,10 +4359,6 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
|
|
|
netdev_dbg(netdev, "Got Error Indication\n");
|
|
|
handle_error_indication(crq, adapter);
|
|
|
break;
|
|
|
- case REQUEST_ERROR_RSP:
|
|
|
- netdev_dbg(netdev, "Got Error Detail Response\n");
|
|
|
- handle_error_info_rsp(crq, adapter);
|
|
|
- break;
|
|
|
case REQUEST_STATISTICS_RSP:
|
|
|
netdev_dbg(netdev, "Got Statistics Response\n");
|
|
|
complete(&adapter->stats_done);
|
|
@@ -4830,9 +4717,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)
|
|
|
|
|
|
spin_lock_init(&adapter->stats_lock);
|
|
|
|
|
|
- INIT_LIST_HEAD(&adapter->errors);
|
|
|
- spin_lock_init(&adapter->error_list_lock);
|
|
|
-
|
|
|
INIT_WORK(&adapter->ibmvnic_reset, __ibmvnic_reset);
|
|
|
INIT_LIST_HEAD(&adapter->rwi_list);
|
|
|
mutex_init(&adapter->reset_lock);
|