root/drivers/net/wireless/ath/ath6kl/recovery.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ath6kl_recovery_work
  2. ath6kl_recovery_err_notify
  3. ath6kl_recovery_hb_event
  4. ath6kl_recovery_hb_timer
  5. ath6kl_recovery_init
  6. ath6kl_recovery_cleanup
  7. ath6kl_recovery_suspend
  8. ath6kl_recovery_resume

   1 /*
   2  * Copyright (c) 2012 Qualcomm Atheros, Inc.
   3  *
   4  * Permission to use, copy, modify, and/or distribute this software for any
   5  * purpose with or without fee is hereby granted, provided that the above
   6  * copyright notice and this permission notice appear in all copies.
   7  *
   8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15  */
  16 
  17 #include "core.h"
  18 #include "cfg80211.h"
  19 #include "debug.h"
  20 
  21 static void ath6kl_recovery_work(struct work_struct *work)
  22 {
  23         struct ath6kl *ar = container_of(work, struct ath6kl,
  24                                          fw_recovery.recovery_work);
  25 
  26         ar->state = ATH6KL_STATE_RECOVERY;
  27 
  28         del_timer_sync(&ar->fw_recovery.hb_timer);
  29 
  30         ath6kl_init_hw_restart(ar);
  31 
  32         ar->state = ATH6KL_STATE_ON;
  33         clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
  34 
  35         ar->fw_recovery.err_reason = 0;
  36 
  37         if (ar->fw_recovery.hb_poll)
  38                 mod_timer(&ar->fw_recovery.hb_timer, jiffies +
  39                           msecs_to_jiffies(ar->fw_recovery.hb_poll));
  40 }
  41 
  42 void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
  43 {
  44         if (!ar->fw_recovery.enable)
  45                 return;
  46 
  47         ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Fw error detected, reason:%d\n",
  48                    reason);
  49 
  50         set_bit(reason, &ar->fw_recovery.err_reason);
  51 
  52         if (!test_bit(RECOVERY_CLEANUP, &ar->flag) &&
  53             ar->state != ATH6KL_STATE_RECOVERY)
  54                 queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
  55 }
  56 
  57 void ath6kl_recovery_hb_event(struct ath6kl *ar, u32 cookie)
  58 {
  59         if (cookie == ar->fw_recovery.seq_num)
  60                 ar->fw_recovery.hb_pending = false;
  61 }
  62 
  63 static void ath6kl_recovery_hb_timer(struct timer_list *t)
  64 {
  65         struct ath6kl *ar = from_timer(ar, t, fw_recovery.hb_timer);
  66         int err;
  67 
  68         if (test_bit(RECOVERY_CLEANUP, &ar->flag) ||
  69             (ar->state == ATH6KL_STATE_RECOVERY))
  70                 return;
  71 
  72         if (ar->fw_recovery.hb_pending)
  73                 ar->fw_recovery.hb_misscnt++;
  74         else
  75                 ar->fw_recovery.hb_misscnt = 0;
  76 
  77         if (ar->fw_recovery.hb_misscnt > ATH6KL_HB_RESP_MISS_THRES) {
  78                 ar->fw_recovery.hb_misscnt = 0;
  79                 ar->fw_recovery.seq_num = 0;
  80                 ar->fw_recovery.hb_pending = false;
  81                 ath6kl_recovery_err_notify(ar, ATH6KL_FW_HB_RESP_FAILURE);
  82                 return;
  83         }
  84 
  85         ar->fw_recovery.seq_num++;
  86         ar->fw_recovery.hb_pending = true;
  87 
  88         err = ath6kl_wmi_get_challenge_resp_cmd(ar->wmi,
  89                                                 ar->fw_recovery.seq_num, 0);
  90         if (err)
  91                 ath6kl_warn("Failed to send hb challenge request, err:%d\n",
  92                             err);
  93 
  94         mod_timer(&ar->fw_recovery.hb_timer, jiffies +
  95                   msecs_to_jiffies(ar->fw_recovery.hb_poll));
  96 }
  97 
  98 void ath6kl_recovery_init(struct ath6kl *ar)
  99 {
 100         struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;
 101 
 102         clear_bit(RECOVERY_CLEANUP, &ar->flag);
 103         INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
 104         recovery->seq_num = 0;
 105         recovery->hb_misscnt = 0;
 106         ar->fw_recovery.hb_pending = false;
 107         timer_setup(&ar->fw_recovery.hb_timer, ath6kl_recovery_hb_timer,
 108                     TIMER_DEFERRABLE);
 109 
 110         if (ar->fw_recovery.hb_poll)
 111                 mod_timer(&ar->fw_recovery.hb_timer, jiffies +
 112                           msecs_to_jiffies(ar->fw_recovery.hb_poll));
 113 }
 114 
 115 void ath6kl_recovery_cleanup(struct ath6kl *ar)
 116 {
 117         if (!ar->fw_recovery.enable)
 118                 return;
 119 
 120         set_bit(RECOVERY_CLEANUP, &ar->flag);
 121 
 122         del_timer_sync(&ar->fw_recovery.hb_timer);
 123         cancel_work_sync(&ar->fw_recovery.recovery_work);
 124 }
 125 
 126 void ath6kl_recovery_suspend(struct ath6kl *ar)
 127 {
 128         if (!ar->fw_recovery.enable)
 129                 return;
 130 
 131         ath6kl_recovery_cleanup(ar);
 132 
 133         if (!ar->fw_recovery.err_reason)
 134                 return;
 135 
 136         /* Process pending fw error detection */
 137         ar->fw_recovery.err_reason = 0;
 138         WARN_ON(ar->state != ATH6KL_STATE_ON);
 139         ar->state = ATH6KL_STATE_RECOVERY;
 140         ath6kl_init_hw_restart(ar);
 141         ar->state = ATH6KL_STATE_ON;
 142 }
 143 
 144 void ath6kl_recovery_resume(struct ath6kl *ar)
 145 {
 146         if (!ar->fw_recovery.enable)
 147                 return;
 148 
 149         clear_bit(RECOVERY_CLEANUP, &ar->flag);
 150 
 151         if (!ar->fw_recovery.hb_poll)
 152                 return;
 153 
 154         ar->fw_recovery.hb_pending = false;
 155         ar->fw_recovery.seq_num = 0;
 156         ar->fw_recovery.hb_misscnt = 0;
 157         mod_timer(&ar->fw_recovery.hb_timer,
 158                   jiffies + msecs_to_jiffies(ar->fw_recovery.hb_poll));
 159 }

/* [<][>][^][v][top][bottom][index][help] */