From: Shengzhen Li <s...@marvell.com>

commit 5781fc29dbbd3ee5e11c1bf4fa6696ae89d19840 upstream

As interrupt is read in interrupt handler as well as interrupt processing
thread, we observed a corner case issue for MSI in which interrupt gets
processed twice.

This patch moves interrupt reading code for MSI mode from
mwifiex_interrupt_status() to mwifiex_pcie_process_int() to avoid the
issue.

Signed-off-by: Shengzhen Li <s...@marvell.com>
Signed-off-by: Amitkumar Karwar <akar...@marvell.com>
Signed-off-by: Kalle Valo <kv...@codeaurora.org>
[Kevin: replace mwifiex_dbg() with pr_debug() and fix 'card'
undeclared error]
Signed-off-by: Kevin Hao <kexin....@windriver.com>
---
 drivers/net/wireless/mwifiex/pcie.c | 49 ++++++++++++++++++++++++++++++++++---
 1 file changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/pcie.c 
b/drivers/net/wireless/mwifiex/pcie.c
index dab899d48236..9979eeff228e 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -2034,6 +2034,14 @@ static void mwifiex_interrupt_status(struct 
mwifiex_adapter *adapter)
 {
        u32 pcie_ireg;
        unsigned long flags;
+       struct pcie_service_card *card = adapter->card;
+
+       if (card->msi_enable) {
+               spin_lock_irqsave(&adapter->int_lock, flags);
+               adapter->int_status = 1;
+               spin_unlock_irqrestore(&adapter->int_lock, flags);
+               return;
+       }
 
        if (!mwifiex_pcie_ok_to_access_hw(adapter))
                return;
@@ -2121,15 +2129,42 @@ exit:
 static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
 {
        int ret;
-       u32 pcie_ireg;
+       u32 pcie_ireg = 0;
        unsigned long flags;
+       struct pcie_service_card *card = adapter->card;
 
        spin_lock_irqsave(&adapter->int_lock, flags);
-       /* Clear out unused interrupts */
-       pcie_ireg = adapter->int_status;
+       if (!card->msi_enable) {
+               /* Clear out unused interrupts */
+               pcie_ireg = adapter->int_status;
+       }
        adapter->int_status = 0;
        spin_unlock_irqrestore(&adapter->int_lock, flags);
 
+       if (card->msi_enable) {
+               if (mwifiex_pcie_ok_to_access_hw(adapter)) {
+                       if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
+                                            &pcie_ireg)) {
+                               pr_debug("Read register failed\n");
+                               return -1;
+                       }
+
+                       if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) {
+                               if (mwifiex_write_reg(adapter,
+                                                     PCIE_HOST_INT_STATUS,
+                                                     ~pcie_ireg)) {
+                                       pr_debug("Write register failed\n");
+                                       return -1;
+                               }
+                               if (!adapter->pps_uapsd_mode &&
+                                   adapter->ps_state == PS_STATE_SLEEP) {
+                                       adapter->ps_state = PS_STATE_AWAKE;
+                                       adapter->pm_wakeup_fw_try = false;
+                                       del_timer(&adapter->wakeup_timer);
+                               }
+                       }
+               }
+       }
        while (pcie_ireg & HOST_INTR_MASK) {
                if (pcie_ireg & HOST_INTR_DNLD_DONE) {
                        pcie_ireg &= ~HOST_INTR_DNLD_DONE;
@@ -2166,6 +2201,12 @@ static int mwifiex_process_int_status(struct 
mwifiex_adapter *adapter)
                                return ret;
                }
 
+               if (card->msi_enable) {
+                       spin_lock_irqsave(&adapter->int_lock, flags);
+                       adapter->int_status = 0;
+                       spin_unlock_irqrestore(&adapter->int_lock, flags);
+               }
+
                if (mwifiex_pcie_ok_to_access_hw(adapter)) {
                        if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS,
                                             &pcie_ireg)) {
@@ -2188,7 +2229,7 @@ static int mwifiex_process_int_status(struct 
mwifiex_adapter *adapter)
        }
        dev_dbg(adapter->dev, "info: cmd_sent=%d data_sent=%d\n",
                adapter->cmd_sent, adapter->data_sent);
-       if (adapter->ps_state != PS_STATE_SLEEP)
+       if (!card->msi_enable && adapter->ps_state != PS_STATE_SLEEP)
                mwifiex_pcie_enable_host_int(adapter);
 
        return 0;
-- 
2.9.3

-- 
_______________________________________________
linux-yocto mailing list
linux-yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/linux-yocto

Reply via email to