ibmvnic: Fix error handling when registering long-term-mapped buffers
authorThomas Falcon <tlfalcon@linux.vnet.ibm.com>
Wed, 21 Jun 2017 19:53:01 +0000 (14:53 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 22 Jun 2017 15:31:34 +0000 (11:31 -0400)
The patch stores the return code of the REQUEST_MAP_RSP sub-CRQ command
in the private data structure, where it can be later checked during
device open or a reset.

In the case of a reset, the mapping request to the vNIC Server may fail,
especially in the case of a partition migration. The driver attempts to
handle this by re-allocating the buffer and re-sending the mapping request.

The original error handling implementation was removed. The separate
function handling the REQUEST_MAP response message was also removed,
since it is now simple enough to be handled in the ibmvnic_handle_crq
function.

Signed-off-by: Thomas Falcon <tlfalcon@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/ibm/ibmvnic.h

index 013509544632d93b8e7edc2dfaf11132fb5befa6..aab69dd018d4c811cc81ecf876cb4b06419e101b 100644 (file)
@@ -163,16 +163,6 @@ static long h_reg_sub_crq(unsigned long unit_address, unsigned long token,
        return rc;
 }
 
        return rc;
 }
 
-static void reset_long_term_buff(struct ibmvnic_adapter *adapter,
-                                struct ibmvnic_long_term_buff *ltb)
-{
-       memset(ltb->buff, 0, ltb->size);
-
-       init_completion(&adapter->fw_done);
-       send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
-       wait_for_completion(&adapter->fw_done);
-}
-
 static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
                                struct ibmvnic_long_term_buff *ltb, int size)
 {
 static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
                                struct ibmvnic_long_term_buff *ltb, int size)
 {
@@ -193,6 +183,12 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter,
        send_request_map(adapter, ltb->addr,
                         ltb->size, ltb->map_id);
        wait_for_completion(&adapter->fw_done);
        send_request_map(adapter, ltb->addr,
                         ltb->size, ltb->map_id);
        wait_for_completion(&adapter->fw_done);
+
+       if (adapter->fw_done_rc) {
+               dev_err(dev, "Couldn't map long term buffer,rc = %d\n",
+                       adapter->fw_done_rc);
+               return -1;
+       }
        return 0;
 }
 
        return 0;
 }
 
@@ -210,6 +206,24 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter,
        dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
 }
 
        dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr);
 }
 
+static int reset_long_term_buff(struct ibmvnic_adapter *adapter,
+                               struct ibmvnic_long_term_buff *ltb)
+{
+       memset(ltb->buff, 0, ltb->size);
+
+       init_completion(&adapter->fw_done);
+       send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id);
+       wait_for_completion(&adapter->fw_done);
+
+       if (adapter->fw_done_rc) {
+               dev_info(&adapter->vdev->dev,
+                        "Reset failed, attempting to free and reallocate buffer\n");
+               free_long_term_buff(adapter, ltb);
+               return alloc_long_term_buff(adapter, ltb, ltb->size);
+       }
+       return 0;
+}
+
 static void deactivate_rx_pools(struct ibmvnic_adapter *adapter)
 {
        int i;
 static void deactivate_rx_pools(struct ibmvnic_adapter *adapter)
 {
        int i;
@@ -366,13 +380,15 @@ static int reset_rx_pools(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_rx_pool *rx_pool;
        int rx_scrqs;
 {
        struct ibmvnic_rx_pool *rx_pool;
        int rx_scrqs;
-       int i, j;
+       int i, j, rc;
 
        rx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
        for (i = 0; i < rx_scrqs; i++) {
                rx_pool = &adapter->rx_pool[i];
 
 
        rx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
        for (i = 0; i < rx_scrqs; i++) {
                rx_pool = &adapter->rx_pool[i];
 
-               reset_long_term_buff(adapter, &rx_pool->long_term_buff);
+               rc = reset_long_term_buff(adapter, &rx_pool->long_term_buff);
+               if (rc)
+                       return rc;
 
                for (j = 0; j < rx_pool->size; j++)
                        rx_pool->free_map[j] = j;
 
                for (j = 0; j < rx_pool->size; j++)
                        rx_pool->free_map[j] = j;
@@ -494,13 +510,15 @@ static int reset_tx_pools(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_tx_pool *tx_pool;
        int tx_scrqs;
 {
        struct ibmvnic_tx_pool *tx_pool;
        int tx_scrqs;
-       int i, j;
+       int i, j, rc;
 
        tx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
        for (i = 0; i < tx_scrqs; i++) {
                tx_pool = &adapter->tx_pool[i];
 
 
        tx_scrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
        for (i = 0; i < tx_scrqs; i++) {
                tx_pool = &adapter->tx_pool[i];
 
-               reset_long_term_buff(adapter, &tx_pool->long_term_buff);
+               rc = reset_long_term_buff(adapter, &tx_pool->long_term_buff);
+               if (rc)
+                       return rc;
 
                memset(tx_pool->tx_buff, 0,
                       adapter->req_tx_entries_per_subcrq *
 
                memset(tx_pool->tx_buff, 0,
                       adapter->req_tx_entries_per_subcrq *
@@ -3075,36 +3093,6 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq,
        return 0;
 }
 
        return 0;
 }
 
-static void handle_request_map_rsp(union ibmvnic_crq *crq,
-                                  struct ibmvnic_adapter *adapter)
-{
-       struct device *dev = &adapter->vdev->dev;
-       u8 map_id = crq->request_map_rsp.map_id;
-       int tx_subcrqs;
-       int rx_subcrqs;
-       long rc;
-       int i;
-
-       tx_subcrqs = be32_to_cpu(adapter->login_rsp_buf->num_txsubm_subcrqs);
-       rx_subcrqs = be32_to_cpu(adapter->login_rsp_buf->num_rxadd_subcrqs);
-
-       rc = crq->request_map_rsp.rc.code;
-       if (rc) {
-               dev_err(dev, "Error %ld in REQUEST_MAP_RSP\n", rc);
-               adapter->map_id--;
-               /* need to find and zero tx/rx_pool map_id */
-               for (i = 0; i < tx_subcrqs; i++) {
-                       if (adapter->tx_pool[i].long_term_buff.map_id == map_id)
-                               adapter->tx_pool[i].long_term_buff.map_id = 0;
-               }
-               for (i = 0; i < rx_subcrqs; i++) {
-                       if (adapter->rx_pool[i].long_term_buff.map_id == map_id)
-                               adapter->rx_pool[i].long_term_buff.map_id = 0;
-               }
-       }
-       complete(&adapter->fw_done);
-}
-
 static void handle_request_unmap_rsp(union ibmvnic_crq *crq,
                                     struct ibmvnic_adapter *adapter)
 {
 static void handle_request_unmap_rsp(union ibmvnic_crq *crq,
                                     struct ibmvnic_adapter *adapter)
 {
@@ -3385,7 +3373,8 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq,
                handle_query_map_rsp(crq, adapter);
                break;
        case REQUEST_MAP_RSP:
                handle_query_map_rsp(crq, adapter);
                break;
        case REQUEST_MAP_RSP:
-               handle_request_map_rsp(crq, adapter);
+               adapter->fw_done_rc = crq->request_map_rsp.rc.code;
+               complete(&adapter->fw_done);
                break;
        case REQUEST_UNMAP_RSP:
                handle_request_unmap_rsp(crq, adapter);
                break;
        case REQUEST_UNMAP_RSP:
                handle_request_unmap_rsp(crq, adapter);
index 2d525c761b75c56de92a0d1926ac5397ba25af7c..8eff6e15f4bbc51f75a026ef566ff009b3464234 100644 (file)
@@ -988,6 +988,7 @@ struct ibmvnic_adapter {
        spinlock_t error_list_lock;
 
        struct completion fw_done;
        spinlock_t error_list_lock;
 
        struct completion fw_done;
+       int fw_done_rc;
 
        /* partner capabilities */
        u64 min_tx_queues;
 
        /* partner capabilities */
        u64 min_tx_queues;