net: ena: fix bug that might cause hang after consecutive open/close interface.
authorNetanel Belgazal <netanel@amazon.com>
Sun, 11 Jun 2017 12:42:44 +0000 (15:42 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 11 Jun 2017 20:36:46 +0000 (16:36 -0400)
Fixing a bug that the driver does not unmask the IO interrupts
in ndo_open():
occasionally, the MSI-X interrupt (for one or more IO queues)
can be masked when ndo_close() was called.
If that is followed by ndo open(),
then the MSI-X will be still masked so no interrupt
will be received by the driver.

Fixes: 1738cd3ed342 ("Add a driver for Amazon Elastic Network Adapters (ENA)")
Signed-off-by: Netanel Belgazal <netanel@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/amazon/ena/ena_netdev.c

index 7c1214d7885566ded4dfc05e85c2ee86b8d3c949..0e3c60c7eccf1004dd79c36aba5055a4355be548 100644 (file)
@@ -1078,6 +1078,26 @@ inline void ena_adjust_intr_moderation(struct ena_ring *rx_ring,
        rx_ring->per_napi_bytes = 0;
 }
 
+static inline void ena_unmask_interrupt(struct ena_ring *tx_ring,
+                                       struct ena_ring *rx_ring)
+{
+       struct ena_eth_io_intr_reg intr_reg;
+
+       /* Update intr register: rx intr delay,
+        * tx intr delay and interrupt unmask
+        */
+       ena_com_update_intr_reg(&intr_reg,
+                               rx_ring->smoothed_interval,
+                               tx_ring->smoothed_interval,
+                               true);
+
+       /* It is a shared MSI-X.
+        * Tx and Rx CQ have pointer to it.
+        * So we use one of them to reach the intr reg
+        */
+       ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg);
+}
+
 static inline void ena_update_ring_numa_node(struct ena_ring *tx_ring,
                                             struct ena_ring *rx_ring)
 {
@@ -1108,7 +1128,6 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
 {
        struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi);
        struct ena_ring *tx_ring, *rx_ring;
-       struct ena_eth_io_intr_reg intr_reg;
 
        u32 tx_work_done;
        u32 rx_work_done;
@@ -1149,22 +1168,9 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
                        if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev))
                                ena_adjust_intr_moderation(rx_ring, tx_ring);
 
-                       /* Update intr register: rx intr delay,
-                        * tx intr delay and interrupt unmask
-                        */
-                       ena_com_update_intr_reg(&intr_reg,
-                                               rx_ring->smoothed_interval,
-                                               tx_ring->smoothed_interval,
-                                               true);
-
-                       /* It is a shared MSI-X.
-                        * Tx and Rx CQ have pointer to it.
-                        * So we use one of them to reach the intr reg
-                        */
-                       ena_com_unmask_intr(rx_ring->ena_com_io_cq, &intr_reg);
+                       ena_unmask_interrupt(tx_ring, rx_ring);
                }
 
-
                ena_update_ring_numa_node(tx_ring, rx_ring);
 
                ret = rx_work_done;
@@ -1485,6 +1491,11 @@ static int ena_up_complete(struct ena_adapter *adapter)
 
        ena_napi_enable_all(adapter);
 
+       /* Enable completion queues interrupt */
+       for (i = 0; i < adapter->num_queues; i++)
+               ena_unmask_interrupt(&adapter->tx_ring[i],
+                                    &adapter->rx_ring[i]);
+
        /* schedule napi in case we had pending packets
         * from the last time we disable napi
         */