184caf800SVasanthakumar Thiagarajan /*
284caf800SVasanthakumar Thiagarajan  * Copyright (c) 2012 Qualcomm Atheros, Inc.
384caf800SVasanthakumar Thiagarajan  *
484caf800SVasanthakumar Thiagarajan  * Permission to use, copy, modify, and/or distribute this software for any
584caf800SVasanthakumar Thiagarajan  * purpose with or without fee is hereby granted, provided that the above
684caf800SVasanthakumar Thiagarajan  * copyright notice and this permission notice appear in all copies.
784caf800SVasanthakumar Thiagarajan  *
884caf800SVasanthakumar Thiagarajan  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
984caf800SVasanthakumar Thiagarajan  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1084caf800SVasanthakumar Thiagarajan  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1184caf800SVasanthakumar Thiagarajan  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1284caf800SVasanthakumar Thiagarajan  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1384caf800SVasanthakumar Thiagarajan  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1484caf800SVasanthakumar Thiagarajan  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1584caf800SVasanthakumar Thiagarajan  */
1684caf800SVasanthakumar Thiagarajan 
1784caf800SVasanthakumar Thiagarajan #include "core.h"
1884caf800SVasanthakumar Thiagarajan #include "cfg80211.h"
1984caf800SVasanthakumar Thiagarajan #include "debug.h"
2084caf800SVasanthakumar Thiagarajan 
2184caf800SVasanthakumar Thiagarajan static void ath6kl_recovery_work(struct work_struct *work)
2284caf800SVasanthakumar Thiagarajan {
2384caf800SVasanthakumar Thiagarajan 	struct ath6kl *ar = container_of(work, struct ath6kl,
2484caf800SVasanthakumar Thiagarajan 					 fw_recovery.recovery_work);
2584caf800SVasanthakumar Thiagarajan 
2684caf800SVasanthakumar Thiagarajan 	ath6kl_init_hw_restart(ar);
2784caf800SVasanthakumar Thiagarajan }
2884caf800SVasanthakumar Thiagarajan 
2984caf800SVasanthakumar Thiagarajan void ath6kl_recovery_err_notify(struct ath6kl *ar, enum ath6kl_fw_err reason)
3084caf800SVasanthakumar Thiagarajan {
3184caf800SVasanthakumar Thiagarajan 	ath6kl_dbg(ATH6KL_DBG_RECOVERY, "Fw error detected, reason:%d\n",
3284caf800SVasanthakumar Thiagarajan 		   reason);
3384caf800SVasanthakumar Thiagarajan 
3484caf800SVasanthakumar Thiagarajan 	set_bit(reason, &ar->fw_recovery.err_reason);
3584caf800SVasanthakumar Thiagarajan 
3684caf800SVasanthakumar Thiagarajan 	if (ar->fw_recovery.enable && ar->state != ATH6KL_STATE_RECOVERY)
3784caf800SVasanthakumar Thiagarajan 		queue_work(ar->ath6kl_wq, &ar->fw_recovery.recovery_work);
3884caf800SVasanthakumar Thiagarajan }
3984caf800SVasanthakumar Thiagarajan 
4084caf800SVasanthakumar Thiagarajan void ath6kl_recovery_init(struct ath6kl *ar)
4184caf800SVasanthakumar Thiagarajan {
4284caf800SVasanthakumar Thiagarajan 	struct ath6kl_fw_recovery *recovery = &ar->fw_recovery;
4384caf800SVasanthakumar Thiagarajan 
4484caf800SVasanthakumar Thiagarajan 	recovery->enable = true;
4584caf800SVasanthakumar Thiagarajan 	INIT_WORK(&recovery->recovery_work, ath6kl_recovery_work);
4684caf800SVasanthakumar Thiagarajan }
4784caf800SVasanthakumar Thiagarajan 
4884caf800SVasanthakumar Thiagarajan void ath6kl_recovery_cleanup(struct ath6kl *ar)
4984caf800SVasanthakumar Thiagarajan {
5084caf800SVasanthakumar Thiagarajan 	ar->fw_recovery.enable = false;
5184caf800SVasanthakumar Thiagarajan 
5284caf800SVasanthakumar Thiagarajan 	cancel_work_sync(&ar->fw_recovery.recovery_work);
5384caf800SVasanthakumar Thiagarajan }
5484caf800SVasanthakumar Thiagarajan 
5584caf800SVasanthakumar Thiagarajan void ath6kl_recovery_suspend(struct ath6kl *ar)
5684caf800SVasanthakumar Thiagarajan {
5784caf800SVasanthakumar Thiagarajan 	ath6kl_recovery_cleanup(ar);
5884caf800SVasanthakumar Thiagarajan 
5984caf800SVasanthakumar Thiagarajan 	/* Process pending fw error detection */
6084caf800SVasanthakumar Thiagarajan 	if (ar->fw_recovery.err_reason)
6184caf800SVasanthakumar Thiagarajan 		ath6kl_init_hw_restart(ar);
6284caf800SVasanthakumar Thiagarajan }
63