mwifiex: add wakeup timer based recovery mechanism
authorAmitkumar Karwar <akarwar@marvell.com>
Wed, 31 Dec 2014 10:36:41 +0000 (02:36 -0800)
committerKalle Valo <kvalo@codeaurora.org>
Tue, 6 Jan 2015 19:19:44 +0000 (21:19 +0200)
If host fails to wakeup the firmware, we will trigger card reset
after 3 second timeout.

Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/sta_event.c
drivers/net/wireless/mwifiex/usb.c

index a3dd601a495a1e405df682022eed451a7229d5a9..524692a59d4a6fd601cbc0c97437324a4407453f 100644 (file)
@@ -52,6 +52,18 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv)
        return 0;
 }
 
+static void wakeup_timer_fn(unsigned long data)
+{
+       struct mwifiex_adapter *adapter = (struct mwifiex_adapter *)data;
+
+       dev_err(adapter->dev, "Firmware wakeup failed\n");
+       adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
+       mwifiex_cancel_all_pending_cmd(adapter);
+
+       if (adapter->if_ops.card_reset)
+               adapter->if_ops.card_reset(adapter);
+}
+
 /*
  * This function initializes the private structure and sets default
  * values to the members.
@@ -285,6 +297,9 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
        adapter->ext_scan = true;
        adapter->key_api_major_ver = 0;
        adapter->key_api_minor_ver = 0;
+
+       setup_timer(&adapter->wakeup_timer, wakeup_timer_fn,
+                   (unsigned long)adapter);
 }
 
 /*
@@ -391,6 +406,7 @@ mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter)
                return;
        }
 
+       del_timer(&adapter->wakeup_timer);
        mwifiex_cancel_all_pending_cmd(adapter);
 
        /* Free lock variables */
index 2d4047f4be175385cdea31e950fda69fc38dc1d8..119e87574e838a015da056e52ca859d09e937ad7 100644 (file)
@@ -237,6 +237,7 @@ process_start:
                    (is_command_pending(adapter) ||
                     !mwifiex_wmm_lists_empty(adapter))) {
                        adapter->pm_wakeup_fw_try = true;
+                       mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3));
                        adapter->if_ops.wakeup(adapter);
                        continue;
                }
@@ -244,6 +245,7 @@ process_start:
                if (IS_CARD_RX_RCVD(adapter)) {
                        adapter->data_received = false;
                        adapter->pm_wakeup_fw_try = false;
+                       del_timer_sync(&adapter->wakeup_timer);
                        if (adapter->ps_state == PS_STATE_SLEEP)
                                adapter->ps_state = PS_STATE_AWAKE;
                } else {
index f9279399226a91b6da1256fc06b8d42d44a4edbb..55273eefb785567522379921ab050f4f87145e12 100644 (file)
@@ -830,6 +830,7 @@ struct mwifiex_adapter {
        u16 gen_null_pkt;
        u16 pps_uapsd_mode;
        u32 pm_wakeup_fw_try;
+       struct timer_list wakeup_timer;
        u8 is_hs_configured;
        struct mwifiex_hs_config_param hs_cfg;
        u8 hs_activated;
index c3a20f94f3c99f86fbbfdc6b23faba01b54ee5e5..10e4a93d3d5693d82d72df021d6b55dcbf2c6cff 100644 (file)
@@ -2064,6 +2064,7 @@ static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter)
                                 * state until cookie is set */
                                adapter->ps_state = PS_STATE_AWAKE;
                                adapter->pm_wakeup_fw_try = false;
+                               del_timer(&adapter->wakeup_timer);
                }
        }
 }
index fbec95bbc10f199d6c170b866d0843f26fae7973..419e35f1dbf3779770056311d20eecaf73e06e31 100644 (file)
@@ -312,6 +312,8 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                                        adapter->ps_state = PS_STATE_AWAKE;
                                        adapter->pm_wakeup_card_req = false;
                                        adapter->pm_wakeup_fw_try = false;
+                                       mod_timer(&adapter->wakeup_timer,
+                                                 jiffies + (HZ*3));
                                        break;
                                }
                                if (!mwifiex_send_null_packet
@@ -326,6 +328,7 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
                adapter->ps_state = PS_STATE_AWAKE;
                adapter->pm_wakeup_card_req = false;
                adapter->pm_wakeup_fw_try = false;
+               del_timer_sync(&adapter->wakeup_timer);
 
                break;
 
index 8ae7a8586811f0be9daf074112b2e6b7880e6b88..199b43f89e0196e2239e5a11e66684ce23715d05 100644 (file)
@@ -990,6 +990,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
 {
        /* Simulation of HS_AWAKE event */
        adapter->pm_wakeup_fw_try = false;
+       del_timer_sync(&adapter->wakeup_timer);
        adapter->pm_wakeup_card_req = false;
        adapter->ps_state = PS_STATE_AWAKE;