aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2014-02-18 15:41:56 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-03-23 21:38:13 -0700
commit02395fb0f850f04631988ddf532dc74f538d35de (patch)
treebca50304bd40056af2aa86c05bd6d3b2f74d4bf6 /drivers/net/wireless
parentef8f92b153230230d437e32573c0560bae9a8f13 (diff)
mwifiex: fix cmd and Tx data timeout issue for PCIe cards
commit 1c97560f6d751a620978504a4a888c631192b71a upstream. We are sending sleep confirm done interrupt in the middle of sleep handshake. There is a corner case when Tx done interrupt is received from firmware during sleep handshake due to which host and firmware power states go out of sync causing cmd and Tx data timeout problem. Hence sleep confirm done interrupt is sent at the end of sleep handshake to fix the problem. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c28
1 files changed, 11 insertions, 17 deletions
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 1662b99dd148..801c709656f9 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -1515,6 +1515,14 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
if (adapter->ps_state == PS_STATE_SLEEP_CFM) {
mwifiex_process_sleep_confirm_resp(adapter, skb->data,
skb->len);
+ mwifiex_pcie_enable_host_int(adapter);
+ if (mwifiex_write_reg(adapter,
+ PCIE_CPU_INT_EVENT,
+ CPU_INTR_SLEEP_CFM_DONE)) {
+ dev_warn(adapter->dev,
+ "Write register failed\n");
+ return -1;
+ }
while (reg->sleep_cookie && (count++ < 10) &&
mwifiex_pcie_ok_to_access_hw(adapter))
usleep_range(50, 60);
@@ -1985,23 +1993,9 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
adapter->int_status |= pcie_ireg;
spin_unlock_irqrestore(&adapter->int_lock, flags);
- if (pcie_ireg & HOST_INTR_CMD_DONE) {
- if ((adapter->ps_state == PS_STATE_SLEEP_CFM) ||
- (adapter->ps_state == PS_STATE_SLEEP)) {
- mwifiex_pcie_enable_host_int(adapter);
- if (mwifiex_write_reg(adapter,
- PCIE_CPU_INT_EVENT,
- CPU_INTR_SLEEP_CFM_DONE)
- ) {
- dev_warn(adapter->dev,
- "Write register failed\n");
- return;
-
- }
- }
- } else if (!adapter->pps_uapsd_mode &&
- adapter->ps_state == PS_STATE_SLEEP &&
- mwifiex_pcie_ok_to_access_hw(adapter)) {
+ if (!adapter->pps_uapsd_mode &&
+ adapter->ps_state == PS_STATE_SLEEP &&
+ mwifiex_pcie_ok_to_access_hw(adapter)) {
/* Potentially for PCIe we could get other
* interrupts like shared. Don't change power
* state until cookie is set */