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: Avinash Patil <patila@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
6ba1eafed1
commit
659c478861
|
@ -1594,39 +1594,40 @@ exit:
|
||||||
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)
|
||||||
"Write register failed\n");
|
"Write register failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
adapter->int_status |= pcie_ireg;
|
|
||||||
adapter->int_status &= HOST_INTR_MASK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue