]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: ena: fix rare uncompleted admin command false alarm
authorNetanel Belgazal <netanel@amazon.com>
Sun, 11 Jun 2017 12:42:43 +0000 (15:42 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 11 Jun 2017 20:36:45 +0000 (16:36 -0400)
The current flow to detect admin completion is:
while (command_not_completed) {
if (timeout)
error

check_for_completion()
sleep()
   }
So in case the sleep took more than the timeout
(in case the thread/workqueue was not scheduled due to higher priority
task or prolonged VMexit), the driver can detect a stall even if
the completion is present.

The fix changes the order of this function to first check for
completion and only after that check if the timeout expired.

Fixes: 42904aea461f ("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_com.c

index 08d11cede9c972596ee683c5d255fe143b76b9b8..e1c2fab6292f547f1bc6b55a86f05b7060a5e195 100644 (file)
@@ -508,15 +508,20 @@ static int ena_com_comp_status_to_errno(u8 comp_status)
 static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx,
                                                     struct ena_com_admin_queue *admin_queue)
 {
-       unsigned long flags;
-       u32 start_time;
+       unsigned long flags, timeout;
        int ret;
 
-       start_time = ((u32)jiffies_to_usecs(jiffies));
+       timeout = jiffies + ADMIN_CMD_TIMEOUT_US;
+
+       while (1) {
+               spin_lock_irqsave(&admin_queue->q_lock, flags);
+               ena_com_handle_admin_completion(admin_queue);
+               spin_unlock_irqrestore(&admin_queue->q_lock, flags);
 
-       while (comp_ctx->status == ENA_CMD_SUBMITTED) {
-               if ((((u32)jiffies_to_usecs(jiffies)) - start_time) >
-                   ADMIN_CMD_TIMEOUT_US) {
+               if (comp_ctx->status != ENA_CMD_SUBMITTED)
+                       break;
+
+               if (time_is_before_jiffies(timeout)) {
                        pr_err("Wait for completion (polling) timeout\n");
                        /* ENA didn't have any completion */
                        spin_lock_irqsave(&admin_queue->q_lock, flags);
@@ -528,10 +533,6 @@ static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_c
                        goto err;
                }
 
-               spin_lock_irqsave(&admin_queue->q_lock, flags);
-               ena_com_handle_admin_completion(admin_queue);
-               spin_unlock_irqrestore(&admin_queue->q_lock, flags);
-
                msleep(100);
        }