]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wil6210: ignore HALP ICR if already handled
authorMaya Erez <merez@codeaurora.org>
Fri, 22 Feb 2019 14:21:04 +0000 (16:21 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 21 Apr 2020 07:03:12 +0000 (09:03 +0200)
commit 979c9d8d01c482b1befb44dc639ecb907b5a37bd upstream.

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>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/ath/wil6210/interrupt.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/wil6210.h

index 0655cd8845142c244a260252d01b3d74e003d062..d161dc930313d2ec0d67cd1bd5839d4fa7a2b2c8 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
@@ -590,10 +590,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 10673fa9388ec0b266d4963f8e008fe7dc27c8ee..28d2bfd0fde79de5236a57e114926af9276637a1 100644 (file)
@@ -1814,11 +1814,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 75fe1a3b70466165db6865957880bb7ccc613b6f..6a05f59ee58e9347e273e6ee20e3a29556cf2a55 100644 (file)
@@ -778,6 +778,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 {