| From 1c97560f6d751a620978504a4a888c631192b71a Mon Sep 17 00:00:00 2001 |
| From: Amitkumar Karwar <akarwar@marvell.com> |
| Date: Tue, 18 Feb 2014 15:41:56 -0800 |
| Subject: mwifiex: fix cmd and Tx data timeout issue for PCIe cards |
| |
| From: Amitkumar Karwar <akarwar@marvell.com> |
| |
| 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> |
| |
| --- |
| drivers/net/wireless/mwifiex/pcie.c | 28 +++++++++++----------------- |
| 1 file changed, 11 insertions(+), 17 deletions(-) |
| |
| --- a/drivers/net/wireless/mwifiex/pcie.c |
| +++ b/drivers/net/wireless/mwifiex/pcie.c |
| @@ -1531,6 +1531,14 @@ static int mwifiex_pcie_process_cmd_comp |
| 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); |
| @@ -1999,23 +2007,9 @@ static void mwifiex_interrupt_status(str |
| 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 */ |