diff options
author | Netanel Belgazal <netanel@amazon.com> | 2017-06-11 08:42:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-06-11 16:36:45 -0400 |
commit | a77c1aafcc906f657d1a0890c1d898be9ee1d5c9 (patch) | |
tree | a63a4ac44158e16d8a523ac42dc0fefbc98f5fbd | |
parent | b87fa0fafef4b16495740432f4eb8262efa500d0 (diff) |
net: ena: fix rare uncompleted admin command false alarm
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: 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>
-rw-r--r-- | drivers/net/ethernet/amazon/ena/ena_com.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 08d11cede9c9..e1c2fab6292f 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c | |||
@@ -508,15 +508,20 @@ static int ena_com_comp_status_to_errno(u8 comp_status) | |||
508 | static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx, | 508 | static int ena_com_wait_and_process_admin_cq_polling(struct ena_comp_ctx *comp_ctx, |
509 | struct ena_com_admin_queue *admin_queue) | 509 | struct ena_com_admin_queue *admin_queue) |
510 | { | 510 | { |
511 | unsigned long flags; | 511 | unsigned long flags, timeout; |
512 | u32 start_time; | ||
513 | int ret; | 512 | int ret; |
514 | 513 | ||
515 | start_time = ((u32)jiffies_to_usecs(jiffies)); | 514 | timeout = jiffies + ADMIN_CMD_TIMEOUT_US; |
515 | |||
516 | while (1) { | ||
517 | spin_lock_irqsave(&admin_queue->q_lock, flags); | ||
518 | ena_com_handle_admin_completion(admin_queue); | ||
519 | spin_unlock_irqrestore(&admin_queue->q_lock, flags); | ||
516 | 520 | ||
517 | while (comp_ctx->status == ENA_CMD_SUBMITTED) { | 521 | if (comp_ctx->status != ENA_CMD_SUBMITTED) |
518 | if ((((u32)jiffies_to_usecs(jiffies)) - start_time) > | 522 | break; |
519 | ADMIN_CMD_TIMEOUT_US) { | 523 | |
524 | if (time_is_before_jiffies(timeout)) { | ||
520 | pr_err("Wait for completion (polling) timeout\n"); | 525 | pr_err("Wait for completion (polling) timeout\n"); |
521 | /* ENA didn't have any completion */ | 526 | /* ENA didn't have any completion */ |
522 | spin_lock_irqsave(&admin_queue->q_lock, flags); | 527 | 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 | |||
528 | goto err; | 533 | goto err; |
529 | } | 534 | } |
530 | 535 | ||
531 | spin_lock_irqsave(&admin_queue->q_lock, flags); | ||
532 | ena_com_handle_admin_completion(admin_queue); | ||
533 | spin_unlock_irqrestore(&admin_queue->q_lock, flags); | ||
534 | |||
535 | msleep(100); | 536 | msleep(100); |
536 | } | 537 | } |
537 | 538 | ||