diff options
author | Avinash Patil <patila@marvell.com> | 2013-01-04 00:21:28 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2013-01-07 15:18:29 -0500 |
commit | 659c4788611f725ede2def6e4db5d8d4a59b93b5 (patch) | |
tree | 659d0d8fb6f9f4db383197dc8f287566ec3730d3 /drivers/net | |
parent | 6ba1eafed183c6e0886d3483c8acac4efe1e95db (diff) |
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>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/mwifiex/pcie.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 13fbc4eb1595..e4c2cfdd049c 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -1594,39 +1594,40 @@ exit: | |||
1594 | static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | 1594 | static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) |
1595 | { | 1595 | { |
1596 | int ret; | 1596 | int ret; |
1597 | u32 pcie_ireg = 0; | 1597 | u32 pcie_ireg; |
1598 | unsigned long flags; | 1598 | unsigned long flags; |
1599 | 1599 | ||
1600 | spin_lock_irqsave(&adapter->int_lock, flags); | 1600 | spin_lock_irqsave(&adapter->int_lock, flags); |
1601 | /* Clear out unused interrupts */ | 1601 | /* Clear out unused interrupts */ |
1602 | adapter->int_status &= HOST_INTR_MASK; | 1602 | pcie_ireg = adapter->int_status; |
1603 | adapter->int_status = 0; | ||
1603 | spin_unlock_irqrestore(&adapter->int_lock, flags); | 1604 | spin_unlock_irqrestore(&adapter->int_lock, flags); |
1604 | 1605 | ||
1605 | while (adapter->int_status & HOST_INTR_MASK) { | 1606 | while (pcie_ireg & HOST_INTR_MASK) { |
1606 | if (adapter->int_status & HOST_INTR_DNLD_DONE) { | 1607 | if (pcie_ireg & HOST_INTR_DNLD_DONE) { |
1607 | adapter->int_status &= ~HOST_INTR_DNLD_DONE; | 1608 | pcie_ireg &= ~HOST_INTR_DNLD_DONE; |
1608 | if (adapter->data_sent) { | 1609 | if (adapter->data_sent) { |
1609 | dev_dbg(adapter->dev, "info: DATA sent intr\n"); | 1610 | dev_dbg(adapter->dev, "info: DATA sent intr\n"); |
1610 | adapter->data_sent = false; | 1611 | adapter->data_sent = false; |
1611 | } | 1612 | } |
1612 | } | 1613 | } |
1613 | if (adapter->int_status & HOST_INTR_UPLD_RDY) { | 1614 | if (pcie_ireg & HOST_INTR_UPLD_RDY) { |
1614 | adapter->int_status &= ~HOST_INTR_UPLD_RDY; | 1615 | pcie_ireg &= ~HOST_INTR_UPLD_RDY; |
1615 | dev_dbg(adapter->dev, "info: Rx DATA\n"); | 1616 | dev_dbg(adapter->dev, "info: Rx DATA\n"); |
1616 | ret = mwifiex_pcie_process_recv_data(adapter); | 1617 | ret = mwifiex_pcie_process_recv_data(adapter); |
1617 | if (ret) | 1618 | if (ret) |
1618 | return ret; | 1619 | return ret; |
1619 | } | 1620 | } |
1620 | if (adapter->int_status & HOST_INTR_EVENT_RDY) { | 1621 | if (pcie_ireg & HOST_INTR_EVENT_RDY) { |
1621 | adapter->int_status &= ~HOST_INTR_EVENT_RDY; | 1622 | pcie_ireg &= ~HOST_INTR_EVENT_RDY; |
1622 | dev_dbg(adapter->dev, "info: Rx EVENT\n"); | 1623 | dev_dbg(adapter->dev, "info: Rx EVENT\n"); |
1623 | ret = mwifiex_pcie_process_event_ready(adapter); | 1624 | ret = mwifiex_pcie_process_event_ready(adapter); |
1624 | if (ret) | 1625 | if (ret) |
1625 | return ret; | 1626 | return ret; |
1626 | } | 1627 | } |
1627 | 1628 | ||
1628 | if (adapter->int_status & HOST_INTR_CMD_DONE) { | 1629 | if (pcie_ireg & HOST_INTR_CMD_DONE) { |
1629 | adapter->int_status &= ~HOST_INTR_CMD_DONE; | 1630 | pcie_ireg &= ~HOST_INTR_CMD_DONE; |
1630 | if (adapter->cmd_sent) { | 1631 | if (adapter->cmd_sent) { |
1631 | dev_dbg(adapter->dev, | 1632 | dev_dbg(adapter->dev, |
1632 | "info: CMD sent Interrupt\n"); | 1633 | "info: CMD sent Interrupt\n"); |
@@ -1654,8 +1655,6 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1654 | "Write register failed\n"); | 1655 | "Write register failed\n"); |
1655 | return -1; | 1656 | return -1; |
1656 | } | 1657 | } |
1657 | adapter->int_status |= pcie_ireg; | ||
1658 | adapter->int_status &= HOST_INTR_MASK; | ||
1659 | } | 1658 | } |
1660 | 1659 | ||
1661 | } | 1660 | } |