ibmvnic: Wait for any pending scrqs entries at driver close
authorNathan Fontenot <nfont@linux.vnet.ibm.com>
Wed, 3 May 2017 18:05:02 +0000 (14:05 -0400)
committerDavid S. Miller <davem@davemloft.net>
Wed, 3 May 2017 15:33:05 +0000 (11:33 -0400)
When closing the ibmvnic driver we need to wait for any pending
sub crq entries to ensure they are handled.

Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ibm/ibmvnic.c

index 2297cf2..a312bc1 100644 (file)
@@ -743,23 +743,6 @@ static int ibmvnic_open(struct net_device *netdev)
        return rc;
 }
 
-static void disable_sub_crqs(struct ibmvnic_adapter *adapter)
-{
-       int i;
-
-       if (adapter->tx_scrq) {
-               for (i = 0; i < adapter->req_tx_queues; i++)
-                       if (adapter->tx_scrq[i])
-                               disable_irq(adapter->tx_scrq[i]->irq);
-       }
-
-       if (adapter->rx_scrq) {
-               for (i = 0; i < adapter->req_rx_queues; i++)
-                       if (adapter->rx_scrq[i])
-                               disable_irq(adapter->rx_scrq[i]->irq);
-       }
-}
-
 static void clean_tx_pools(struct ibmvnic_adapter *adapter)
 {
        struct ibmvnic_tx_pool *tx_pool;
@@ -797,15 +780,39 @@ static int __ibmvnic_close(struct net_device *netdev)
        adapter->state = VNIC_CLOSING;
        netif_tx_stop_all_queues(netdev);
 
-       clean_tx_pools(adapter);
-       disable_sub_crqs(adapter);
-
        if (adapter->napi) {
                for (i = 0; i < adapter->req_rx_queues; i++)
                        napi_disable(&adapter->napi[i]);
        }
 
+       clean_tx_pools(adapter);
+
+       if (adapter->tx_scrq) {
+               for (i = 0; i < adapter->req_tx_queues; i++)
+                       if (adapter->tx_scrq[i]->irq)
+                               disable_irq(adapter->tx_scrq[i]->irq);
+       }
+
        rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_DN);
+       if (rc)
+               return rc;
+
+       if (adapter->rx_scrq) {
+               for (i = 0; i < adapter->req_rx_queues; i++) {
+                       int retries = 10;
+
+                       while (pending_scrq(adapter, adapter->rx_scrq[i])) {
+                               retries--;
+                               mdelay(100);
+
+                               if (retries == 0)
+                                       break;
+                       }
+
+                       if (adapter->rx_scrq[i]->irq)
+                               disable_irq(adapter->rx_scrq[i]->irq);
+               }
+       }
 
        adapter->state = VNIC_CLOSED;
        return rc;