wil6210: ignore HALP ICR if already handled
authorMaya Erez <merez@codeaurora.org>
Fri, 22 Feb 2019 14:21:04 +0000 (16:21 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 28 Feb 2019 09:24:59 +0000 (11:24 +0200)
HALP ICR is set as long as the FW should stay awake.
To prevent its multiple handling the driver masks this IRQ bit.
However, if there is a different MISC ICR before the driver clears
this bit, there is a risk of race condition between HALP mask and
unmask. This race leads to HALP timeout, in case it is mistakenly
masked.
Add an atomic flag to indicate if HALP ICR should be handled.

Signed-off-by: Maya Erez <merez@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/ath/wil6210/interrupt.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/wil6210.h

index 5d287a8e1b458a8aca674275a55c007df944e4c3..3f5bd177d55ff0e9eb88fb2b80d439d05f035752 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -575,10 +575,14 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
        }
 
        if (isr & BIT_DMA_EP_MISC_ICR_HALP) {
-               wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
-               wil6210_mask_halp(wil);
                isr &= ~BIT_DMA_EP_MISC_ICR_HALP;
-               complete(&wil->halp.comp);
+               if (wil->halp.handle_icr) {
+                       /* no need to handle HALP ICRs until next vote */
+                       wil->halp.handle_icr = false;
+                       wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
+                       wil6210_mask_halp(wil);
+                       complete(&wil->halp.comp);
+               }
        }
 
        wil->isr_misc = isr;
index 10de16ab7d6996799a24e6ab5534f816d0a93567..277abfdf3322c5b8a59b08093a7a9219a9105514 100644 (file)
@@ -1919,11 +1919,14 @@ void wil_halp_vote(struct wil6210_priv *wil)
 
        if (++wil->halp.ref_cnt == 1) {
                reinit_completion(&wil->halp.comp);
+               /* mark to IRQ context to handle HALP ICR */
+               wil->halp.handle_icr = true;
                wil6210_set_halp(wil);
                rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
                if (!rc) {
                        wil_err(wil, "HALP vote timed out\n");
                        /* Mask HALP as done in case the interrupt is raised */
+                       wil->halp.handle_icr = false;
                        wil6210_mask_halp(wil);
                } else {
                        wil_dbg_irq(wil,
index 85dca1b05283fb29d610f6f161086696223035db..e1b1039b13abd009297abf5e841d1c6f825e759b 100644 (file)
@@ -794,6 +794,7 @@ struct wil_halp {
        struct mutex            lock; /* protect halp ref_cnt */
        unsigned int            ref_cnt;
        struct completion       comp;
+       u8                      handle_icr;
 };
 
 struct wil_blob_wrapper {