cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wow.c (22336B)


      1// SPDX-License-Identifier: BSD-3-Clause-Clear
      2/*
      3 * Copyright (c) 2020 The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/delay.h>
      7
      8#include "mac.h"
      9
     10#include <net/mac80211.h>
     11#include "core.h"
     12#include "hif.h"
     13#include "debug.h"
     14#include "wmi.h"
     15#include "wow.h"
     16#include "dp_rx.h"
     17
     18static const struct wiphy_wowlan_support ath11k_wowlan_support = {
     19	.flags = WIPHY_WOWLAN_DISCONNECT |
     20		 WIPHY_WOWLAN_MAGIC_PKT |
     21		 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
     22		 WIPHY_WOWLAN_GTK_REKEY_FAILURE,
     23	.pattern_min_len = WOW_MIN_PATTERN_SIZE,
     24	.pattern_max_len = WOW_MAX_PATTERN_SIZE,
     25	.max_pkt_offset = WOW_MAX_PKT_OFFSET,
     26};
     27
     28int ath11k_wow_enable(struct ath11k_base *ab)
     29{
     30	struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
     31	int i, ret;
     32
     33	clear_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
     34
     35	for (i = 0; i < ATH11K_WOW_RETRY_NUM; i++) {
     36		reinit_completion(&ab->htc_suspend);
     37
     38		ret = ath11k_wmi_wow_enable(ar);
     39		if (ret) {
     40			ath11k_warn(ab, "failed to issue wow enable: %d\n", ret);
     41			return ret;
     42		}
     43
     44		ret = wait_for_completion_timeout(&ab->htc_suspend, 3 * HZ);
     45		if (ret == 0) {
     46			ath11k_warn(ab,
     47				    "timed out while waiting for htc suspend completion\n");
     48			return -ETIMEDOUT;
     49		}
     50
     51		if (test_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags))
     52			/* success, suspend complete received */
     53			return 0;
     54
     55		ath11k_warn(ab, "htc suspend not complete, retrying (try %d)\n",
     56			    i);
     57		msleep(ATH11K_WOW_RETRY_WAIT_MS);
     58	}
     59
     60	ath11k_warn(ab, "htc suspend not complete, failing after %d tries\n", i);
     61
     62	return -ETIMEDOUT;
     63}
     64
     65int ath11k_wow_wakeup(struct ath11k_base *ab)
     66{
     67	struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
     68	int ret;
     69
     70	reinit_completion(&ab->wow.wakeup_completed);
     71
     72	ret = ath11k_wmi_wow_host_wakeup_ind(ar);
     73	if (ret) {
     74		ath11k_warn(ab, "failed to send wow wakeup indication: %d\n",
     75			    ret);
     76		return ret;
     77	}
     78
     79	ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ);
     80	if (ret == 0) {
     81		ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n");
     82		return -ETIMEDOUT;
     83	}
     84
     85	return 0;
     86}
     87
     88static int ath11k_wow_vif_cleanup(struct ath11k_vif *arvif)
     89{
     90	struct ath11k *ar = arvif->ar;
     91	int i, ret;
     92
     93	for (i = 0; i < WOW_EVENT_MAX; i++) {
     94		ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0);
     95		if (ret) {
     96			ath11k_warn(ar->ab, "failed to issue wow wakeup for event %s on vdev %i: %d\n",
     97				    wow_wakeup_event(i), arvif->vdev_id, ret);
     98			return ret;
     99		}
    100	}
    101
    102	for (i = 0; i < ar->wow.max_num_patterns; i++) {
    103		ret = ath11k_wmi_wow_del_pattern(ar, arvif->vdev_id, i);
    104		if (ret) {
    105			ath11k_warn(ar->ab, "failed to delete wow pattern %d for vdev %i: %d\n",
    106				    i, arvif->vdev_id, ret);
    107			return ret;
    108		}
    109	}
    110
    111	return 0;
    112}
    113
    114static int ath11k_wow_cleanup(struct ath11k *ar)
    115{
    116	struct ath11k_vif *arvif;
    117	int ret;
    118
    119	lockdep_assert_held(&ar->conf_mutex);
    120
    121	list_for_each_entry(arvif, &ar->arvifs, list) {
    122		ret = ath11k_wow_vif_cleanup(arvif);
    123		if (ret) {
    124			ath11k_warn(ar->ab, "failed to clean wow wakeups on vdev %i: %d\n",
    125				    arvif->vdev_id, ret);
    126			return ret;
    127		}
    128	}
    129
    130	return 0;
    131}
    132
    133/* Convert a 802.3 format to a 802.11 format.
    134 *         +------------+-----------+--------+----------------+
    135 * 802.3:  |dest mac(6B)|src mac(6B)|type(2B)|     body...    |
    136 *         +------------+-----------+--------+----------------+
    137 *                |__         |_______    |____________  |________
    138 *                   |                |                |          |
    139 *         +--+------------+----+-----------+---------------+-----------+
    140 * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)|  8B  |type(2B)|  body...  |
    141 *         +--+------------+----+-----------+---------------+-----------+
    142 */
    143static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
    144					     const struct cfg80211_pkt_pattern *old)
    145{
    146	u8 hdr_8023_pattern[ETH_HLEN] = {};
    147	u8 hdr_8023_bit_mask[ETH_HLEN] = {};
    148	u8 hdr_80211_pattern[WOW_HDR_LEN] = {};
    149	u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {};
    150
    151	int total_len = old->pkt_offset + old->pattern_len;
    152	int hdr_80211_end_offset;
    153
    154	struct ieee80211_hdr_3addr *new_hdr_pattern =
    155		(struct ieee80211_hdr_3addr *)hdr_80211_pattern;
    156	struct ieee80211_hdr_3addr *new_hdr_mask =
    157		(struct ieee80211_hdr_3addr *)hdr_80211_bit_mask;
    158	struct ethhdr *old_hdr_pattern = (struct ethhdr *)hdr_8023_pattern;
    159	struct ethhdr *old_hdr_mask = (struct ethhdr *)hdr_8023_bit_mask;
    160	int hdr_len = sizeof(*new_hdr_pattern);
    161
    162	struct rfc1042_hdr *new_rfc_pattern =
    163		(struct rfc1042_hdr *)(hdr_80211_pattern + hdr_len);
    164	struct rfc1042_hdr *new_rfc_mask =
    165		(struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len);
    166	int rfc_len = sizeof(*new_rfc_pattern);
    167
    168	memcpy(hdr_8023_pattern + old->pkt_offset,
    169	       old->pattern, ETH_HLEN - old->pkt_offset);
    170	memcpy(hdr_8023_bit_mask + old->pkt_offset,
    171	       old->mask, ETH_HLEN - old->pkt_offset);
    172
    173	/* Copy destination address */
    174	memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN);
    175	memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN);
    176
    177	/* Copy source address */
    178	memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN);
    179	memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN);
    180
    181	/* Copy logic link type */
    182	memcpy(&new_rfc_pattern->snap_type,
    183	       &old_hdr_pattern->h_proto,
    184	       sizeof(old_hdr_pattern->h_proto));
    185	memcpy(&new_rfc_mask->snap_type,
    186	       &old_hdr_mask->h_proto,
    187	       sizeof(old_hdr_mask->h_proto));
    188
    189	/* Compute new pkt_offset */
    190	if (old->pkt_offset < ETH_ALEN)
    191		new->pkt_offset = old->pkt_offset +
    192			offsetof(struct ieee80211_hdr_3addr, addr1);
    193	else if (old->pkt_offset < offsetof(struct ethhdr, h_proto))
    194		new->pkt_offset = old->pkt_offset +
    195			offsetof(struct ieee80211_hdr_3addr, addr3) -
    196			offsetof(struct ethhdr, h_source);
    197	else
    198		new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN;
    199
    200	/* Compute new hdr end offset */
    201	if (total_len > ETH_HLEN)
    202		hdr_80211_end_offset = hdr_len + rfc_len;
    203	else if (total_len > offsetof(struct ethhdr, h_proto))
    204		hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN;
    205	else if (total_len > ETH_ALEN)
    206		hdr_80211_end_offset = total_len - ETH_ALEN +
    207			offsetof(struct ieee80211_hdr_3addr, addr3);
    208	else
    209		hdr_80211_end_offset = total_len +
    210			offsetof(struct ieee80211_hdr_3addr, addr1);
    211
    212	new->pattern_len = hdr_80211_end_offset - new->pkt_offset;
    213
    214	memcpy((u8 *)new->pattern,
    215	       hdr_80211_pattern + new->pkt_offset,
    216	       new->pattern_len);
    217	memcpy((u8 *)new->mask,
    218	       hdr_80211_bit_mask + new->pkt_offset,
    219	       new->pattern_len);
    220
    221	if (total_len > ETH_HLEN) {
    222		/* Copy frame body */
    223		memcpy((u8 *)new->pattern + new->pattern_len,
    224		       (void *)old->pattern + ETH_HLEN - old->pkt_offset,
    225		       total_len - ETH_HLEN);
    226		memcpy((u8 *)new->mask + new->pattern_len,
    227		       (void *)old->mask + ETH_HLEN - old->pkt_offset,
    228		       total_len - ETH_HLEN);
    229
    230		new->pattern_len += total_len - ETH_HLEN;
    231	}
    232}
    233
    234static int ath11k_wmi_pno_check_and_convert(struct ath11k *ar, u32 vdev_id,
    235					    struct cfg80211_sched_scan_request *nd_config,
    236					    struct wmi_pno_scan_req *pno)
    237{
    238	int i, j;
    239	u8 ssid_len;
    240
    241	pno->enable = 1;
    242	pno->vdev_id = vdev_id;
    243	pno->uc_networks_count = nd_config->n_match_sets;
    244
    245	if (!pno->uc_networks_count ||
    246	    pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS)
    247		return -EINVAL;
    248
    249	if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX)
    250		return -EINVAL;
    251
    252	/* Filling per profile params */
    253	for (i = 0; i < pno->uc_networks_count; i++) {
    254		ssid_len = nd_config->match_sets[i].ssid.ssid_len;
    255
    256		if (ssid_len == 0 || ssid_len > 32)
    257			return -EINVAL;
    258
    259		pno->a_networks[i].ssid.ssid_len = ssid_len;
    260
    261		memcpy(pno->a_networks[i].ssid.ssid,
    262		       nd_config->match_sets[i].ssid.ssid,
    263		       nd_config->match_sets[i].ssid.ssid_len);
    264		pno->a_networks[i].authentication = 0;
    265		pno->a_networks[i].encryption     = 0;
    266		pno->a_networks[i].bcast_nw_type  = 0;
    267
    268		/* Copying list of valid channel into request */
    269		pno->a_networks[i].channel_count = nd_config->n_channels;
    270		pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold;
    271
    272		for (j = 0; j < nd_config->n_channels; j++) {
    273			pno->a_networks[i].channels[j] =
    274					nd_config->channels[j]->center_freq;
    275		}
    276	}
    277
    278	/* set scan to passive if no SSIDs are specified in the request */
    279	if (nd_config->n_ssids == 0)
    280		pno->do_passive_scan = true;
    281	else
    282		pno->do_passive_scan = false;
    283
    284	for (i = 0; i < nd_config->n_ssids; i++) {
    285		j = 0;
    286		while (j < pno->uc_networks_count) {
    287			if (pno->a_networks[j].ssid.ssid_len ==
    288				nd_config->ssids[i].ssid_len &&
    289			(memcmp(pno->a_networks[j].ssid.ssid,
    290				nd_config->ssids[i].ssid,
    291				pno->a_networks[j].ssid.ssid_len) == 0)) {
    292				pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN;
    293				break;
    294			}
    295			j++;
    296		}
    297	}
    298
    299	if (nd_config->n_scan_plans == 2) {
    300		pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
    301		pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations;
    302		pno->slow_scan_period =
    303			nd_config->scan_plans[1].interval * MSEC_PER_SEC;
    304	} else if (nd_config->n_scan_plans == 1) {
    305		pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
    306		pno->fast_scan_max_cycles = 1;
    307		pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
    308	} else {
    309		ath11k_warn(ar->ab, "Invalid number of scan plans %d !!",
    310			    nd_config->n_scan_plans);
    311	}
    312
    313	if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
    314		/* enable mac randomization */
    315		pno->enable_pno_scan_randomization = 1;
    316		memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN);
    317		memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN);
    318	}
    319
    320	pno->delay_start_time = nd_config->delay;
    321
    322	/* Current FW does not support min-max range for dwell time */
    323	pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME;
    324	pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME;
    325
    326	return 0;
    327}
    328
    329static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif,
    330				      struct cfg80211_wowlan *wowlan)
    331{
    332	int ret, i;
    333	unsigned long wow_mask = 0;
    334	struct ath11k *ar = arvif->ar;
    335	const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
    336	int pattern_id = 0;
    337
    338	/* Setup requested WOW features */
    339	switch (arvif->vdev_type) {
    340	case WMI_VDEV_TYPE_IBSS:
    341		__set_bit(WOW_BEACON_EVENT, &wow_mask);
    342		fallthrough;
    343	case WMI_VDEV_TYPE_AP:
    344		__set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
    345		__set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
    346		__set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask);
    347		__set_bit(WOW_AUTH_REQ_EVENT, &wow_mask);
    348		__set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask);
    349		__set_bit(WOW_HTT_EVENT, &wow_mask);
    350		__set_bit(WOW_RA_MATCH_EVENT, &wow_mask);
    351		break;
    352	case WMI_VDEV_TYPE_STA:
    353		if (wowlan->disconnect) {
    354			__set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
    355			__set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
    356			__set_bit(WOW_BMISS_EVENT, &wow_mask);
    357			__set_bit(WOW_CSA_IE_EVENT, &wow_mask);
    358		}
    359
    360		if (wowlan->magic_pkt)
    361			__set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask);
    362
    363		if (wowlan->nd_config) {
    364			struct wmi_pno_scan_req *pno;
    365			int ret;
    366
    367			pno = kzalloc(sizeof(*pno), GFP_KERNEL);
    368			if (!pno)
    369				return -ENOMEM;
    370
    371			ar->nlo_enabled = true;
    372
    373			ret = ath11k_wmi_pno_check_and_convert(ar, arvif->vdev_id,
    374							       wowlan->nd_config, pno);
    375			if (!ret) {
    376				ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
    377				__set_bit(WOW_NLO_DETECTED_EVENT, &wow_mask);
    378			}
    379
    380			kfree(pno);
    381		}
    382		break;
    383	default:
    384		break;
    385	}
    386
    387	for (i = 0; i < wowlan->n_patterns; i++) {
    388		u8 bitmask[WOW_MAX_PATTERN_SIZE] = {};
    389		u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {};
    390		u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {};
    391		struct cfg80211_pkt_pattern new_pattern = {};
    392		struct cfg80211_pkt_pattern old_pattern = patterns[i];
    393		int j;
    394
    395		new_pattern.pattern = ath_pattern;
    396		new_pattern.mask = ath_bitmask;
    397		if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE)
    398			continue;
    399		/* convert bytemask to bitmask */
    400		for (j = 0; j < patterns[i].pattern_len; j++)
    401			if (patterns[i].mask[j / 8] & BIT(j % 8))
    402				bitmask[j] = 0xff;
    403		old_pattern.mask = bitmask;
    404
    405		if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
    406		    ATH11K_HW_TXRX_NATIVE_WIFI) {
    407			if (patterns[i].pkt_offset < ETH_HLEN) {
    408				u8 pattern_ext[WOW_MAX_PATTERN_SIZE] = {};
    409
    410				memcpy(pattern_ext, old_pattern.pattern,
    411				       old_pattern.pattern_len);
    412				old_pattern.pattern = pattern_ext;
    413				ath11k_wow_convert_8023_to_80211(&new_pattern,
    414								 &old_pattern);
    415			} else {
    416				new_pattern = old_pattern;
    417				new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
    418			}
    419		}
    420
    421		if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE))
    422			return -EINVAL;
    423
    424		ret = ath11k_wmi_wow_add_pattern(ar, arvif->vdev_id,
    425						 pattern_id,
    426						 new_pattern.pattern,
    427						 new_pattern.mask,
    428						 new_pattern.pattern_len,
    429						 new_pattern.pkt_offset);
    430		if (ret) {
    431			ath11k_warn(ar->ab, "failed to add pattern %i to vdev %i: %d\n",
    432				    pattern_id,
    433				    arvif->vdev_id, ret);
    434			return ret;
    435		}
    436
    437		pattern_id++;
    438		__set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask);
    439	}
    440
    441	for (i = 0; i < WOW_EVENT_MAX; i++) {
    442		if (!test_bit(i, &wow_mask))
    443			continue;
    444		ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1);
    445		if (ret) {
    446			ath11k_warn(ar->ab, "failed to enable wakeup event %s on vdev %i: %d\n",
    447				    wow_wakeup_event(i), arvif->vdev_id, ret);
    448			return ret;
    449		}
    450	}
    451
    452	return 0;
    453}
    454
    455static int ath11k_wow_set_wakeups(struct ath11k *ar,
    456				  struct cfg80211_wowlan *wowlan)
    457{
    458	struct ath11k_vif *arvif;
    459	int ret;
    460
    461	lockdep_assert_held(&ar->conf_mutex);
    462
    463	list_for_each_entry(arvif, &ar->arvifs, list) {
    464		ret = ath11k_vif_wow_set_wakeups(arvif, wowlan);
    465		if (ret) {
    466			ath11k_warn(ar->ab, "failed to set wow wakeups on vdev %i: %d\n",
    467				    arvif->vdev_id, ret);
    468			return ret;
    469		}
    470	}
    471
    472	return 0;
    473}
    474
    475static int ath11k_vif_wow_clean_nlo(struct ath11k_vif *arvif)
    476{
    477	int ret = 0;
    478	struct ath11k *ar = arvif->ar;
    479
    480	switch (arvif->vdev_type) {
    481	case WMI_VDEV_TYPE_STA:
    482		if (ar->nlo_enabled) {
    483			struct wmi_pno_scan_req *pno;
    484
    485			pno = kzalloc(sizeof(*pno), GFP_KERNEL);
    486			if (!pno)
    487				return -ENOMEM;
    488
    489			pno->enable = 0;
    490			ar->nlo_enabled = false;
    491			ret = ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
    492			kfree(pno);
    493		}
    494		break;
    495	default:
    496		break;
    497	}
    498	return ret;
    499}
    500
    501static int ath11k_wow_nlo_cleanup(struct ath11k *ar)
    502{
    503	struct ath11k_vif *arvif;
    504	int ret;
    505
    506	lockdep_assert_held(&ar->conf_mutex);
    507
    508	list_for_each_entry(arvif, &ar->arvifs, list) {
    509		ret = ath11k_vif_wow_clean_nlo(arvif);
    510		if (ret) {
    511			ath11k_warn(ar->ab, "failed to clean nlo settings on vdev %i: %d\n",
    512				    arvif->vdev_id, ret);
    513			return ret;
    514		}
    515	}
    516
    517	return 0;
    518}
    519
    520static int ath11k_wow_set_hw_filter(struct ath11k *ar)
    521{
    522	struct ath11k_vif *arvif;
    523	u32 bitmap;
    524	int ret;
    525
    526	lockdep_assert_held(&ar->conf_mutex);
    527
    528	list_for_each_entry(arvif, &ar->arvifs, list) {
    529		bitmap = WMI_HW_DATA_FILTER_DROP_NON_ICMPV6_MC |
    530			WMI_HW_DATA_FILTER_DROP_NON_ARP_BC;
    531		ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id,
    532						    bitmap,
    533						    true);
    534		if (ret) {
    535			ath11k_warn(ar->ab, "failed to set hw data filter on vdev %i: %d\n",
    536				    arvif->vdev_id, ret);
    537			return ret;
    538		}
    539	}
    540
    541	return 0;
    542}
    543
    544static int ath11k_wow_clear_hw_filter(struct ath11k *ar)
    545{
    546	struct ath11k_vif *arvif;
    547	int ret;
    548
    549	lockdep_assert_held(&ar->conf_mutex);
    550
    551	list_for_each_entry(arvif, &ar->arvifs, list) {
    552		ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id, 0, false);
    553
    554		if (ret) {
    555			ath11k_warn(ar->ab, "failed to clear hw data filter on vdev %i: %d\n",
    556				    arvif->vdev_id, ret);
    557			return ret;
    558		}
    559	}
    560
    561	return 0;
    562}
    563
    564static int ath11k_wow_arp_ns_offload(struct ath11k *ar, bool enable)
    565{
    566	struct ath11k_vif *arvif;
    567	int ret;
    568
    569	lockdep_assert_held(&ar->conf_mutex);
    570
    571	list_for_each_entry(arvif, &ar->arvifs, list) {
    572		if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
    573			continue;
    574
    575		ret = ath11k_wmi_arp_ns_offload(ar, arvif, enable);
    576
    577		if (ret) {
    578			ath11k_warn(ar->ab, "failed to set arp ns offload vdev %i: enable %d, ret %d\n",
    579				    arvif->vdev_id, enable, ret);
    580			return ret;
    581		}
    582	}
    583
    584	return 0;
    585}
    586
    587static int ath11k_gtk_rekey_offload(struct ath11k *ar, bool enable)
    588{
    589	struct ath11k_vif *arvif;
    590	int ret;
    591
    592	lockdep_assert_held(&ar->conf_mutex);
    593
    594	list_for_each_entry(arvif, &ar->arvifs, list) {
    595		if (arvif->vdev_type != WMI_VDEV_TYPE_STA ||
    596		    !arvif->is_up ||
    597		    !arvif->rekey_data.enable_offload)
    598			continue;
    599
    600		/* get rekey info before disable rekey offload */
    601		if (!enable) {
    602			ret = ath11k_wmi_gtk_rekey_getinfo(ar, arvif);
    603			if (ret) {
    604				ath11k_warn(ar->ab, "failed to request rekey info vdev %i, ret %d\n",
    605					    arvif->vdev_id, ret);
    606				return ret;
    607			}
    608		}
    609
    610		ret = ath11k_wmi_gtk_rekey_offload(ar, arvif, enable);
    611
    612		if (ret) {
    613			ath11k_warn(ar->ab, "failed to offload gtk reky vdev %i: enable %d, ret %d\n",
    614				    arvif->vdev_id, enable, ret);
    615			return ret;
    616		}
    617	}
    618
    619	return 0;
    620}
    621
    622static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable)
    623{
    624	int ret;
    625
    626	ret = ath11k_wow_arp_ns_offload(ar, enable);
    627	if (ret) {
    628		ath11k_warn(ar->ab, "failed to offload ARP and NS %d %d\n",
    629			    enable, ret);
    630		return ret;
    631	}
    632
    633	ret = ath11k_gtk_rekey_offload(ar, enable);
    634	if (ret) {
    635		ath11k_warn(ar->ab, "failed to offload gtk rekey %d %d\n",
    636			    enable, ret);
    637		return ret;
    638	}
    639
    640	return 0;
    641}
    642
    643static int ath11k_wow_set_keepalive(struct ath11k *ar,
    644				    enum wmi_sta_keepalive_method method,
    645				    u32 interval)
    646{
    647	struct ath11k_vif *arvif;
    648	int ret;
    649
    650	lockdep_assert_held(&ar->conf_mutex);
    651
    652	list_for_each_entry(arvif, &ar->arvifs, list) {
    653		ret = ath11k_mac_vif_set_keepalive(arvif, method, interval);
    654		if (ret)
    655			return ret;
    656	}
    657
    658	return 0;
    659}
    660
    661int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
    662			  struct cfg80211_wowlan *wowlan)
    663{
    664	struct ath11k *ar = hw->priv;
    665	int ret;
    666
    667	mutex_lock(&ar->conf_mutex);
    668
    669	ret = ath11k_dp_rx_pktlog_stop(ar->ab, true);
    670	if (ret) {
    671		ath11k_warn(ar->ab,
    672			    "failed to stop dp rx (and timer) pktlog during wow suspend: %d\n",
    673			    ret);
    674		goto exit;
    675	}
    676
    677	ret =  ath11k_wow_cleanup(ar);
    678	if (ret) {
    679		ath11k_warn(ar->ab, "failed to clear wow wakeup events: %d\n",
    680			    ret);
    681		goto exit;
    682	}
    683
    684	ret = ath11k_wow_set_wakeups(ar, wowlan);
    685	if (ret) {
    686		ath11k_warn(ar->ab, "failed to set wow wakeup events: %d\n",
    687			    ret);
    688		goto cleanup;
    689	}
    690
    691	ret = ath11k_wow_protocol_offload(ar, true);
    692	if (ret) {
    693		ath11k_warn(ar->ab, "failed to set wow protocol offload events: %d\n",
    694			    ret);
    695		goto cleanup;
    696	}
    697
    698	ath11k_mac_drain_tx(ar);
    699	ret = ath11k_mac_wait_tx_complete(ar);
    700	if (ret) {
    701		ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret);
    702		goto cleanup;
    703	}
    704
    705	ret = ath11k_wow_set_hw_filter(ar);
    706	if (ret) {
    707		ath11k_warn(ar->ab, "failed to set hw filter: %d\n",
    708			    ret);
    709		goto cleanup;
    710	}
    711
    712	ret = ath11k_wow_set_keepalive(ar,
    713				       WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
    714				       WMI_STA_KEEPALIVE_INTERVAL_DEFAULT);
    715	if (ret) {
    716		ath11k_warn(ar->ab, "failed to enable wow keepalive: %d\n", ret);
    717		goto cleanup;
    718	}
    719
    720	ret = ath11k_wow_enable(ar->ab);
    721	if (ret) {
    722		ath11k_warn(ar->ab, "failed to start wow: %d\n", ret);
    723		goto cleanup;
    724	}
    725
    726	ret = ath11k_dp_rx_pktlog_stop(ar->ab, false);
    727	if (ret) {
    728		ath11k_warn(ar->ab,
    729			    "failed to stop dp rx pktlog during wow suspend: %d\n",
    730			    ret);
    731		goto cleanup;
    732	}
    733
    734	ath11k_ce_stop_shadow_timers(ar->ab);
    735	ath11k_dp_stop_shadow_timers(ar->ab);
    736
    737	ath11k_hif_irq_disable(ar->ab);
    738	ath11k_hif_ce_irq_disable(ar->ab);
    739
    740	ret = ath11k_hif_suspend(ar->ab);
    741	if (ret) {
    742		ath11k_warn(ar->ab, "failed to suspend hif: %d\n", ret);
    743		goto wakeup;
    744	}
    745
    746	goto exit;
    747
    748wakeup:
    749	ath11k_wow_wakeup(ar->ab);
    750
    751cleanup:
    752	ath11k_wow_cleanup(ar);
    753
    754exit:
    755	mutex_unlock(&ar->conf_mutex);
    756	return ret ? 1 : 0;
    757}
    758
    759void ath11k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
    760{
    761	struct ath11k *ar = hw->priv;
    762
    763	mutex_lock(&ar->conf_mutex);
    764	device_set_wakeup_enable(ar->ab->dev, enabled);
    765	mutex_unlock(&ar->conf_mutex);
    766}
    767
    768int ath11k_wow_op_resume(struct ieee80211_hw *hw)
    769{
    770	struct ath11k *ar = hw->priv;
    771	int ret;
    772
    773	mutex_lock(&ar->conf_mutex);
    774
    775	ret = ath11k_hif_resume(ar->ab);
    776	if (ret) {
    777		ath11k_warn(ar->ab, "failed to resume hif: %d\n", ret);
    778		goto exit;
    779	}
    780
    781	ath11k_hif_ce_irq_enable(ar->ab);
    782	ath11k_hif_irq_enable(ar->ab);
    783
    784	ret = ath11k_dp_rx_pktlog_start(ar->ab);
    785	if (ret) {
    786		ath11k_warn(ar->ab, "failed to start rx pktlog from wow: %d\n", ret);
    787		goto exit;
    788	}
    789
    790	ret = ath11k_wow_wakeup(ar->ab);
    791	if (ret) {
    792		ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret);
    793		goto exit;
    794	}
    795
    796	ret = ath11k_wow_nlo_cleanup(ar);
    797	if (ret) {
    798		ath11k_warn(ar->ab, "failed to cleanup nlo: %d\n", ret);
    799		goto exit;
    800	}
    801
    802	ret = ath11k_wow_clear_hw_filter(ar);
    803	if (ret) {
    804		ath11k_warn(ar->ab, "failed to clear hw filter: %d\n", ret);
    805		goto exit;
    806	}
    807
    808	ret = ath11k_wow_protocol_offload(ar, false);
    809	if (ret) {
    810		ath11k_warn(ar->ab, "failed to clear wow protocol offload events: %d\n",
    811			    ret);
    812		goto exit;
    813	}
    814
    815	ret = ath11k_wow_set_keepalive(ar,
    816				       WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
    817				       WMI_STA_KEEPALIVE_INTERVAL_DISABLE);
    818	if (ret) {
    819		ath11k_warn(ar->ab, "failed to disable wow keepalive: %d\n", ret);
    820		goto exit;
    821	}
    822
    823exit:
    824	if (ret) {
    825		switch (ar->state) {
    826		case ATH11K_STATE_ON:
    827			ar->state = ATH11K_STATE_RESTARTING;
    828			ret = 1;
    829			break;
    830		case ATH11K_STATE_OFF:
    831		case ATH11K_STATE_RESTARTING:
    832		case ATH11K_STATE_RESTARTED:
    833		case ATH11K_STATE_WEDGED:
    834			ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n",
    835				    ar->state);
    836			ret = -EIO;
    837			break;
    838		}
    839	}
    840
    841	mutex_unlock(&ar->conf_mutex);
    842	return ret;
    843}
    844
    845int ath11k_wow_init(struct ath11k *ar)
    846{
    847	if (!test_bit(WMI_TLV_SERVICE_WOW, ar->wmi->wmi_ab->svc_map))
    848		return 0;
    849
    850	ar->wow.wowlan_support = ath11k_wowlan_support;
    851
    852	if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
    853	    ATH11K_HW_TXRX_NATIVE_WIFI) {
    854		ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE;
    855		ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE;
    856	}
    857
    858	if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) {
    859		ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
    860		ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
    861	}
    862
    863	ar->wow.max_num_patterns = ATH11K_WOW_PATTERNS;
    864	ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
    865	ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;
    866
    867	device_set_wakeup_capable(ar->ab->dev, true);
    868
    869	return 0;
    870}