1*dd4f32aeSBjoern A. Zeeb // SPDX-License-Identifier: BSD-3-Clause-Clear 2*dd4f32aeSBjoern A. Zeeb /* 3*dd4f32aeSBjoern A. Zeeb * Copyright (c) 2020 The Linux Foundation. All rights reserved. 4*dd4f32aeSBjoern A. Zeeb */ 5*dd4f32aeSBjoern A. Zeeb 6*dd4f32aeSBjoern A. Zeeb #include <linux/delay.h> 7*dd4f32aeSBjoern A. Zeeb 8*dd4f32aeSBjoern A. Zeeb #include "mac.h" 9*dd4f32aeSBjoern A. Zeeb #include "core.h" 10*dd4f32aeSBjoern A. Zeeb #include "hif.h" 11*dd4f32aeSBjoern A. Zeeb #include "debug.h" 12*dd4f32aeSBjoern A. Zeeb #include "wmi.h" 13*dd4f32aeSBjoern A. Zeeb #include "wow.h" 14*dd4f32aeSBjoern A. Zeeb 15*dd4f32aeSBjoern A. Zeeb int ath11k_wow_enable(struct ath11k_base *ab) 16*dd4f32aeSBjoern A. Zeeb { 17*dd4f32aeSBjoern A. Zeeb struct ath11k *ar = ath11k_ab_to_ar(ab, 0); 18*dd4f32aeSBjoern A. Zeeb int i, ret; 19*dd4f32aeSBjoern A. Zeeb 20*dd4f32aeSBjoern A. Zeeb clear_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags); 21*dd4f32aeSBjoern A. Zeeb 22*dd4f32aeSBjoern A. Zeeb for (i = 0; i < ATH11K_WOW_RETRY_NUM; i++) { 23*dd4f32aeSBjoern A. Zeeb reinit_completion(&ab->htc_suspend); 24*dd4f32aeSBjoern A. Zeeb 25*dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_wow_enable(ar); 26*dd4f32aeSBjoern A. Zeeb if (ret) { 27*dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to issue wow enable: %d\n", ret); 28*dd4f32aeSBjoern A. Zeeb return ret; 29*dd4f32aeSBjoern A. Zeeb } 30*dd4f32aeSBjoern A. Zeeb 31*dd4f32aeSBjoern A. Zeeb ret = wait_for_completion_timeout(&ab->htc_suspend, 3 * HZ); 32*dd4f32aeSBjoern A. Zeeb if (ret == 0) { 33*dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, 34*dd4f32aeSBjoern A. Zeeb "timed out while waiting for htc suspend completion\n"); 35*dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT; 36*dd4f32aeSBjoern A. Zeeb } 37*dd4f32aeSBjoern A. Zeeb 38*dd4f32aeSBjoern A. Zeeb if (test_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags)) 39*dd4f32aeSBjoern A. Zeeb /* success, suspend complete received */ 40*dd4f32aeSBjoern A. Zeeb return 0; 41*dd4f32aeSBjoern A. Zeeb 42*dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "htc suspend not complete, retrying (try %d)\n", 43*dd4f32aeSBjoern A. Zeeb i); 44*dd4f32aeSBjoern A. Zeeb msleep(ATH11K_WOW_RETRY_WAIT_MS); 45*dd4f32aeSBjoern A. Zeeb } 46*dd4f32aeSBjoern A. Zeeb 47*dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "htc suspend not complete, failing after %d tries\n", i); 48*dd4f32aeSBjoern A. Zeeb 49*dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT; 50*dd4f32aeSBjoern A. Zeeb } 51*dd4f32aeSBjoern A. Zeeb 52*dd4f32aeSBjoern A. Zeeb int ath11k_wow_wakeup(struct ath11k_base *ab) 53*dd4f32aeSBjoern A. Zeeb { 54*dd4f32aeSBjoern A. Zeeb struct ath11k *ar = ath11k_ab_to_ar(ab, 0); 55*dd4f32aeSBjoern A. Zeeb int ret; 56*dd4f32aeSBjoern A. Zeeb 57*dd4f32aeSBjoern A. Zeeb reinit_completion(&ab->wow.wakeup_completed); 58*dd4f32aeSBjoern A. Zeeb 59*dd4f32aeSBjoern A. Zeeb ret = ath11k_wmi_wow_host_wakeup_ind(ar); 60*dd4f32aeSBjoern A. Zeeb if (ret) { 61*dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "failed to send wow wakeup indication: %d\n", 62*dd4f32aeSBjoern A. Zeeb ret); 63*dd4f32aeSBjoern A. Zeeb return ret; 64*dd4f32aeSBjoern A. Zeeb } 65*dd4f32aeSBjoern A. Zeeb 66*dd4f32aeSBjoern A. Zeeb ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ); 67*dd4f32aeSBjoern A. Zeeb if (ret == 0) { 68*dd4f32aeSBjoern A. Zeeb ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n"); 69*dd4f32aeSBjoern A. Zeeb return -ETIMEDOUT; 70*dd4f32aeSBjoern A. Zeeb } 71*dd4f32aeSBjoern A. Zeeb 72*dd4f32aeSBjoern A. Zeeb return 0; 73*dd4f32aeSBjoern A. Zeeb } 74