Commit 659c4788 authored by Avinash Patil's avatar Avinash Patil Committed by John W. Linville

mwifiex: access interrupt status only while holding lock

This patch fixes a bug for few instances where PCIe interrupt
status variable is accessed without holding spin lock.
This can result into missing interrupts.

Fix this by copying interrupt status to a local variable and
then using it for calling specific routine.
Signed-off-by: default avatarAvinash Patil <patila@marvell.com>
Signed-off-by: default avatarBing Zhao <bzhao@marvell.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6ba1eafe
...@@ -1594,39 +1594,40 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) ...@@ -1594,39 +1594,40 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
{ {
int ret; int ret;
u32 pcie_ireg = 0; u32 pcie_ireg;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&adapter->int_lock, flags); spin_lock_irqsave(&adapter->int_lock, flags);
/* Clear out unused interrupts */ /* Clear out unused interrupts */
adapter->int_status &= HOST_INTR_MASK; pcie_ireg = adapter->int_status;
adapter->int_status = 0;
spin_unlock_irqrestore(&adapter->int_lock, flags); spin_unlock_irqrestore(&adapter->int_lock, flags);
while (adapter->int_status & HOST_INTR_MASK) { while (pcie_ireg & HOST_INTR_MASK) {
if (adapter->int_status & HOST_INTR_DNLD_DONE) { if (pcie_ireg & HOST_INTR_DNLD_DONE) {
adapter->int_status &= ~HOST_INTR_DNLD_DONE; pcie_ireg &= ~HOST_INTR_DNLD_DONE;
if (adapter->data_sent) { if (adapter->data_sent) {
dev_dbg(adapter->dev, "info: DATA sent intr\n"); dev_dbg(adapter->dev, "info: DATA sent intr\n");
adapter->data_sent = false; adapter->data_sent = false;
} }
} }
if (adapter->int_status & HOST_INTR_UPLD_RDY) { if (pcie_ireg & HOST_INTR_UPLD_RDY) {
adapter->int_status &= ~HOST_INTR_UPLD_RDY; pcie_ireg &= ~HOST_INTR_UPLD_RDY;
dev_dbg(adapter->dev, "info: Rx DATA\n"); dev_dbg(adapter->dev, "info: Rx DATA\n");
ret = mwifiex_pcie_process_recv_data(adapter); ret = mwifiex_pcie_process_recv_data(adapter);
if (ret) if (ret)
return ret; return ret;
} }
if (adapter->int_status & HOST_INTR_EVENT_RDY) { if (pcie_ireg & HOST_INTR_EVENT_RDY) {
adapter->int_status &= ~HOST_INTR_EVENT_RDY; pcie_ireg &= ~HOST_INTR_EVENT_RDY;
dev_dbg(adapter->dev, "info: Rx EVENT\n"); dev_dbg(adapter->dev, "info: Rx EVENT\n");
ret = mwifiex_pcie_process_event_ready(adapter); ret = mwifiex_pcie_process_event_ready(adapter);
if (ret) if (ret)
return ret; return ret;
} }
if (adapter->int_status & HOST_INTR_CMD_DONE) { if (pcie_ireg & HOST_INTR_CMD_DONE) {
adapter->int_status &= ~HOST_INTR_CMD_DONE; pcie_ireg &= ~HOST_INTR_CMD_DONE;
if (adapter->cmd_sent) { if (adapter->cmd_sent) {
dev_dbg(adapter->dev, dev_dbg(adapter->dev,
"info: CMD sent Interrupt\n"); "info: CMD sent Interrupt\n");
...@@ -1654,8 +1655,6 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) ...@@ -1654,8 +1655,6 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter)
"Write register failed\n"); "Write register failed\n");
return -1; return -1;
} }
adapter->int_status |= pcie_ireg;
adapter->int_status &= HOST_INTR_MASK;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment