aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaya Erez <merez@codeaurora.org>2019-02-22 09:21:04 -0500
committerKalle Valo <kvalo@codeaurora.org>2019-02-28 04:24:59 -0500
commit979c9d8d01c482b1befb44dc639ecb907b5a37bd (patch)
treef178f48c23d8bec9a167259c96624fe8bff3b14e
parenta380eb5736c04942c158b22af04467eb21c27045 (diff)
wil6210: ignore HALP ICR if already handled
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>
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c12
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h1
3 files changed, 12 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 5d287a8e1b45..3f5bd177d55f 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. 2 * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
4 * 4 *
5 * Permission to use, copy, modify, and/or distribute this software for any 5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 6 * 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)
575 } 575 }
576 576
577 if (isr & BIT_DMA_EP_MISC_ICR_HALP) { 577 if (isr & BIT_DMA_EP_MISC_ICR_HALP) {
578 wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
579 wil6210_mask_halp(wil);
580 isr &= ~BIT_DMA_EP_MISC_ICR_HALP; 578 isr &= ~BIT_DMA_EP_MISC_ICR_HALP;
581 complete(&wil->halp.comp); 579 if (wil->halp.handle_icr) {
580 /* no need to handle HALP ICRs until next vote */
581 wil->halp.handle_icr = false;
582 wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n");
583 wil6210_mask_halp(wil);
584 complete(&wil->halp.comp);
585 }
582 } 586 }
583 587
584 wil->isr_misc = isr; 588 wil->isr_misc = isr;
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 10de16ab7d69..277abfdf3322 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -1919,11 +1919,14 @@ void wil_halp_vote(struct wil6210_priv *wil)
1919 1919
1920 if (++wil->halp.ref_cnt == 1) { 1920 if (++wil->halp.ref_cnt == 1) {
1921 reinit_completion(&wil->halp.comp); 1921 reinit_completion(&wil->halp.comp);
1922 /* mark to IRQ context to handle HALP ICR */
1923 wil->halp.handle_icr = true;
1922 wil6210_set_halp(wil); 1924 wil6210_set_halp(wil);
1923 rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); 1925 rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies);
1924 if (!rc) { 1926 if (!rc) {
1925 wil_err(wil, "HALP vote timed out\n"); 1927 wil_err(wil, "HALP vote timed out\n");
1926 /* Mask HALP as done in case the interrupt is raised */ 1928 /* Mask HALP as done in case the interrupt is raised */
1929 wil->halp.handle_icr = false;
1927 wil6210_mask_halp(wil); 1930 wil6210_mask_halp(wil);
1928 } else { 1931 } else {
1929 wil_dbg_irq(wil, 1932 wil_dbg_irq(wil,
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 85dca1b05283..e1b1039b13ab 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -794,6 +794,7 @@ struct wil_halp {
794 struct mutex lock; /* protect halp ref_cnt */ 794 struct mutex lock; /* protect halp ref_cnt */
795 unsigned int ref_cnt; 795 unsigned int ref_cnt;
796 struct completion comp; 796 struct completion comp;
797 u8 handle_icr;
797}; 798};
798 799
799struct wil_blob_wrapper { 800struct wil_blob_wrapper {