brintos

brintos / linux-shallow public Read only

0
0
Text · 100.4 KiB · 244ca8c Raw
3778 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause2/*3 * Copyright (C) 2012-2014, 2018-2024 Intel Corporation4 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH5 * Copyright (C) 2016-2017 Intel Deutschland GmbH6 */7#include <linux/etherdevice.h>8#include <linux/ip.h>9#include <linux/fs.h>10#include <net/cfg80211.h>11#include <net/ipv6.h>12#include <net/tcp.h>13#include <net/addrconf.h>14#include "iwl-modparams.h"15#include "fw-api.h"16#include "mvm.h"17#include "fw/img.h"18 19void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw,20			    struct ieee80211_vif *vif,21			    struct cfg80211_gtk_rekey_data *data)22{23	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);24	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);25 26	mutex_lock(&mvm->mutex);27 28	mvmvif->rekey_data.kek_len = data->kek_len;29	mvmvif->rekey_data.kck_len = data->kck_len;30	memcpy(mvmvif->rekey_data.kek, data->kek, data->kek_len);31	memcpy(mvmvif->rekey_data.kck, data->kck, data->kck_len);32	mvmvif->rekey_data.akm = data->akm & 0xFF;33	mvmvif->rekey_data.replay_ctr =34		cpu_to_le64(be64_to_cpup((const __be64 *)data->replay_ctr));35	mvmvif->rekey_data.valid = true;36 37	mutex_unlock(&mvm->mutex);38}39 40#if IS_ENABLED(CONFIG_IPV6)41void iwl_mvm_ipv6_addr_change(struct ieee80211_hw *hw,42			      struct ieee80211_vif *vif,43			      struct inet6_dev *idev)44{45	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);46	struct inet6_ifaddr *ifa;47	int idx = 0;48 49	memset(mvmvif->tentative_addrs, 0, sizeof(mvmvif->tentative_addrs));50 51	read_lock_bh(&idev->lock);52	list_for_each_entry(ifa, &idev->addr_list, if_list) {53		mvmvif->target_ipv6_addrs[idx] = ifa->addr;54		if (ifa->flags & IFA_F_TENTATIVE)55			__set_bit(idx, mvmvif->tentative_addrs);56		idx++;57		if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)58			break;59	}60	read_unlock_bh(&idev->lock);61 62	mvmvif->num_target_ipv6_addrs = idx;63}64#endif65 66void iwl_mvm_set_default_unicast_key(struct ieee80211_hw *hw,67				     struct ieee80211_vif *vif, int idx)68{69	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);70 71	mvmvif->tx_key_idx = idx;72}73 74static void iwl_mvm_convert_p1k(u16 *p1k, __le16 *out)75{76	int i;77 78	for (i = 0; i < IWL_P1K_SIZE; i++)79		out[i] = cpu_to_le16(p1k[i]);80}81 82static const u8 *iwl_mvm_find_max_pn(struct ieee80211_key_conf *key,83				     struct iwl_mvm_key_pn *ptk_pn,84				     struct ieee80211_key_seq *seq,85				     int tid, int queues)86{87	const u8 *ret = seq->ccmp.pn;88	int i;89 90	/* get the PN from mac80211, used on the default queue */91	ieee80211_get_key_rx_seq(key, tid, seq);92 93	/* and use the internal data for the other queues */94	for (i = 1; i < queues; i++) {95		const u8 *tmp = ptk_pn->q[i].pn[tid];96 97		if (memcmp(ret, tmp, IEEE80211_CCMP_PN_LEN) <= 0)98			ret = tmp;99	}100 101	return ret;102}103 104struct wowlan_key_reprogram_data {105	bool error;106	int wep_key_idx;107};108 109static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,110					struct ieee80211_vif *vif,111					struct ieee80211_sta *sta,112					struct ieee80211_key_conf *key,113					void *_data)114{115	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);116	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);117	struct wowlan_key_reprogram_data *data = _data;118	int ret;119 120	switch (key->cipher) {121	case WLAN_CIPHER_SUITE_WEP40:122	case WLAN_CIPHER_SUITE_WEP104: { /* hack it for now */123		struct {124			struct iwl_mvm_wep_key_cmd wep_key_cmd;125			struct iwl_mvm_wep_key wep_key;126		} __packed wkc = {127			.wep_key_cmd.mac_id_n_color =128				cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,129								mvmvif->color)),130			.wep_key_cmd.num_keys = 1,131			/* firmware sets STA_KEY_FLG_WEP_13BYTES */132			.wep_key_cmd.decryption_type = STA_KEY_FLG_WEP,133			.wep_key.key_index = key->keyidx,134			.wep_key.key_size = key->keylen,135		};136 137		/*138		 * This will fail -- the key functions don't set support139		 * pairwise WEP keys. However, that's better than silently140		 * failing WoWLAN. Or maybe not?141		 */142		if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)143			break;144 145		memcpy(&wkc.wep_key.key[3], key->key, key->keylen);146		if (key->keyidx == mvmvif->tx_key_idx) {147			/* TX key must be at offset 0 */148			wkc.wep_key.key_offset = 0;149		} else {150			/* others start at 1 */151			data->wep_key_idx++;152			wkc.wep_key.key_offset = data->wep_key_idx;153		}154 155		mutex_lock(&mvm->mutex);156		ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, sizeof(wkc), &wkc);157		data->error = ret != 0;158 159		mvm->ptk_ivlen = key->iv_len;160		mvm->ptk_icvlen = key->icv_len;161		mvm->gtk_ivlen = key->iv_len;162		mvm->gtk_icvlen = key->icv_len;163		mutex_unlock(&mvm->mutex);164 165		/* don't upload key again */166		return;167	}168	default:169		data->error = true;170		return;171	case WLAN_CIPHER_SUITE_BIP_GMAC_256:172	case WLAN_CIPHER_SUITE_BIP_GMAC_128:173		return;174	case WLAN_CIPHER_SUITE_AES_CMAC:175		/*176		 * Ignore CMAC keys -- the WoWLAN firmware doesn't support them177		 * but we also shouldn't abort suspend due to that. It does have178		 * support for the IGTK key renewal, but doesn't really use the179		 * IGTK for anything. This means we could spuriously wake up or180		 * be deauthenticated, but that was considered acceptable.181		 */182		return;183	case WLAN_CIPHER_SUITE_TKIP:184	case WLAN_CIPHER_SUITE_CCMP:185	case WLAN_CIPHER_SUITE_GCMP:186	case WLAN_CIPHER_SUITE_GCMP_256:187		break;188	}189 190	mutex_lock(&mvm->mutex);191	/*192	 * The D3 firmware hardcodes the key offset 0 as the key it193	 * uses to transmit packets to the AP, i.e. the PTK.194	 */195	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {196		mvm->ptk_ivlen = key->iv_len;197		mvm->ptk_icvlen = key->icv_len;198		ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 0);199	} else {200		/*201		 * firmware only supports TSC/RSC for a single key,202		 * so if there are multiple keep overwriting them203		 * with new ones -- this relies on mac80211 doing204		 * list_add_tail().205		 */206		mvm->gtk_ivlen = key->iv_len;207		mvm->gtk_icvlen = key->icv_len;208		ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 1);209	}210	mutex_unlock(&mvm->mutex);211	data->error = ret != 0;212}213 214struct wowlan_key_rsc_tsc_data {215	struct iwl_wowlan_rsc_tsc_params_cmd_v4 *rsc_tsc;216	bool have_rsc_tsc;217};218 219static void iwl_mvm_wowlan_get_rsc_tsc_data(struct ieee80211_hw *hw,220					    struct ieee80211_vif *vif,221					    struct ieee80211_sta *sta,222					    struct ieee80211_key_conf *key,223					    void *_data)224{225	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);226	struct wowlan_key_rsc_tsc_data *data = _data;227	struct aes_sc *aes_sc;228	struct tkip_sc *tkip_sc, *tkip_tx_sc = NULL;229	struct ieee80211_key_seq seq;230	int i;231 232	switch (key->cipher) {233	default:234		break;235	case WLAN_CIPHER_SUITE_TKIP:236		if (sta) {237			u64 pn64;238 239			tkip_sc =240			   data->rsc_tsc->params.all_tsc_rsc.tkip.unicast_rsc;241			tkip_tx_sc =242				&data->rsc_tsc->params.all_tsc_rsc.tkip.tsc;243 244			pn64 = atomic64_read(&key->tx_pn);245			tkip_tx_sc->iv16 = cpu_to_le16(TKIP_PN_TO_IV16(pn64));246			tkip_tx_sc->iv32 = cpu_to_le32(TKIP_PN_TO_IV32(pn64));247		} else {248			tkip_sc =249			  data->rsc_tsc->params.all_tsc_rsc.tkip.multicast_rsc;250		}251 252		/*253		 * For non-QoS this relies on the fact that both the uCode and254		 * mac80211 use TID 0 (as they need to to avoid replay attacks)255		 * for checking the IV in the frames.256		 */257		for (i = 0; i < IWL_NUM_RSC; i++) {258			ieee80211_get_key_rx_seq(key, i, &seq);259			tkip_sc[i].iv16 = cpu_to_le16(seq.tkip.iv16);260			tkip_sc[i].iv32 = cpu_to_le32(seq.tkip.iv32);261		}262 263		data->have_rsc_tsc = true;264		break;265	case WLAN_CIPHER_SUITE_CCMP:266	case WLAN_CIPHER_SUITE_GCMP:267	case WLAN_CIPHER_SUITE_GCMP_256:268		if (sta) {269			struct aes_sc *aes_tx_sc;270			u64 pn64;271 272			aes_sc =273			   data->rsc_tsc->params.all_tsc_rsc.aes.unicast_rsc;274			aes_tx_sc =275				&data->rsc_tsc->params.all_tsc_rsc.aes.tsc;276 277			pn64 = atomic64_read(&key->tx_pn);278			aes_tx_sc->pn = cpu_to_le64(pn64);279		} else {280			aes_sc =281			   data->rsc_tsc->params.all_tsc_rsc.aes.multicast_rsc;282		}283 284		/*285		 * For non-QoS this relies on the fact that both the uCode and286		 * mac80211/our RX code use TID 0 for checking the PN.287		 */288		if (sta && iwl_mvm_has_new_rx_api(mvm)) {289			struct iwl_mvm_sta *mvmsta;290			struct iwl_mvm_key_pn *ptk_pn;291			const u8 *pn;292 293			mvmsta = iwl_mvm_sta_from_mac80211(sta);294			rcu_read_lock();295			ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);296			if (WARN_ON(!ptk_pn)) {297				rcu_read_unlock();298				break;299			}300 301			for (i = 0; i < IWL_MAX_TID_COUNT; i++) {302				pn = iwl_mvm_find_max_pn(key, ptk_pn, &seq, i,303						mvm->trans->num_rx_queues);304				aes_sc[i].pn = cpu_to_le64((u64)pn[5] |305							   ((u64)pn[4] << 8) |306							   ((u64)pn[3] << 16) |307							   ((u64)pn[2] << 24) |308							   ((u64)pn[1] << 32) |309							   ((u64)pn[0] << 40));310			}311 312			rcu_read_unlock();313		} else {314			for (i = 0; i < IWL_NUM_RSC; i++) {315				u8 *pn = seq.ccmp.pn;316 317				ieee80211_get_key_rx_seq(key, i, &seq);318				aes_sc[i].pn = cpu_to_le64((u64)pn[5] |319							   ((u64)pn[4] << 8) |320							   ((u64)pn[3] << 16) |321							   ((u64)pn[2] << 24) |322							   ((u64)pn[1] << 32) |323							   ((u64)pn[0] << 40));324			}325		}326		data->have_rsc_tsc = true;327		break;328	}329}330 331struct wowlan_key_rsc_v5_data {332	struct iwl_wowlan_rsc_tsc_params_cmd *rsc;333	bool have_rsc;334	int gtks;335	int gtk_ids[4];336};337 338static void iwl_mvm_wowlan_get_rsc_v5_data(struct ieee80211_hw *hw,339					   struct ieee80211_vif *vif,340					   struct ieee80211_sta *sta,341					   struct ieee80211_key_conf *key,342					   void *_data)343{344	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);345	struct wowlan_key_rsc_v5_data *data = _data;346	struct ieee80211_key_seq seq;347	__le64 *rsc;348	int i;349 350	/* only for ciphers that can be PTK/GTK */351	switch (key->cipher) {352	default:353		return;354	case WLAN_CIPHER_SUITE_TKIP:355	case WLAN_CIPHER_SUITE_CCMP:356	case WLAN_CIPHER_SUITE_GCMP:357	case WLAN_CIPHER_SUITE_GCMP_256:358		break;359	}360 361	if (sta) {362		rsc = data->rsc->ucast_rsc;363	} else {364		if (WARN_ON(data->gtks >= ARRAY_SIZE(data->gtk_ids)))365			return;366		data->gtk_ids[data->gtks] = key->keyidx;367		rsc = data->rsc->mcast_rsc[data->gtks % 2];368		if (WARN_ON(key->keyidx >=369				ARRAY_SIZE(data->rsc->mcast_key_id_map)))370			return;371		data->rsc->mcast_key_id_map[key->keyidx] = data->gtks % 2;372		if (data->gtks >= 2) {373			int prev = data->gtks - 2;374			int prev_idx = data->gtk_ids[prev];375 376			data->rsc->mcast_key_id_map[prev_idx] =377				IWL_MCAST_KEY_MAP_INVALID;378		}379		data->gtks++;380	}381 382	switch (key->cipher) {383	default:384		WARN_ON(1);385		break;386	case WLAN_CIPHER_SUITE_TKIP:387 388		/*389		 * For non-QoS this relies on the fact that both the uCode and390		 * mac80211 use TID 0 (as they need to to avoid replay attacks)391		 * for checking the IV in the frames.392		 */393		for (i = 0; i < IWL_MAX_TID_COUNT; i++) {394			ieee80211_get_key_rx_seq(key, i, &seq);395 396			rsc[i] = cpu_to_le64(((u64)seq.tkip.iv32 << 16) |397					     seq.tkip.iv16);398		}399 400		data->have_rsc = true;401		break;402	case WLAN_CIPHER_SUITE_CCMP:403	case WLAN_CIPHER_SUITE_GCMP:404	case WLAN_CIPHER_SUITE_GCMP_256:405		/*406		 * For non-QoS this relies on the fact that both the uCode and407		 * mac80211/our RX code use TID 0 for checking the PN.408		 */409		if (sta) {410			struct iwl_mvm_sta *mvmsta;411			struct iwl_mvm_key_pn *ptk_pn;412			const u8 *pn;413 414			mvmsta = iwl_mvm_sta_from_mac80211(sta);415			rcu_read_lock();416			ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);417			if (WARN_ON(!ptk_pn)) {418				rcu_read_unlock();419				break;420			}421 422			for (i = 0; i < IWL_MAX_TID_COUNT; i++) {423				pn = iwl_mvm_find_max_pn(key, ptk_pn, &seq, i,424						mvm->trans->num_rx_queues);425				rsc[i] = cpu_to_le64((u64)pn[5] |426						     ((u64)pn[4] << 8) |427						     ((u64)pn[3] << 16) |428						     ((u64)pn[2] << 24) |429						     ((u64)pn[1] << 32) |430						     ((u64)pn[0] << 40));431			}432 433			rcu_read_unlock();434		} else {435			for (i = 0; i < IWL_MAX_TID_COUNT; i++) {436				u8 *pn = seq.ccmp.pn;437 438				ieee80211_get_key_rx_seq(key, i, &seq);439				rsc[i] = cpu_to_le64((u64)pn[5] |440						     ((u64)pn[4] << 8) |441						     ((u64)pn[3] << 16) |442						     ((u64)pn[2] << 24) |443						     ((u64)pn[1] << 32) |444						     ((u64)pn[0] << 40));445			}446		}447		data->have_rsc = true;448		break;449	}450}451 452static int iwl_mvm_wowlan_config_rsc_tsc(struct iwl_mvm *mvm,453					 struct ieee80211_vif *vif,454					 struct iwl_mvm_vif_link_info *mvm_link)455{456	int ver = iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_TSC_RSC_PARAM,457					IWL_FW_CMD_VER_UNKNOWN);458	int ret;459 460	if (ver == 5) {461		struct wowlan_key_rsc_v5_data data = {};462		int i;463 464		data.rsc = kzalloc(sizeof(*data.rsc), GFP_KERNEL);465		if (!data.rsc)466			return -ENOMEM;467 468		for (i = 0; i < ARRAY_SIZE(data.rsc->mcast_key_id_map); i++)469			data.rsc->mcast_key_id_map[i] =470				IWL_MCAST_KEY_MAP_INVALID;471		data.rsc->sta_id = cpu_to_le32(mvm_link->ap_sta_id);472 473		ieee80211_iter_keys(mvm->hw, vif,474				    iwl_mvm_wowlan_get_rsc_v5_data,475				    &data);476 477		if (data.have_rsc)478			ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,479						   CMD_ASYNC, sizeof(*data.rsc),480						   data.rsc);481		else482			ret = 0;483		kfree(data.rsc);484	} else if (ver == 4 || ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN) {485		struct wowlan_key_rsc_tsc_data data = {};486		int size;487 488		data.rsc_tsc = kzalloc(sizeof(*data.rsc_tsc), GFP_KERNEL);489		if (!data.rsc_tsc)490			return -ENOMEM;491 492		if (ver == 4) {493			size = sizeof(*data.rsc_tsc);494			data.rsc_tsc->sta_id =495				cpu_to_le32(mvm_link->ap_sta_id);496		} else {497			/* ver == 2 || ver == IWL_FW_CMD_VER_UNKNOWN */498			size = sizeof(data.rsc_tsc->params);499		}500 501		ieee80211_iter_keys(mvm->hw, vif,502				    iwl_mvm_wowlan_get_rsc_tsc_data,503				    &data);504 505		if (data.have_rsc_tsc)506			ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_TSC_RSC_PARAM,507						   CMD_ASYNC, size,508						   data.rsc_tsc);509		else510			ret = 0;511		kfree(data.rsc_tsc);512	} else {513		ret = 0;514		WARN_ON_ONCE(1);515	}516 517	return ret;518}519 520struct wowlan_key_tkip_data {521	struct iwl_wowlan_tkip_params_cmd tkip;522	bool have_tkip_keys;523};524 525static void iwl_mvm_wowlan_get_tkip_data(struct ieee80211_hw *hw,526					 struct ieee80211_vif *vif,527					 struct ieee80211_sta *sta,528					 struct ieee80211_key_conf *key,529					 void *_data)530{531	struct wowlan_key_tkip_data *data = _data;532	struct iwl_p1k_cache *rx_p1ks;533	u8 *rx_mic_key;534	struct ieee80211_key_seq seq;535	u32 cur_rx_iv32 = 0;536	u16 p1k[IWL_P1K_SIZE];537	int i;538 539	switch (key->cipher) {540	default:541		break;542	case WLAN_CIPHER_SUITE_TKIP:543		if (sta) {544			u64 pn64;545 546			rx_p1ks = data->tkip.rx_uni;547 548			pn64 = atomic64_read(&key->tx_pn);549 550			ieee80211_get_tkip_p1k_iv(key, TKIP_PN_TO_IV32(pn64),551						  p1k);552			iwl_mvm_convert_p1k(p1k, data->tkip.tx.p1k);553 554			memcpy(data->tkip.mic_keys.tx,555			       &key->key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],556			       IWL_MIC_KEY_SIZE);557 558			rx_mic_key = data->tkip.mic_keys.rx_unicast;559		} else {560			rx_p1ks = data->tkip.rx_multi;561			rx_mic_key = data->tkip.mic_keys.rx_mcast;562		}563 564		for (i = 0; i < IWL_NUM_RSC; i++) {565			ieee80211_get_key_rx_seq(key, i, &seq);566			/* wrapping isn't allowed, AP must rekey */567			if (seq.tkip.iv32 > cur_rx_iv32)568				cur_rx_iv32 = seq.tkip.iv32;569		}570 571		ieee80211_get_tkip_rx_p1k(key, vif->bss_conf.bssid,572					  cur_rx_iv32, p1k);573		iwl_mvm_convert_p1k(p1k, rx_p1ks[0].p1k);574		ieee80211_get_tkip_rx_p1k(key, vif->bss_conf.bssid,575					  cur_rx_iv32 + 1, p1k);576		iwl_mvm_convert_p1k(p1k, rx_p1ks[1].p1k);577 578		memcpy(rx_mic_key,579		       &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],580		       IWL_MIC_KEY_SIZE);581 582		data->have_tkip_keys = true;583		break;584	}585}586 587struct wowlan_key_gtk_type_iter {588	struct iwl_wowlan_kek_kck_material_cmd_v4 *kek_kck_cmd;589};590 591static void iwl_mvm_wowlan_gtk_type_iter(struct ieee80211_hw *hw,592					 struct ieee80211_vif *vif,593					 struct ieee80211_sta *sta,594					 struct ieee80211_key_conf *key,595					 void *_data)596{597	struct wowlan_key_gtk_type_iter *data = _data;598	__le32 *cipher = NULL;599 600	if (key->keyidx == 4 || key->keyidx == 5)601		cipher = &data->kek_kck_cmd->igtk_cipher;602	if (key->keyidx == 6 || key->keyidx == 7)603		cipher = &data->kek_kck_cmd->bigtk_cipher;604 605	switch (key->cipher) {606	default:607		return;608	case WLAN_CIPHER_SUITE_TKIP:609		if (!sta)610			data->kek_kck_cmd->gtk_cipher =611				cpu_to_le32(STA_KEY_FLG_TKIP);612		return;613	case WLAN_CIPHER_SUITE_BIP_GMAC_256:614	case WLAN_CIPHER_SUITE_BIP_GMAC_128:615		if (cipher)616			*cipher = cpu_to_le32(STA_KEY_FLG_GCMP);617		return;618	case WLAN_CIPHER_SUITE_AES_CMAC:619	case WLAN_CIPHER_SUITE_BIP_CMAC_256:620		if (cipher)621			*cipher = cpu_to_le32(STA_KEY_FLG_CCM);622		return;623	case WLAN_CIPHER_SUITE_CCMP:624		if (!sta)625			data->kek_kck_cmd->gtk_cipher =626				cpu_to_le32(STA_KEY_FLG_CCM);627		return;628	case WLAN_CIPHER_SUITE_GCMP:629	case WLAN_CIPHER_SUITE_GCMP_256:630		if (!sta)631			data->kek_kck_cmd->gtk_cipher =632				cpu_to_le32(STA_KEY_FLG_GCMP);633		return;634	}635}636 637static int iwl_mvm_send_patterns_v1(struct iwl_mvm *mvm,638				    struct cfg80211_wowlan *wowlan)639{640	struct iwl_wowlan_patterns_cmd_v1 *pattern_cmd;641	struct iwl_host_cmd cmd = {642		.id = WOWLAN_PATTERNS,643		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,644	};645	int i, err;646 647	if (!wowlan->n_patterns)648		return 0;649 650	cmd.len[0] = struct_size(pattern_cmd, patterns, wowlan->n_patterns);651 652	pattern_cmd = kmalloc(cmd.len[0], GFP_KERNEL);653	if (!pattern_cmd)654		return -ENOMEM;655 656	pattern_cmd->n_patterns = cpu_to_le32(wowlan->n_patterns);657 658	for (i = 0; i < wowlan->n_patterns; i++) {659		int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);660 661		memcpy(&pattern_cmd->patterns[i].mask,662		       wowlan->patterns[i].mask, mask_len);663		memcpy(&pattern_cmd->patterns[i].pattern,664		       wowlan->patterns[i].pattern,665		       wowlan->patterns[i].pattern_len);666		pattern_cmd->patterns[i].mask_size = mask_len;667		pattern_cmd->patterns[i].pattern_size =668			wowlan->patterns[i].pattern_len;669	}670 671	cmd.data[0] = pattern_cmd;672	err = iwl_mvm_send_cmd(mvm, &cmd);673	kfree(pattern_cmd);674	return err;675}676 677static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,678				 struct iwl_mvm_vif_link_info *mvm_link,679				 struct cfg80211_wowlan *wowlan)680{681	struct iwl_wowlan_patterns_cmd *pattern_cmd;682	struct iwl_host_cmd cmd = {683		.id = WOWLAN_PATTERNS,684		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,685	};686	int i, err;687	int ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd.id,688					IWL_FW_CMD_VER_UNKNOWN);689 690	if (!wowlan->n_patterns)691		return 0;692 693	cmd.len[0] = sizeof(*pattern_cmd) +694		wowlan->n_patterns * sizeof(struct iwl_wowlan_pattern_v2);695 696	pattern_cmd = kzalloc(cmd.len[0], GFP_KERNEL);697	if (!pattern_cmd)698		return -ENOMEM;699 700	pattern_cmd->n_patterns = wowlan->n_patterns;701	if (ver >= 3)702		pattern_cmd->sta_id = mvm_link->ap_sta_id;703 704	for (i = 0; i < wowlan->n_patterns; i++) {705		int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);706 707		pattern_cmd->patterns[i].pattern_type =708			WOWLAN_PATTERN_TYPE_BITMASK;709 710		memcpy(&pattern_cmd->patterns[i].u.bitmask.mask,711		       wowlan->patterns[i].mask, mask_len);712		memcpy(&pattern_cmd->patterns[i].u.bitmask.pattern,713		       wowlan->patterns[i].pattern,714		       wowlan->patterns[i].pattern_len);715		pattern_cmd->patterns[i].u.bitmask.mask_size = mask_len;716		pattern_cmd->patterns[i].u.bitmask.pattern_size =717			wowlan->patterns[i].pattern_len;718	}719 720	cmd.data[0] = pattern_cmd;721	err = iwl_mvm_send_cmd(mvm, &cmd);722	kfree(pattern_cmd);723	return err;724}725 726static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,727				struct ieee80211_sta *ap_sta)728{729	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);730	struct ieee80211_chanctx_conf *ctx;731	u8 chains_static, chains_dynamic;732	struct cfg80211_chan_def chandef, ap_def;733	int ret, i;734	struct iwl_binding_cmd_v1 binding_cmd = {};735	struct iwl_time_quota_cmd quota_cmd = {};736	struct iwl_time_quota_data *quota;737	u32 status;738 739	if (WARN_ON_ONCE(iwl_mvm_is_cdb_supported(mvm) ||740			 ieee80211_vif_is_mld(vif)))741		return -EINVAL;742 743	/* add back the PHY */744	if (WARN_ON(!mvmvif->deflink.phy_ctxt))745		return -EINVAL;746 747	rcu_read_lock();748	ctx = rcu_dereference(vif->bss_conf.chanctx_conf);749	if (WARN_ON(!ctx)) {750		rcu_read_unlock();751		return -EINVAL;752	}753	chandef = ctx->def;754	ap_def = ctx->ap;755	chains_static = ctx->rx_chains_static;756	chains_dynamic = ctx->rx_chains_dynamic;757	rcu_read_unlock();758 759	ret = iwl_mvm_phy_ctxt_add(mvm, mvmvif->deflink.phy_ctxt, &chandef,760				   &ap_def, chains_static, chains_dynamic);761	if (ret)762		return ret;763 764	/* add back the MAC */765	mvmvif->uploaded = false;766 767	if (WARN_ON(!vif->cfg.assoc))768		return -EINVAL;769 770	ret = iwl_mvm_mac_ctxt_add(mvm, vif);771	if (ret)772		return ret;773 774	/* add back binding - XXX refactor? */775	binding_cmd.id_and_color =776		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,777						mvmvif->deflink.phy_ctxt->color));778	binding_cmd.action = cpu_to_le32(FW_CTXT_ACTION_ADD);779	binding_cmd.phy =780		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,781						mvmvif->deflink.phy_ctxt->color));782	binding_cmd.macs[0] = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,783							      mvmvif->color));784	for (i = 1; i < MAX_MACS_IN_BINDING; i++)785		binding_cmd.macs[i] = cpu_to_le32(FW_CTXT_INVALID);786 787	status = 0;788	ret = iwl_mvm_send_cmd_pdu_status(mvm, BINDING_CONTEXT_CMD,789					  IWL_BINDING_CMD_SIZE_V1, &binding_cmd,790					  &status);791	if (ret) {792		IWL_ERR(mvm, "Failed to add binding: %d\n", ret);793		return ret;794	}795 796	if (status) {797		IWL_ERR(mvm, "Binding command failed: %u\n", status);798		return -EIO;799	}800 801	ret = iwl_mvm_sta_send_to_fw(mvm, ap_sta, false, 0);802	if (ret)803		return ret;804	rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->deflink.ap_sta_id],805			   ap_sta);806 807	ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);808	if (ret)809		return ret;810 811	/* and some quota */812	quota = iwl_mvm_quota_cmd_get_quota(mvm, &quota_cmd, 0);813	quota->id_and_color =814		cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->deflink.phy_ctxt->id,815						mvmvif->deflink.phy_ctxt->color));816	quota->quota = cpu_to_le32(IWL_MVM_MAX_QUOTA);817	quota->max_duration = cpu_to_le32(IWL_MVM_MAX_QUOTA);818 819	for (i = 1; i < MAX_BINDINGS; i++) {820		quota = iwl_mvm_quota_cmd_get_quota(mvm, &quota_cmd, i);821		quota->id_and_color = cpu_to_le32(FW_CTXT_INVALID);822	}823 824	ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,825				   iwl_mvm_quota_cmd_size(mvm), &quota_cmd);826	if (ret)827		IWL_ERR(mvm, "Failed to send quota: %d\n", ret);828 829	if (iwl_mvm_is_lar_supported(mvm) && iwl_mvm_init_fw_regd(mvm, false))830		IWL_ERR(mvm, "Failed to initialize D3 LAR information\n");831 832	return 0;833}834 835static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm,836				       struct ieee80211_vif *vif)837{838	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);839	struct iwl_nonqos_seq_query_cmd query_cmd = {840		.get_set_flag = cpu_to_le32(IWL_NONQOS_SEQ_GET),841		.mac_id_n_color =842			cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,843							mvmvif->color)),844	};845	struct iwl_host_cmd cmd = {846		.id = NON_QOS_TX_COUNTER_CMD,847		.flags = CMD_WANT_SKB,848	};849	int err;850	u32 size;851 852	cmd.data[0] = &query_cmd;853	cmd.len[0] = sizeof(query_cmd);854 855	err = iwl_mvm_send_cmd(mvm, &cmd);856	if (err)857		return err;858 859	size = iwl_rx_packet_payload_len(cmd.resp_pkt);860	if (size < sizeof(__le16)) {861		err = -EINVAL;862	} else {863		err = le16_to_cpup((__le16 *)cmd.resp_pkt->data);864		/* firmware returns next, not last-used seqno */865		err = (u16) (err - 0x10);866	}867 868	iwl_free_resp(&cmd);869	return err;870}871 872void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)873{874	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);875	struct iwl_nonqos_seq_query_cmd query_cmd = {876		.get_set_flag = cpu_to_le32(IWL_NONQOS_SEQ_SET),877		.mac_id_n_color =878			cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,879							mvmvif->color)),880		.value = cpu_to_le16(mvmvif->seqno),881	};882 883	/* return if called during restart, not resume from D3 */884	if (!mvmvif->seqno_valid)885		return;886 887	mvmvif->seqno_valid = false;888 889	if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, 0,890				 sizeof(query_cmd), &query_cmd))891		IWL_ERR(mvm, "failed to set non-QoS seqno\n");892}893 894static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)895{896	iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_REGULAR, true);897 898	iwl_mvm_stop_device(mvm);899	/*900	 * Set the HW restart bit -- this is mostly true as we're901	 * going to load new firmware and reprogram that, though902	 * the reprogramming is going to be manual to avoid adding903	 * all the MACs that aren't support.904	 * We don't have to clear up everything though because the905	 * reprogramming is manual. When we resume, we'll actually906	 * go through a proper restart sequence again to switch907	 * back to the runtime firmware image.908	 */909	set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);910 911	/* the fw is reset, so all the keys are cleared */912	memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));913 914	mvm->ptk_ivlen = 0;915	mvm->ptk_icvlen = 0;916	mvm->ptk_ivlen = 0;917	mvm->ptk_icvlen = 0;918 919	return iwl_mvm_load_d3_fw(mvm);920}921 922static int923iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,924			  struct cfg80211_wowlan *wowlan,925			  struct iwl_wowlan_config_cmd *wowlan_config_cmd,926			  struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,927			  struct ieee80211_sta *ap_sta)928{929	struct iwl_mvm_sta *mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);930 931	/* TODO: wowlan_config_cmd->wowlan_ba_teardown_tids */932 933	wowlan_config_cmd->is_11n_connection =934					ap_sta->deflink.ht_cap.ht_supported;935	wowlan_config_cmd->flags = ENABLE_L3_FILTERING |936		ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING;937 938	if (ap_sta->mfp)939		wowlan_config_cmd->flags |= IS_11W_ASSOC;940 941	if (iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_CONFIGURATION, 0) < 6) {942		/* Query the last used seqno and set it */943		int ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);944 945		if (ret < 0)946			return ret;947 948		wowlan_config_cmd->non_qos_seq = cpu_to_le16(ret);949	}950 951	iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, wowlan_config_cmd);952 953	if (wowlan->disconnect)954		wowlan_config_cmd->wakeup_filter |=955			cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |956				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);957	if (wowlan->magic_pkt)958		wowlan_config_cmd->wakeup_filter |=959			cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);960	if (wowlan->gtk_rekey_failure)961		wowlan_config_cmd->wakeup_filter |=962			cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);963	if (wowlan->eap_identity_req)964		wowlan_config_cmd->wakeup_filter |=965			cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);966	if (wowlan->four_way_handshake)967		wowlan_config_cmd->wakeup_filter |=968			cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);969	if (wowlan->n_patterns)970		wowlan_config_cmd->wakeup_filter |=971			cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);972 973	if (wowlan->rfkill_release)974		wowlan_config_cmd->wakeup_filter |=975			cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);976 977	if (wowlan->tcp) {978		/*979		 * Set the "link change" (really "link lost") flag as well980		 * since that implies losing the TCP connection.981		 */982		wowlan_config_cmd->wakeup_filter |=983			cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |984				    IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |985				    IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |986				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);987	}988 989	if (wowlan->any) {990		wowlan_config_cmd->wakeup_filter |=991			cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |992				    IWL_WOWLAN_WAKEUP_LINK_CHANGE |993				    IWL_WOWLAN_WAKEUP_RX_FRAME |994				    IWL_WOWLAN_WAKEUP_BCN_FILTERING);995	}996 997	return 0;998}999 1000static int iwl_mvm_wowlan_config_key_params(struct iwl_mvm *mvm,1001					    struct ieee80211_vif *vif,1002					    struct iwl_mvm_vif_link_info *mvm_link)1003{1004	bool unified = fw_has_capa(&mvm->fw->ucode_capa,1005				   IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);1006	struct wowlan_key_reprogram_data key_data = {};1007	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);1008	int ret;1009	u8 cmd_ver;1010	size_t cmd_size;1011 1012	if (!unified) {1013		/*1014		 * if we have to configure keys, call ieee80211_iter_keys(),1015		 * as we need non-atomic context in order to take the1016		 * required locks.1017		 */1018		/*1019		 * Note that currently we don't use CMD_ASYNC in the iterator.1020		 * In case of key_data.configure_keys, all the configured1021		 * commands are SYNC, and iwl_mvm_wowlan_program_keys() will1022		 * take care of locking/unlocking mvm->mutex.1023		 */1024		ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_program_keys,1025				    &key_data);1026 1027		if (key_data.error)1028			return -EIO;1029	}1030 1031	ret = iwl_mvm_wowlan_config_rsc_tsc(mvm, vif, mvm_link);1032	if (ret)1033		return ret;1034 1035	if (!fw_has_api(&mvm->fw->ucode_capa,1036			IWL_UCODE_TLV_API_TKIP_MIC_KEYS)) {1037		int ver = iwl_fw_lookup_cmd_ver(mvm->fw, WOWLAN_TKIP_PARAM,1038						IWL_FW_CMD_VER_UNKNOWN);1039		struct wowlan_key_tkip_data tkip_data = {};1040		int size;1041 1042		if (ver == 2) {1043			size = sizeof(tkip_data.tkip);1044			tkip_data.tkip.sta_id =1045				cpu_to_le32(mvm_link->ap_sta_id);1046		} else if (ver == 1 || ver == IWL_FW_CMD_VER_UNKNOWN) {1047			size = sizeof(struct iwl_wowlan_tkip_params_cmd_ver_1);1048		} else {1049			WARN_ON_ONCE(1);1050			return -EINVAL;1051		}1052 1053		ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_get_tkip_data,1054				    &tkip_data);1055 1056		if (tkip_data.have_tkip_keys) {1057			/* send relevant data according to CMD version */1058			ret = iwl_mvm_send_cmd_pdu(mvm,1059						   WOWLAN_TKIP_PARAM,1060						   CMD_ASYNC, size,1061						   &tkip_data.tkip);1062			if (ret)1063				return ret;1064		}1065	}1066 1067	/* configure rekey data only if offloaded rekey is supported (d3) */1068	if (mvmvif->rekey_data.valid) {1069		struct iwl_wowlan_kek_kck_material_cmd_v4 kek_kck_cmd = {};1070		struct iwl_wowlan_kek_kck_material_cmd_v4 *_kek_kck_cmd =1071			&kek_kck_cmd;1072		struct wowlan_key_gtk_type_iter gtk_type_data = {1073			.kek_kck_cmd = _kek_kck_cmd,1074		};1075 1076		cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw,1077						WOWLAN_KEK_KCK_MATERIAL,1078						IWL_FW_CMD_VER_UNKNOWN);1079		if (WARN_ON(cmd_ver != 2 && cmd_ver != 3 && cmd_ver != 4 &&1080			    cmd_ver != IWL_FW_CMD_VER_UNKNOWN))1081			return -EINVAL;1082 1083		ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_wowlan_gtk_type_iter,1084				    &gtk_type_data);1085 1086		memcpy(kek_kck_cmd.kck, mvmvif->rekey_data.kck,1087		       mvmvif->rekey_data.kck_len);1088		kek_kck_cmd.kck_len = cpu_to_le16(mvmvif->rekey_data.kck_len);1089		memcpy(kek_kck_cmd.kek, mvmvif->rekey_data.kek,1090		       mvmvif->rekey_data.kek_len);1091		kek_kck_cmd.kek_len = cpu_to_le16(mvmvif->rekey_data.kek_len);1092		kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;1093		kek_kck_cmd.akm = cpu_to_le32(mvmvif->rekey_data.akm);1094		kek_kck_cmd.sta_id = cpu_to_le32(mvm_link->ap_sta_id);1095 1096		if (cmd_ver == 4) {1097			cmd_size = sizeof(struct iwl_wowlan_kek_kck_material_cmd_v4);1098		} else {1099			if (cmd_ver == 3)1100				cmd_size =1101					sizeof(struct iwl_wowlan_kek_kck_material_cmd_v3);1102			else1103				cmd_size =1104					sizeof(struct iwl_wowlan_kek_kck_material_cmd_v2);1105			/* skip the sta_id at the beginning */1106			_kek_kck_cmd = (void *)1107				((u8 *)_kek_kck_cmd + sizeof(kek_kck_cmd.sta_id));1108		}1109 1110		IWL_DEBUG_WOWLAN(mvm, "setting akm %d\n",1111				 mvmvif->rekey_data.akm);1112 1113		ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_KEK_KCK_MATERIAL,1114					   CMD_ASYNC, cmd_size, _kek_kck_cmd);1115		if (ret)1116			return ret;1117	}1118 1119	return 0;1120}1121 1122static int1123iwl_mvm_wowlan_config(struct iwl_mvm *mvm,1124		      struct cfg80211_wowlan *wowlan,1125		      struct iwl_wowlan_config_cmd *wowlan_config_cmd,1126		      struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,1127		      struct iwl_mvm_vif_link_info *mvm_link,1128		      struct ieee80211_sta *ap_sta)1129{1130	int ret;1131	bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,1132					 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);1133 1134	mvm->offload_tid = wowlan_config_cmd->offloading_tid;1135 1136	if (!unified_image) {1137		ret = iwl_mvm_switch_to_d3(mvm);1138		if (ret)1139			return ret;1140 1141		ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);1142		if (ret)1143			return ret;1144	}1145 1146	ret = iwl_mvm_wowlan_config_key_params(mvm, vif, mvm_link);1147	if (ret)1148		return ret;1149 1150	ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,1151				   sizeof(*wowlan_config_cmd),1152				   wowlan_config_cmd);1153	if (ret)1154		return ret;1155 1156	if (fw_has_api(&mvm->fw->ucode_capa,1157		       IWL_UCODE_TLV_API_WOWLAN_TCP_SYN_WAKE))1158		ret = iwl_mvm_send_patterns(mvm, mvm_link, wowlan);1159	else1160		ret = iwl_mvm_send_patterns_v1(mvm, wowlan);1161	if (ret)1162		return ret;1163 1164	return iwl_mvm_send_proto_offload(mvm, vif, false, true, 0,1165					  mvm_link->ap_sta_id);1166}1167 1168static int1169iwl_mvm_netdetect_config(struct iwl_mvm *mvm,1170			 struct cfg80211_wowlan *wowlan,1171			 struct cfg80211_sched_scan_request *nd_config,1172			 struct ieee80211_vif *vif)1173{1174	int ret;1175	bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,1176					 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);1177 1178	if (!unified_image) {1179		ret = iwl_mvm_switch_to_d3(mvm);1180		if (ret)1181			return ret;1182	} else {1183		/* In theory, we wouldn't have to stop a running sched1184		 * scan in order to start another one (for1185		 * net-detect).  But in practice this doesn't seem to1186		 * work properly, so stop any running sched_scan now.1187		 */1188		ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_SCHED, true);1189		if (ret)1190			return ret;1191	}1192 1193	ret = iwl_mvm_sched_scan_start(mvm, vif, nd_config, &mvm->nd_ies,1194				       IWL_MVM_SCAN_NETDETECT);1195	if (ret)1196		return ret;1197 1198	if (WARN_ON(mvm->nd_match_sets || mvm->nd_channels))1199		return -EBUSY;1200 1201	/* save the sched scan matchsets... */1202	if (nd_config->n_match_sets) {1203		mvm->nd_match_sets = kmemdup(nd_config->match_sets,1204					     sizeof(*nd_config->match_sets) *1205					     nd_config->n_match_sets,1206					     GFP_KERNEL);1207		if (mvm->nd_match_sets)1208			mvm->n_nd_match_sets = nd_config->n_match_sets;1209	}1210 1211	/* ...and the sched scan channels for later reporting */1212	mvm->nd_channels = kmemdup(nd_config->channels,1213				   sizeof(*nd_config->channels) *1214				   nd_config->n_channels,1215				   GFP_KERNEL);1216	if (mvm->nd_channels)1217		mvm->n_nd_channels = nd_config->n_channels;1218 1219	return 0;1220}1221 1222static void iwl_mvm_free_nd(struct iwl_mvm *mvm)1223{1224	kfree(mvm->nd_match_sets);1225	mvm->nd_match_sets = NULL;1226	mvm->n_nd_match_sets = 0;1227	kfree(mvm->nd_channels);1228	mvm->nd_channels = NULL;1229	mvm->n_nd_channels = 0;1230}1231 1232static int __iwl_mvm_suspend(struct ieee80211_hw *hw,1233			     struct cfg80211_wowlan *wowlan,1234			     bool test)1235{1236	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);1237	struct ieee80211_vif *vif = NULL;1238	struct iwl_mvm_vif *mvmvif = NULL;1239	struct ieee80211_sta *ap_sta = NULL;1240	struct iwl_mvm_vif_link_info *mvm_link;1241	struct iwl_d3_manager_config d3_cfg_cmd_data = {1242		/*1243		 * Program the minimum sleep time to 10 seconds, as many1244		 * platforms have issues processing a wakeup signal while1245		 * still being in the process of suspending.1246		 */1247		.min_sleep_time = cpu_to_le32(10 * 1000 * 1000),1248	};1249	struct iwl_host_cmd d3_cfg_cmd = {1250		.id = D3_CONFIG_CMD,1251		.flags = CMD_WANT_SKB | CMD_SEND_IN_D3,1252		.data[0] = &d3_cfg_cmd_data,1253		.len[0] = sizeof(d3_cfg_cmd_data),1254	};1255	int ret;1256	int len __maybe_unused;1257	bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,1258					 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);1259 1260	if (!wowlan) {1261		/*1262		 * mac80211 shouldn't get here, but for D3 test1263		 * it doesn't warrant a warning1264		 */1265		WARN_ON(!test);1266		return -EINVAL;1267	}1268 1269	vif = iwl_mvm_get_bss_vif(mvm);1270	if (IS_ERR_OR_NULL(vif))1271		return 1;1272 1273	ret = iwl_mvm_block_esr_sync(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN);1274	if (ret)1275		return ret;1276 1277	mutex_lock(&mvm->mutex);1278 1279	set_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);1280 1281	synchronize_net();1282 1283	mvmvif = iwl_mvm_vif_from_mac80211(vif);1284 1285	mvm_link = mvmvif->link[iwl_mvm_get_primary_link(vif)];1286	if (WARN_ON_ONCE(!mvm_link)) {1287		ret = -EINVAL;1288		goto out_noreset;1289	}1290 1291	if (mvm_link->ap_sta_id == IWL_MVM_INVALID_STA) {1292		/* if we're not associated, this must be netdetect */1293		if (!wowlan->nd_config) {1294			ret = 1;1295			goto out_noreset;1296		}1297 1298		ret = iwl_mvm_netdetect_config(1299			mvm, wowlan, wowlan->nd_config, vif);1300		if (ret)1301			goto out;1302 1303		mvm->net_detect = true;1304	} else {1305		struct iwl_wowlan_config_cmd wowlan_config_cmd = {1306			.offloading_tid = 0,1307		};1308 1309		wowlan_config_cmd.sta_id = mvm_link->ap_sta_id;1310 1311		ap_sta = rcu_dereference_protected(1312			mvm->fw_id_to_mac_id[mvm_link->ap_sta_id],1313			lockdep_is_held(&mvm->mutex));1314		if (IS_ERR_OR_NULL(ap_sta)) {1315			ret = -EINVAL;1316			goto out_noreset;1317		}1318 1319		ret = iwl_mvm_sta_ensure_queue(1320			mvm, ap_sta->txq[wowlan_config_cmd.offloading_tid]);1321		if (ret)1322			goto out_noreset;1323 1324		ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd,1325						vif, mvmvif, ap_sta);1326		if (ret)1327			goto out_noreset;1328		ret = iwl_mvm_wowlan_config(mvm, wowlan, &wowlan_config_cmd,1329					    vif, mvmvif, mvm_link, ap_sta);1330		if (ret)1331			goto out;1332 1333		mvm->net_detect = false;1334	}1335 1336	ret = iwl_mvm_power_update_device(mvm);1337	if (ret)1338		goto out;1339 1340	ret = iwl_mvm_power_update_mac(mvm);1341	if (ret)1342		goto out;1343 1344#ifdef CONFIG_IWLWIFI_DEBUGFS1345	if (mvm->d3_wake_sysassert)1346		d3_cfg_cmd_data.wakeup_flags |=1347			cpu_to_le32(IWL_WAKEUP_D3_CONFIG_FW_ERROR);1348#endif1349 1350	/*1351	 * Prior to 9000 device family the driver needs to stop the dbg1352	 * recording before entering D3. In later devices the FW stops the1353	 * recording automatically.1354	 */1355	if (mvm->trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_9000)1356		iwl_fw_dbg_stop_restart_recording(&mvm->fwrt, NULL, true);1357 1358	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;1359 1360	/* must be last -- this switches firmware state */1361	ret = iwl_mvm_send_cmd(mvm, &d3_cfg_cmd);1362	if (ret)1363		goto out;1364#ifdef CONFIG_IWLWIFI_DEBUGFS1365	len = iwl_rx_packet_payload_len(d3_cfg_cmd.resp_pkt);1366	if (len >= sizeof(u32)) {1367		mvm->d3_test_pme_ptr =1368			le32_to_cpup((__le32 *)d3_cfg_cmd.resp_pkt->data);1369	}1370#endif1371	iwl_free_resp(&d3_cfg_cmd);1372 1373	clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);1374 1375	ret = iwl_trans_d3_suspend(mvm->trans, test, !unified_image);1376 out:1377	if (ret < 0) {1378		iwl_mvm_free_nd(mvm);1379 1380		if (!unified_image) {1381			if (mvm->fw_restart > 0) {1382				mvm->fw_restart--;1383				ieee80211_restart_hw(mvm->hw);1384			}1385		}1386 1387		clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);1388	}1389 out_noreset:1390	mutex_unlock(&mvm->mutex);1391 1392	return ret;1393}1394 1395int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)1396{1397	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);1398 1399	iwl_mvm_pause_tcm(mvm, true);1400 1401	mutex_lock(&mvm->mutex);1402	iwl_fw_runtime_suspend(&mvm->fwrt);1403	mutex_unlock(&mvm->mutex);1404 1405	return __iwl_mvm_suspend(hw, wowlan, false);1406}1407 1408struct iwl_multicast_key_data {1409	u8 key[WOWLAN_KEY_MAX_SIZE];1410	u8 len;1411	u8 flags;1412	u8 id;1413	u8 ipn[6];1414};1415 1416/* converted data from the different status responses */1417struct iwl_wowlan_status_data {1418	u64 replay_ctr;1419	u32 num_of_gtk_rekeys;1420	u32 received_beacons;1421	u32 wakeup_reasons;1422	u32 wake_packet_length;1423	u32 wake_packet_bufsize;1424	u16 pattern_number;1425	u16 non_qos_seq_ctr;1426	u16 qos_seq_ctr[8];1427	u8 tid_tear_down;1428 1429	struct {1430		/* including RX MIC key for TKIP */1431		u8 key[WOWLAN_KEY_MAX_SIZE];1432		u8 len;1433		u8 flags;1434		u8 id;1435	} gtk[WOWLAN_GTK_KEYS_NUM];1436 1437	struct {1438		/*1439		 * We store both the TKIP and AES representations1440		 * coming from the firmware because we decode the1441		 * data from there before we iterate the keys and1442		 * know which one we need.1443		 */1444		struct {1445			struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT];1446		} tkip, aes;1447 1448		/*1449		 * We use -1 for when we have valid data but don't know1450		 * the key ID from firmware, and thus it needs to be1451		 * installed with the last key (depending on rekeying).1452		 */1453		s8 key_id;1454		bool valid;1455	} gtk_seq[2];1456 1457	struct {1458		/* Same as above */1459		struct {1460			struct ieee80211_key_seq seq[IWL_MAX_TID_COUNT];1461			u64 tx_pn;1462		} tkip, aes;1463	} ptk;1464 1465	struct iwl_multicast_key_data igtk;1466	struct iwl_multicast_key_data bigtk[WOWLAN_BIGTK_KEYS_NUM];1467 1468	int num_mlo_keys;1469	struct iwl_wowlan_mlo_gtk mlo_keys[WOWLAN_MAX_MLO_KEYS];1470 1471	u8 *wake_packet;1472};1473 1474static void iwl_mvm_report_wakeup_reasons(struct iwl_mvm *mvm,1475					  struct ieee80211_vif *vif,1476					  struct iwl_wowlan_status_data *status)1477{1478	struct sk_buff *pkt = NULL;1479	struct cfg80211_wowlan_wakeup wakeup = {1480		.pattern_idx = -1,1481	};1482	struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;1483	u32 reasons = status->wakeup_reasons;1484 1485	if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) {1486		wakeup_report = NULL;1487		goto report;1488	}1489 1490	pm_wakeup_event(mvm->dev, 0);1491 1492	if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)1493		wakeup.magic_pkt = true;1494 1495	if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN)1496		wakeup.pattern_idx =1497			status->pattern_number;1498 1499	if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |1500		       IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH |1501		       IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE))1502		wakeup.disconnect = true;1503 1504	if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE)1505		wakeup.gtk_rekey_failure = true;1506 1507	if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)1508		wakeup.rfkill_release = true;1509 1510	if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST)1511		wakeup.eap_identity_req = true;1512 1513	if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE)1514		wakeup.four_way_handshake = true;1515 1516	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS)1517		wakeup.tcp_connlost = true;1518 1519	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE)1520		wakeup.tcp_nomoretokens = true;1521 1522	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET)1523		wakeup.tcp_match = true;1524 1525	if (reasons & IWL_WAKEUP_BY_11W_UNPROTECTED_DEAUTH_OR_DISASSOC)1526		wakeup.unprot_deauth_disassoc = true;1527 1528	if (status->wake_packet) {1529		int pktsize = status->wake_packet_bufsize;1530		int pktlen = status->wake_packet_length;1531		const u8 *pktdata = status->wake_packet;1532		const struct ieee80211_hdr *hdr = (const void *)pktdata;1533		int truncated = pktlen - pktsize;1534 1535		/* this would be a firmware bug */1536		if (WARN_ON_ONCE(truncated < 0))1537			truncated = 0;1538 1539		if (ieee80211_is_data(hdr->frame_control)) {1540			int hdrlen = ieee80211_hdrlen(hdr->frame_control);1541			int ivlen = 0, icvlen = 4; /* also FCS */1542 1543			pkt = alloc_skb(pktsize, GFP_KERNEL);1544			if (!pkt)1545				goto report;1546 1547			skb_put_data(pkt, pktdata, hdrlen);1548			pktdata += hdrlen;1549			pktsize -= hdrlen;1550 1551			if (ieee80211_has_protected(hdr->frame_control)) {1552				/*1553				 * This is unlocked and using gtk_i(c)vlen,1554				 * but since everything is under RTNL still1555				 * that's not really a problem - changing1556				 * it would be difficult.1557				 */1558				if (is_multicast_ether_addr(hdr->addr1)) {1559					ivlen = mvm->gtk_ivlen;1560					icvlen += mvm->gtk_icvlen;1561				} else {1562					ivlen = mvm->ptk_ivlen;1563					icvlen += mvm->ptk_icvlen;1564				}1565			}1566 1567			/* if truncated, FCS/ICV is (partially) gone */1568			if (truncated >= icvlen) {1569				icvlen = 0;1570				truncated -= icvlen;1571			} else {1572				icvlen -= truncated;1573				truncated = 0;1574			}1575 1576			pktsize -= ivlen + icvlen;1577			pktdata += ivlen;1578 1579			skb_put_data(pkt, pktdata, pktsize);1580 1581			if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))1582				goto report;1583			wakeup.packet = pkt->data;1584			wakeup.packet_present_len = pkt->len;1585			wakeup.packet_len = pkt->len - truncated;1586			wakeup.packet_80211 = false;1587		} else {1588			int fcslen = 4;1589 1590			if (truncated >= 4) {1591				truncated -= 4;1592				fcslen = 0;1593			} else {1594				fcslen -= truncated;1595				truncated = 0;1596			}1597			pktsize -= fcslen;1598			wakeup.packet = status->wake_packet;1599			wakeup.packet_present_len = pktsize;1600			wakeup.packet_len = pktlen - truncated;1601			wakeup.packet_80211 = true;1602		}1603	}1604 1605 report:1606	ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);1607	kfree_skb(pkt);1608}1609 1610static void iwl_mvm_le64_to_aes_seq(__le64 le_pn, struct ieee80211_key_seq *seq)1611{1612	u64 pn = le64_to_cpu(le_pn);1613 1614	seq->ccmp.pn[0] = pn >> 40;1615	seq->ccmp.pn[1] = pn >> 32;1616	seq->ccmp.pn[2] = pn >> 24;1617	seq->ccmp.pn[3] = pn >> 16;1618	seq->ccmp.pn[4] = pn >> 8;1619	seq->ccmp.pn[5] = pn;1620}1621 1622static void iwl_mvm_aes_sc_to_seq(struct aes_sc *sc,1623				  struct ieee80211_key_seq *seq)1624{1625	iwl_mvm_le64_to_aes_seq(sc->pn, seq);1626}1627 1628static void iwl_mvm_le64_to_tkip_seq(__le64 le_pn, struct ieee80211_key_seq *seq)1629{1630	u64 pn = le64_to_cpu(le_pn);1631 1632	seq->tkip.iv16 = (u16)pn;1633	seq->tkip.iv32 = (u32)(pn >> 16);1634}1635 1636static void iwl_mvm_tkip_sc_to_seq(struct tkip_sc *sc,1637				   struct ieee80211_key_seq *seq)1638{1639	seq->tkip.iv32 = le32_to_cpu(sc->iv32);1640	seq->tkip.iv16 = le16_to_cpu(sc->iv16);1641}1642 1643static void iwl_mvm_set_key_rx_seq_tids(struct ieee80211_key_conf *key,1644					struct ieee80211_key_seq *seq)1645{1646	int tid;1647 1648	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)1649		ieee80211_set_key_rx_seq(key, tid, &seq[tid]);1650}1651 1652static void iwl_mvm_set_aes_ptk_rx_seq(struct iwl_mvm *mvm,1653				       struct iwl_wowlan_status_data *status,1654				       struct ieee80211_sta *sta,1655				       struct ieee80211_key_conf *key)1656{1657	struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);1658	struct iwl_mvm_key_pn *ptk_pn;1659	int tid;1660 1661	iwl_mvm_set_key_rx_seq_tids(key, status->ptk.aes.seq);1662 1663	if (!iwl_mvm_has_new_rx_api(mvm))1664		return;1665 1666 1667	rcu_read_lock();1668	ptk_pn = rcu_dereference(mvmsta->ptk_pn[key->keyidx]);1669	if (WARN_ON(!ptk_pn)) {1670		rcu_read_unlock();1671		return;1672	}1673 1674	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {1675		int i;1676 1677		for (i = 1; i < mvm->trans->num_rx_queues; i++)1678			memcpy(ptk_pn->q[i].pn[tid],1679			       status->ptk.aes.seq[tid].ccmp.pn,1680			       IEEE80211_CCMP_PN_LEN);1681	}1682	rcu_read_unlock();1683}1684 1685static void iwl_mvm_convert_key_counters(struct iwl_wowlan_status_data *status,1686					 union iwl_all_tsc_rsc *sc)1687{1688	int i;1689 1690	BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_MAX_TID_COUNT);1691	BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_NUM_RSC);1692 1693	/* GTK RX counters */1694	for (i = 0; i < IWL_MAX_TID_COUNT; i++) {1695		iwl_mvm_tkip_sc_to_seq(&sc->tkip.multicast_rsc[i],1696				       &status->gtk_seq[0].tkip.seq[i]);1697		iwl_mvm_aes_sc_to_seq(&sc->aes.multicast_rsc[i],1698				      &status->gtk_seq[0].aes.seq[i]);1699	}1700	status->gtk_seq[0].valid = true;1701	status->gtk_seq[0].key_id = -1;1702 1703	/* PTK TX counter */1704	status->ptk.tkip.tx_pn = (u64)le16_to_cpu(sc->tkip.tsc.iv16) |1705				 ((u64)le32_to_cpu(sc->tkip.tsc.iv32) << 16);1706	status->ptk.aes.tx_pn = le64_to_cpu(sc->aes.tsc.pn);1707 1708	/* PTK RX counters */1709	for (i = 0; i < IWL_MAX_TID_COUNT; i++) {1710		iwl_mvm_tkip_sc_to_seq(&sc->tkip.unicast_rsc[i],1711				       &status->ptk.tkip.seq[i]);1712		iwl_mvm_aes_sc_to_seq(&sc->aes.unicast_rsc[i],1713				      &status->ptk.aes.seq[i]);1714	}1715}1716 1717static void1718iwl_mvm_convert_key_counters_v5_gtk_seq(struct iwl_wowlan_status_data *status,1719					struct iwl_wowlan_all_rsc_tsc_v5 *sc,1720					unsigned int idx, unsigned int key_id)1721{1722	int tid;1723 1724	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {1725		iwl_mvm_le64_to_tkip_seq(sc->mcast_rsc[idx][tid],1726					 &status->gtk_seq[idx].tkip.seq[tid]);1727		iwl_mvm_le64_to_aes_seq(sc->mcast_rsc[idx][tid],1728					&status->gtk_seq[idx].aes.seq[tid]);1729	}1730 1731	status->gtk_seq[idx].valid = true;1732	status->gtk_seq[idx].key_id = key_id;1733}1734 1735static void1736iwl_mvm_convert_key_counters_v5(struct iwl_wowlan_status_data *status,1737				struct iwl_wowlan_all_rsc_tsc_v5 *sc)1738{1739	int i, tid;1740 1741	BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_MAX_TID_COUNT);1742	BUILD_BUG_ON(IWL_MAX_TID_COUNT > IWL_NUM_RSC);1743	BUILD_BUG_ON(ARRAY_SIZE(sc->mcast_rsc) != ARRAY_SIZE(status->gtk_seq));1744 1745	/* GTK RX counters */1746	for (i = 0; i < ARRAY_SIZE(sc->mcast_key_id_map); i++) {1747		u8 entry = sc->mcast_key_id_map[i];1748 1749		if (entry < ARRAY_SIZE(sc->mcast_rsc))1750			iwl_mvm_convert_key_counters_v5_gtk_seq(status, sc,1751								entry, i);1752	}1753 1754	/* PTK TX counters not needed, assigned in device */1755 1756	/* PTK RX counters */1757	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {1758		iwl_mvm_le64_to_tkip_seq(sc->ucast_rsc[tid],1759					 &status->ptk.tkip.seq[tid]);1760		iwl_mvm_le64_to_aes_seq(sc->ucast_rsc[tid],1761					&status->ptk.aes.seq[tid]);1762	}1763}1764 1765static void iwl_mvm_set_key_rx_seq_idx(struct ieee80211_key_conf *key,1766				       struct iwl_wowlan_status_data *status,1767				       int idx)1768{1769	switch (key->cipher) {1770	case WLAN_CIPHER_SUITE_CCMP:1771	case WLAN_CIPHER_SUITE_GCMP:1772	case WLAN_CIPHER_SUITE_GCMP_256:1773		iwl_mvm_set_key_rx_seq_tids(key, status->gtk_seq[idx].aes.seq);1774		break;1775	case WLAN_CIPHER_SUITE_TKIP:1776		iwl_mvm_set_key_rx_seq_tids(key, status->gtk_seq[idx].tkip.seq);1777		break;1778	default:1779		WARN_ON(1);1780	}1781}1782 1783static void iwl_mvm_set_key_rx_seq(struct ieee80211_key_conf *key,1784				   struct iwl_wowlan_status_data *status,1785				   bool installed)1786{1787	int i;1788 1789	for (i = 0; i < ARRAY_SIZE(status->gtk_seq); i++) {1790		if (!status->gtk_seq[i].valid)1791			continue;1792 1793		/* Handle the case where we know the key ID */1794		if (status->gtk_seq[i].key_id == key->keyidx) {1795			s8 new_key_id = -1;1796 1797			if (status->num_of_gtk_rekeys)1798				new_key_id = status->gtk[0].flags &1799						IWL_WOWLAN_GTK_IDX_MASK;1800 1801			/* Don't install a new key's value to an old key */1802			if (new_key_id != key->keyidx)1803				iwl_mvm_set_key_rx_seq_idx(key, status, i);1804			continue;1805		}1806 1807		/* handle the case where we didn't, last key only */1808		if (status->gtk_seq[i].key_id == -1 &&1809		    (!status->num_of_gtk_rekeys || installed))1810			iwl_mvm_set_key_rx_seq_idx(key, status, i);1811	}1812}1813 1814struct iwl_mvm_d3_gtk_iter_data {1815	struct iwl_mvm *mvm;1816	struct iwl_wowlan_status_data *status;1817	u32 gtk_cipher, igtk_cipher, bigtk_cipher;1818	bool unhandled_cipher, igtk_support, bigtk_support;1819	int num_keys;1820};1821 1822static void iwl_mvm_d3_find_last_keys(struct ieee80211_hw *hw,1823				      struct ieee80211_vif *vif,1824				      struct ieee80211_sta *sta,1825				      struct ieee80211_key_conf *key,1826				      void *_data)1827{1828	struct iwl_mvm_d3_gtk_iter_data *data = _data;1829	int link_id = vif->active_links ? __ffs(vif->active_links) : -1;1830 1831	if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id)1832		return;1833 1834	if (data->unhandled_cipher)1835		return;1836 1837	switch (key->cipher) {1838	case WLAN_CIPHER_SUITE_WEP40:1839	case WLAN_CIPHER_SUITE_WEP104:1840		/* ignore WEP completely, nothing to do */1841		return;1842	case WLAN_CIPHER_SUITE_CCMP:1843	case WLAN_CIPHER_SUITE_GCMP:1844	case WLAN_CIPHER_SUITE_GCMP_256:1845	case WLAN_CIPHER_SUITE_TKIP:1846		/* we support these */1847		data->gtk_cipher = key->cipher;1848		break;1849	case WLAN_CIPHER_SUITE_BIP_GMAC_128:1850	case WLAN_CIPHER_SUITE_BIP_GMAC_256:1851	case WLAN_CIPHER_SUITE_BIP_CMAC_256:1852	case WLAN_CIPHER_SUITE_AES_CMAC:1853		/* we support these */1854		if (data->igtk_support &&1855		    (key->keyidx == 4 || key->keyidx == 5)) {1856			data->igtk_cipher = key->cipher;1857		} else if (data->bigtk_support &&1858			   (key->keyidx == 6 || key->keyidx == 7)) {1859			data->bigtk_cipher = key->cipher;1860		} else {1861			data->unhandled_cipher = true;1862			return;1863		}1864		break;1865	default:1866		/* everything else - disconnect from AP */1867		data->unhandled_cipher = true;1868		return;1869	}1870 1871	data->num_keys++;1872}1873 1874static void1875iwl_mvm_d3_set_igtk_bigtk_ipn(const struct iwl_multicast_key_data *key,1876			      struct ieee80211_key_seq *seq, u32 cipher)1877{1878	switch (cipher) {1879	case WLAN_CIPHER_SUITE_BIP_GMAC_128:1880	case WLAN_CIPHER_SUITE_BIP_GMAC_256:1881		BUILD_BUG_ON(sizeof(seq->aes_gmac.pn) != sizeof(key->ipn));1882		memcpy(seq->aes_gmac.pn, key->ipn, sizeof(seq->aes_gmac.pn));1883		break;1884	case WLAN_CIPHER_SUITE_BIP_CMAC_256:1885	case WLAN_CIPHER_SUITE_AES_CMAC:1886		BUILD_BUG_ON(sizeof(seq->aes_cmac.pn) != sizeof(key->ipn));1887		memcpy(seq->aes_cmac.pn, key->ipn, sizeof(seq->aes_cmac.pn));1888		break;1889	default:1890		WARN_ON(1);1891	}1892}1893 1894static void1895iwl_mvm_d3_update_igtk_bigtk(struct iwl_wowlan_status_data *status,1896			     struct ieee80211_key_conf *key,1897			     struct iwl_multicast_key_data *key_data)1898{1899	if (status->num_of_gtk_rekeys && key_data->len) {1900		/* remove rekeyed key */1901		ieee80211_remove_key(key);1902	} else {1903		struct ieee80211_key_seq seq;1904 1905		iwl_mvm_d3_set_igtk_bigtk_ipn(key_data,1906					      &seq,1907					      key->cipher);1908		ieee80211_set_key_rx_seq(key, 0, &seq);1909	}1910}1911 1912static void iwl_mvm_d3_update_keys(struct ieee80211_hw *hw,1913				   struct ieee80211_vif *vif,1914				   struct ieee80211_sta *sta,1915				   struct ieee80211_key_conf *key,1916				   void *_data)1917{1918	struct iwl_mvm_d3_gtk_iter_data *data = _data;1919	struct iwl_wowlan_status_data *status = data->status;1920	s8 keyidx;1921	int link_id = vif->active_links ? __ffs(vif->active_links) : -1;1922 1923	if (link_id >= 0 && key->link_id >= 0 && link_id != key->link_id)1924		return;1925 1926	if (data->unhandled_cipher)1927		return;1928 1929	switch (key->cipher) {1930	case WLAN_CIPHER_SUITE_WEP40:1931	case WLAN_CIPHER_SUITE_WEP104:1932		/* ignore WEP completely, nothing to do */1933		return;1934	case WLAN_CIPHER_SUITE_CCMP:1935	case WLAN_CIPHER_SUITE_GCMP:1936	case WLAN_CIPHER_SUITE_GCMP_256:1937		if (sta) {1938			atomic64_set(&key->tx_pn, status->ptk.aes.tx_pn);1939			iwl_mvm_set_aes_ptk_rx_seq(data->mvm, status, sta, key);1940			return;1941		}1942		fallthrough;1943	case WLAN_CIPHER_SUITE_TKIP:1944		if (sta) {1945			atomic64_set(&key->tx_pn, status->ptk.tkip.tx_pn);1946			iwl_mvm_set_key_rx_seq_tids(key, status->ptk.tkip.seq);1947			return;1948		}1949		keyidx = key->keyidx;1950		/* The current key is always sent by the FW, even if it wasn't1951		 * rekeyed during D3.1952		 * We remove an existing key if it has the same index as1953		 * a new key1954		 */1955		if (status->num_of_gtk_rekeys &&1956		    ((status->gtk[0].len && keyidx == status->gtk[0].id) ||1957		     (status->gtk[1].len && keyidx == status->gtk[1].id))) {1958			ieee80211_remove_key(key);1959		} else {1960			iwl_mvm_set_key_rx_seq(key, data->status, false);1961		}1962		break;1963	case WLAN_CIPHER_SUITE_BIP_GMAC_128:1964	case WLAN_CIPHER_SUITE_BIP_GMAC_256:1965	case WLAN_CIPHER_SUITE_BIP_CMAC_256:1966	case WLAN_CIPHER_SUITE_AES_CMAC:1967		if (key->keyidx == 4 || key->keyidx == 5) {1968			iwl_mvm_d3_update_igtk_bigtk(status, key,1969						     &status->igtk);1970		}1971		if (key->keyidx == 6 || key->keyidx == 7) {1972			u8 idx = key->keyidx == status->bigtk[1].id;1973 1974			iwl_mvm_d3_update_igtk_bigtk(status, key,1975						     &status->bigtk[idx]);1976		}1977	}1978}1979 1980struct iwl_mvm_d3_mlo_old_keys {1981	u32 cipher[IEEE80211_MLD_MAX_NUM_LINKS][WOWLAN_MLO_GTK_KEY_NUM_TYPES];1982	struct ieee80211_key_conf *key[IEEE80211_MLD_MAX_NUM_LINKS][8];1983};1984 1985static void iwl_mvm_mlo_key_ciphers(struct ieee80211_hw *hw,1986				    struct ieee80211_vif *vif,1987				    struct ieee80211_sta *sta,1988				    struct ieee80211_key_conf *key,1989				    void *data)1990{1991	struct iwl_mvm_d3_mlo_old_keys *old_keys = data;1992	enum iwl_wowlan_mlo_gtk_type key_type;1993 1994	if (key->link_id < 0)1995		return;1996 1997	if (WARN_ON(key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||1998		    key->keyidx >= 8))1999		return;2000 2001	if (WARN_ON(old_keys->key[key->link_id][key->keyidx]))2002		return;2003 2004	switch (key->cipher) {2005	case WLAN_CIPHER_SUITE_CCMP:2006	case WLAN_CIPHER_SUITE_GCMP:2007	case WLAN_CIPHER_SUITE_GCMP_256:2008		key_type = WOWLAN_MLO_GTK_KEY_TYPE_GTK;2009		break;2010	case WLAN_CIPHER_SUITE_BIP_GMAC_128:2011	case WLAN_CIPHER_SUITE_BIP_GMAC_256:2012	case WLAN_CIPHER_SUITE_BIP_CMAC_256:2013	case WLAN_CIPHER_SUITE_AES_CMAC:2014		if (key->keyidx == 4 || key->keyidx == 5) {2015			key_type = WOWLAN_MLO_GTK_KEY_TYPE_IGTK;2016			break;2017		} else if (key->keyidx == 6 || key->keyidx == 7) {2018			key_type = WOWLAN_MLO_GTK_KEY_TYPE_BIGTK;2019			break;2020		}2021		return;2022	default:2023		/* ignore WEP/TKIP or unknown ciphers */2024		return;2025	}2026 2027	old_keys->cipher[key->link_id][key_type] = key->cipher;2028	old_keys->key[key->link_id][key->keyidx] = key;2029}2030 2031static bool iwl_mvm_mlo_gtk_rekey(struct iwl_wowlan_status_data *status,2032				  struct ieee80211_vif *vif,2033				  struct iwl_mvm *mvm)2034{2035	int i;2036	struct iwl_mvm_d3_mlo_old_keys *old_keys;2037	bool ret = true;2038 2039	IWL_DEBUG_WOWLAN(mvm, "Num of MLO Keys: %d\n", status->num_mlo_keys);2040	if (!status->num_mlo_keys)2041		return true;2042 2043	old_keys = kzalloc(sizeof(*old_keys), GFP_KERNEL);2044	if (!old_keys)2045		return false;2046 2047	/* find the cipher for each mlo key */2048	ieee80211_iter_keys(mvm->hw, vif, iwl_mvm_mlo_key_ciphers, old_keys);2049 2050	for (i = 0; i < status->num_mlo_keys; i++) {2051		struct iwl_wowlan_mlo_gtk *mlo_key = &status->mlo_keys[i];2052		struct ieee80211_key_conf *key, *old_key;2053		struct ieee80211_key_seq seq;2054		struct {2055			struct ieee80211_key_conf conf;2056			u8 key[32];2057		} conf = {};2058		u16 flags = le16_to_cpu(mlo_key->flags);2059		int j, link_id, key_id, key_type;2060 2061		link_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK);2062		key_id = u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK);2063		key_type = u16_get_bits(flags,2064					WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK);2065 2066		if (!(vif->valid_links & BIT(link_id)))2067			continue;2068 2069		if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||2070			    key_id >= 8 ||2071			    key_type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES))2072			continue;2073 2074		conf.conf.cipher = old_keys->cipher[link_id][key_type];2075		/* WARN_ON? */2076		if (!conf.conf.cipher)2077			continue;2078 2079		conf.conf.keylen = 0;2080		switch (conf.conf.cipher) {2081		case WLAN_CIPHER_SUITE_CCMP:2082		case WLAN_CIPHER_SUITE_GCMP:2083			conf.conf.keylen = WLAN_KEY_LEN_CCMP;2084			break;2085		case WLAN_CIPHER_SUITE_GCMP_256:2086			conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;2087			break;2088		case WLAN_CIPHER_SUITE_BIP_GMAC_128:2089			conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;2090			break;2091		case WLAN_CIPHER_SUITE_BIP_GMAC_256:2092			conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;2093			break;2094		case WLAN_CIPHER_SUITE_AES_CMAC:2095			conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;2096			break;2097		case WLAN_CIPHER_SUITE_BIP_CMAC_256:2098			conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;2099			break;2100		}2101 2102		if (WARN_ON(!conf.conf.keylen ||2103			    conf.conf.keylen > sizeof(conf.key)))2104			continue;2105 2106		memcpy(conf.conf.key, mlo_key->key, conf.conf.keylen);2107		conf.conf.keyidx = key_id;2108 2109		old_key = old_keys->key[link_id][key_id];2110		if (old_key) {2111			IWL_DEBUG_WOWLAN(mvm,2112					 "Remove MLO key id %d, link id %d\n",2113					 key_id, link_id);2114			ieee80211_remove_key(old_key);2115		}2116 2117		IWL_DEBUG_WOWLAN(mvm, "Add MLO key id %d, link id %d\n",2118				 key_id, link_id);2119		key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);2120		if (WARN_ON(IS_ERR(key))) {2121			ret = false;2122			goto out;2123		}2124 2125		/*2126		 * mac80211 expects the pn in big-endian2127		 * also note that seq is a union of all cipher types2128		 * (ccmp, gcmp, cmac, gmac), and they all have the same2129		 * pn field (of length 6) so just copy it to ccmp.pn.2130		 */2131		for (j = 5; j >= 0; j--)2132			seq.ccmp.pn[5 - j] = mlo_key->pn[j];2133 2134		/* group keys are non-QoS and use TID 0 */2135		ieee80211_set_key_rx_seq(key, 0, &seq);2136	}2137 2138out:2139	kfree(old_keys);2140	return ret;2141}2142 2143static bool iwl_mvm_gtk_rekey(struct iwl_wowlan_status_data *status,2144			      struct ieee80211_vif *vif,2145			      struct iwl_mvm *mvm, u32 gtk_cipher)2146{2147	int i, j;2148	struct ieee80211_key_conf *key;2149	struct {2150		struct ieee80211_key_conf conf;2151		u8 key[32];2152	} conf = {2153		.conf.cipher = gtk_cipher,2154	};2155	int link_id = vif->active_links ? __ffs(vif->active_links) : -1;2156 2157	BUILD_BUG_ON(WLAN_KEY_LEN_CCMP != WLAN_KEY_LEN_GCMP);2158	BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_CCMP);2159	BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_GCMP_256);2160	BUILD_BUG_ON(sizeof(conf.key) < WLAN_KEY_LEN_TKIP);2161	BUILD_BUG_ON(sizeof(conf.key) < sizeof(status->gtk[0].key));2162 2163	switch (gtk_cipher) {2164	case WLAN_CIPHER_SUITE_CCMP:2165	case WLAN_CIPHER_SUITE_GCMP:2166		conf.conf.keylen = WLAN_KEY_LEN_CCMP;2167		break;2168	case WLAN_CIPHER_SUITE_GCMP_256:2169		conf.conf.keylen = WLAN_KEY_LEN_GCMP_256;2170		break;2171	case WLAN_CIPHER_SUITE_TKIP:2172		conf.conf.keylen = WLAN_KEY_LEN_TKIP;2173		break;2174	default:2175		WARN_ON(1);2176	}2177 2178	for (i = 0; i < ARRAY_SIZE(status->gtk); i++) {2179		if (!status->gtk[i].len)2180			continue;2181 2182		conf.conf.keyidx = status->gtk[i].id;2183		IWL_DEBUG_WOWLAN(mvm,2184				 "Received from FW GTK cipher %d, key index %d\n",2185				 conf.conf.cipher, conf.conf.keyidx);2186		memcpy(conf.conf.key, status->gtk[i].key,2187		       sizeof(status->gtk[i].key));2188 2189		key = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);2190		if (IS_ERR(key))2191			return false;2192 2193		for (j = 0; j < ARRAY_SIZE(status->gtk_seq); j++) {2194			if (!status->gtk_seq[j].valid ||2195			    status->gtk_seq[j].key_id != key->keyidx)2196				continue;2197			iwl_mvm_set_key_rx_seq_idx(key, status, j);2198			break;2199		}2200		WARN_ON(j == ARRAY_SIZE(status->gtk_seq));2201	}2202 2203	return true;2204}2205 2206static bool2207iwl_mvm_d3_igtk_bigtk_rekey_add(struct iwl_wowlan_status_data *status,2208				struct ieee80211_vif *vif, u32 cipher,2209				struct iwl_multicast_key_data *key_data)2210{2211	struct ieee80211_key_conf *key_config;2212	struct {2213		struct ieee80211_key_conf conf;2214		u8 key[WOWLAN_KEY_MAX_SIZE];2215	} conf = {2216		.conf.cipher = cipher,2217		.conf.keyidx = key_data->id,2218	};2219	struct ieee80211_key_seq seq;2220	int link_id = vif->active_links ? __ffs(vif->active_links) : -1;2221 2222	if (!key_data->len)2223		return true;2224 2225	iwl_mvm_d3_set_igtk_bigtk_ipn(key_data, &seq, conf.conf.cipher);2226 2227	switch (cipher) {2228	case WLAN_CIPHER_SUITE_BIP_GMAC_128:2229		conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_128;2230		break;2231	case WLAN_CIPHER_SUITE_BIP_GMAC_256:2232		conf.conf.keylen = WLAN_KEY_LEN_BIP_GMAC_256;2233		break;2234	case WLAN_CIPHER_SUITE_AES_CMAC:2235		conf.conf.keylen = WLAN_KEY_LEN_AES_CMAC;2236		break;2237	case WLAN_CIPHER_SUITE_BIP_CMAC_256:2238		conf.conf.keylen = WLAN_KEY_LEN_BIP_CMAC_256;2239		break;2240	default:2241		WARN_ON(1);2242	}2243	BUILD_BUG_ON(sizeof(conf.key) < sizeof(key_data->key));2244	memcpy(conf.conf.key, key_data->key, conf.conf.keylen);2245 2246	key_config = ieee80211_gtk_rekey_add(vif, &conf.conf, link_id);2247	if (IS_ERR(key_config))2248		return false;2249	ieee80211_set_key_rx_seq(key_config, 0, &seq);2250 2251	if (key_config->keyidx == 4 || key_config->keyidx == 5) {2252		struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);2253		struct iwl_mvm_vif_link_info *mvm_link;2254 2255		link_id = link_id < 0 ? 0 : link_id;2256		mvm_link = mvmvif->link[link_id];2257		mvm_link->igtk = key_config;2258	}2259 2260	return true;2261}2262 2263static int iwl_mvm_lookup_wowlan_status_ver(struct iwl_mvm *mvm)2264{2265	u8 notif_ver;2266 2267	if (!fw_has_api(&mvm->fw->ucode_capa,2268			IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL))2269		return 6;2270 2271	/* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */2272	notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,2273					    WOWLAN_GET_STATUSES, 0);2274	if (!notif_ver)2275		notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP,2276						    WOWLAN_GET_STATUSES, 7);2277 2278	return notif_ver;2279}2280 2281static bool iwl_mvm_setup_connection_keep(struct iwl_mvm *mvm,2282					  struct ieee80211_vif *vif,2283					  struct iwl_wowlan_status_data *status)2284{2285	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);2286	struct iwl_mvm_d3_gtk_iter_data gtkdata = {2287		.mvm = mvm,2288		.status = status,2289	};2290	int i;2291	u32 disconnection_reasons =2292		IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |2293		IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH;2294 2295	if (!status || !vif->bss_conf.bssid)2296		return false;2297 2298	if (iwl_mvm_lookup_wowlan_status_ver(mvm) > 6 ||2299	    iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,2300				    WOWLAN_INFO_NOTIFICATION,2301				    0))2302		gtkdata.igtk_support = true;2303 2304	if (iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,2305				    WOWLAN_INFO_NOTIFICATION,2306				    0) >= 3)2307		gtkdata.bigtk_support = true;2308 2309	/* find last GTK that we used initially, if any */2310	ieee80211_iter_keys(mvm->hw, vif,2311			    iwl_mvm_d3_find_last_keys, &gtkdata);2312	/* not trying to keep connections with MFP/unhandled ciphers */2313	if (gtkdata.unhandled_cipher)2314		return false;2315	if (!gtkdata.num_keys)2316		goto out;2317 2318	/*2319	 * invalidate all other GTKs that might still exist and update2320	 * the one that we used2321	 */2322	ieee80211_iter_keys(mvm->hw, vif,2323			    iwl_mvm_d3_update_keys, &gtkdata);2324 2325	if (status->num_of_gtk_rekeys) {2326		__be64 replay_ctr = cpu_to_be64(status->replay_ctr);2327 2328		IWL_DEBUG_WOWLAN(mvm, "num of GTK rekeying %d\n",2329				 status->num_of_gtk_rekeys);2330 2331		if (!iwl_mvm_gtk_rekey(status, vif, mvm, gtkdata.gtk_cipher))2332			return false;2333 2334		if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif,2335						     gtkdata.igtk_cipher,2336						     &status->igtk))2337			return false;2338 2339		for (i = 0; i < ARRAY_SIZE(status->bigtk); i++) {2340			if (!iwl_mvm_d3_igtk_bigtk_rekey_add(status, vif,2341							     gtkdata.bigtk_cipher,2342							     &status->bigtk[i]))2343				return false;2344		}2345 2346		if (!iwl_mvm_mlo_gtk_rekey(status, vif, mvm))2347			return false;2348 2349		ieee80211_gtk_rekey_notify(vif, vif->bss_conf.bssid,2350					   (void *)&replay_ctr, GFP_KERNEL);2351	}2352 2353out:2354	if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP,2355				    WOWLAN_GET_STATUSES,2356				    IWL_FW_CMD_VER_UNKNOWN) < 10) {2357		mvmvif->seqno_valid = true;2358		/* +0x10 because the set API expects next-to-use, not last-used */2359		mvmvif->seqno = status->non_qos_seq_ctr + 0x10;2360	}2361 2362	if (status->wakeup_reasons & disconnection_reasons)2363		return false;2364 2365	return true;2366}2367 2368static void iwl_mvm_convert_gtk_v2(struct iwl_wowlan_status_data *status,2369				   struct iwl_wowlan_gtk_status_v2 *data)2370{2371	BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data->key));2372	BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +2373		     sizeof(data->tkip_mic_key) >2374		     sizeof(status->gtk[0].key));2375 2376	status->gtk[0].len = data->key_len;2377	status->gtk[0].flags = data->key_flags;2378 2379	memcpy(status->gtk[0].key, data->key, sizeof(data->key));2380 2381	/* if it's as long as the TKIP encryption key, copy MIC key */2382	if (status->gtk[0].len == NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)2383		memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,2384		       data->tkip_mic_key, sizeof(data->tkip_mic_key));2385}2386 2387static void iwl_mvm_convert_gtk_v3(struct iwl_wowlan_status_data *status,2388				   struct iwl_wowlan_gtk_status_v3 *data)2389{2390	int data_idx, status_idx = 0;2391 2392	BUILD_BUG_ON(sizeof(status->gtk[0].key) < sizeof(data[0].key));2393	BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +2394		     sizeof(data[0].tkip_mic_key) >2395		     sizeof(status->gtk[0].key));2396	BUILD_BUG_ON(ARRAY_SIZE(status->gtk) < WOWLAN_GTK_KEYS_NUM);2397	for (data_idx = 0; data_idx < ARRAY_SIZE(status->gtk); data_idx++) {2398		if (!(data[data_idx].key_len))2399			continue;2400		status->gtk[status_idx].len = data[data_idx].key_len;2401		status->gtk[status_idx].flags = data[data_idx].key_flags;2402		status->gtk[status_idx].id = status->gtk[status_idx].flags &2403				    IWL_WOWLAN_GTK_IDX_MASK;2404 2405		memcpy(status->gtk[status_idx].key, data[data_idx].key,2406		       sizeof(data[data_idx].key));2407 2408		/* if it's as long as the TKIP encryption key, copy MIC key */2409		if (status->gtk[status_idx].len ==2410		    NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)2411			memcpy(status->gtk[status_idx].key +2412			       NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,2413			       data[data_idx].tkip_mic_key,2414			       sizeof(data[data_idx].tkip_mic_key));2415		status_idx++;2416	}2417}2418 2419static void iwl_mvm_convert_igtk(struct iwl_wowlan_status_data *status,2420				 struct iwl_wowlan_igtk_status *data)2421{2422	int i;2423 2424	BUILD_BUG_ON(sizeof(status->igtk.key) < sizeof(data->key));2425	BUILD_BUG_ON(sizeof(status->igtk.ipn) != sizeof(data->ipn));2426 2427	if (!data->key_len)2428		return;2429 2430	status->igtk.len = data->key_len;2431	status->igtk.flags = data->key_flags;2432	status->igtk.id = u32_get_bits(data->key_flags,2433				       IWL_WOWLAN_IGTK_BIGTK_IDX_MASK)2434		+ WOWLAN_IGTK_MIN_INDEX;2435 2436	memcpy(status->igtk.key, data->key, sizeof(data->key));2437 2438	/* mac80211 expects big endian for memcmp() to work, convert */2439	for (i = 0; i < sizeof(data->ipn); i++)2440		status->igtk.ipn[i] = data->ipn[sizeof(data->ipn) - i - 1];2441}2442 2443static void iwl_mvm_convert_bigtk(struct iwl_wowlan_status_data *status,2444				  const struct iwl_wowlan_igtk_status *data)2445{2446	int data_idx, status_idx = 0;2447 2448	BUILD_BUG_ON(ARRAY_SIZE(status->bigtk) < WOWLAN_BIGTK_KEYS_NUM);2449 2450	for (data_idx = 0; data_idx < WOWLAN_BIGTK_KEYS_NUM; data_idx++) {2451		if (!data[data_idx].key_len)2452			continue;2453 2454		status->bigtk[status_idx].len = data[data_idx].key_len;2455		status->bigtk[status_idx].flags = data[data_idx].key_flags;2456		status->bigtk[status_idx].id =2457			u32_get_bits(data[data_idx].key_flags,2458				     IWL_WOWLAN_IGTK_BIGTK_IDX_MASK)2459			+ WOWLAN_BIGTK_MIN_INDEX;2460 2461		BUILD_BUG_ON(sizeof(status->bigtk[status_idx].key) <2462			     sizeof(data[data_idx].key));2463		BUILD_BUG_ON(sizeof(status->bigtk[status_idx].ipn) <2464			     sizeof(data[data_idx].ipn));2465 2466		memcpy(status->bigtk[status_idx].key, data[data_idx].key,2467		       sizeof(data[data_idx].key));2468		memcpy(status->bigtk[status_idx].ipn, data[data_idx].ipn,2469		       sizeof(data[data_idx].ipn));2470		status_idx++;2471	}2472}2473 2474static void iwl_mvm_parse_wowlan_info_notif(struct iwl_mvm *mvm,2475					    struct iwl_wowlan_info_notif *data,2476					    struct iwl_wowlan_status_data *status,2477					    u32 len, bool has_mlo_keys)2478{2479	u32 i;2480	u32 expected_len = sizeof(*data);2481 2482	if (!data) {2483		IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n");2484		status = NULL;2485		return;2486	}2487 2488	if (has_mlo_keys)2489		expected_len += (data->num_mlo_link_keys *2490				 sizeof(status->mlo_keys[0]));2491 2492	if (len < expected_len) {2493		IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");2494		status = NULL;2495		return;2496	}2497 2498	if (mvm->fast_resume)2499		return;2500 2501	iwl_mvm_convert_key_counters_v5(status, &data->gtk[0].sc);2502	iwl_mvm_convert_gtk_v3(status, data->gtk);2503	iwl_mvm_convert_igtk(status, &data->igtk[0]);2504	iwl_mvm_convert_bigtk(status, data->bigtk);2505	status->replay_ctr = le64_to_cpu(data->replay_ctr);2506	status->pattern_number = le16_to_cpu(data->pattern_number);2507	for (i = 0; i < IWL_MAX_TID_COUNT; i++)2508		status->qos_seq_ctr[i] =2509			le16_to_cpu(data->qos_seq_ctr[i]);2510	status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons);2511	status->num_of_gtk_rekeys =2512		le32_to_cpu(data->num_of_gtk_rekeys);2513	status->received_beacons = le32_to_cpu(data->received_beacons);2514	status->tid_tear_down = data->tid_tear_down;2515 2516	if (has_mlo_keys && data->num_mlo_link_keys) {2517		status->num_mlo_keys = data->num_mlo_link_keys;2518		if (IWL_FW_CHECK(mvm,2519				 status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,2520				 "Too many mlo keys: %d, max %d\n",2521				 status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))2522			status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;2523		memcpy(status->mlo_keys, data->mlo_gtks,2524		       status->num_mlo_keys * sizeof(status->mlo_keys[0]));2525	}2526}2527 2528static void2529iwl_mvm_parse_wowlan_info_notif_v2(struct iwl_mvm *mvm,2530				   struct iwl_wowlan_info_notif_v2 *data,2531				   struct iwl_wowlan_status_data *status,2532				   u32 len)2533{2534	u32 i;2535 2536	if (!data) {2537		IWL_ERR(mvm, "iwl_wowlan_info_notif data is NULL\n");2538		status = NULL;2539		return;2540	}2541 2542	if (len < sizeof(*data)) {2543		IWL_ERR(mvm, "Invalid WoWLAN info notification!\n");2544		status = NULL;2545		return;2546	}2547 2548	iwl_mvm_convert_key_counters_v5(status, &data->gtk[0].sc);2549	iwl_mvm_convert_gtk_v3(status, data->gtk);2550	iwl_mvm_convert_igtk(status, &data->igtk[0]);2551	status->replay_ctr = le64_to_cpu(data->replay_ctr);2552	status->pattern_number = le16_to_cpu(data->pattern_number);2553	for (i = 0; i < IWL_MAX_TID_COUNT; i++)2554		status->qos_seq_ctr[i] =2555			le16_to_cpu(data->qos_seq_ctr[i]);2556	status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons);2557	status->num_of_gtk_rekeys =2558		le32_to_cpu(data->num_of_gtk_rekeys);2559	status->received_beacons = le32_to_cpu(data->received_beacons);2560	status->tid_tear_down = data->tid_tear_down;2561}2562 2563/* Occasionally, templates would be nice. This is one of those times ... */2564#define iwl_mvm_parse_wowlan_status_common(_ver)			\2565static struct iwl_wowlan_status_data *					\2566iwl_mvm_parse_wowlan_status_common_ ## _ver(struct iwl_mvm *mvm,	\2567					    struct iwl_wowlan_status_ ##_ver *data,\2568					    int len)			\2569{									\2570	struct iwl_wowlan_status_data *status;				\2571	int data_size, i;						\2572									\2573	if (len < sizeof(*data)) {					\2574		IWL_ERR(mvm, "Invalid WoWLAN status response!\n");	\2575		return NULL;						\2576	}								\2577									\2578	data_size = ALIGN(le32_to_cpu(data->wake_packet_bufsize), 4);	\2579	if (len != sizeof(*data) + data_size) {				\2580		IWL_ERR(mvm, "Invalid WoWLAN status response!\n");	\2581		return NULL;						\2582	}								\2583									\2584	status = kzalloc(sizeof(*status), GFP_KERNEL);			\2585	if (!status)							\2586		return NULL;						\2587									\2588	/* copy all the common fields */				\2589	status->replay_ctr = le64_to_cpu(data->replay_ctr);		\2590	status->pattern_number = le16_to_cpu(data->pattern_number);	\2591	status->non_qos_seq_ctr = le16_to_cpu(data->non_qos_seq_ctr);	\2592	for (i = 0; i < 8; i++)						\2593		status->qos_seq_ctr[i] =				\2594			le16_to_cpu(data->qos_seq_ctr[i]);		\2595	status->wakeup_reasons = le32_to_cpu(data->wakeup_reasons);	\2596	status->num_of_gtk_rekeys =					\2597		le32_to_cpu(data->num_of_gtk_rekeys);			\2598	status->received_beacons = le32_to_cpu(data->received_beacons);	\2599	status->wake_packet_length =					\2600		le32_to_cpu(data->wake_packet_length);			\2601	status->wake_packet_bufsize =					\2602		le32_to_cpu(data->wake_packet_bufsize);			\2603	if (status->wake_packet_bufsize) {				\2604		status->wake_packet =					\2605			kmemdup(data->wake_packet,			\2606				status->wake_packet_bufsize,		\2607				GFP_KERNEL);				\2608		if (!status->wake_packet) {				\2609			kfree(status);					\2610			return NULL;					\2611		}							\2612	} else {							\2613		status->wake_packet = NULL;				\2614	}								\2615									\2616	return status;							\2617}2618 2619iwl_mvm_parse_wowlan_status_common(v6)2620iwl_mvm_parse_wowlan_status_common(v7)2621iwl_mvm_parse_wowlan_status_common(v9)2622iwl_mvm_parse_wowlan_status_common(v12)2623 2624static struct iwl_wowlan_status_data *2625iwl_mvm_send_wowlan_get_status(struct iwl_mvm *mvm, u8 sta_id)2626{2627	struct iwl_wowlan_status_data *status;2628	struct iwl_wowlan_get_status_cmd get_status_cmd = {2629		.sta_id = cpu_to_le32(sta_id),2630	};2631	struct iwl_host_cmd cmd = {2632		.id = WOWLAN_GET_STATUSES,2633		.flags = CMD_WANT_SKB,2634		.data = { &get_status_cmd, },2635		.len = { sizeof(get_status_cmd), },2636	};2637	int ret, len;2638	u8 notif_ver;2639	u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd.id,2640					   IWL_FW_CMD_VER_UNKNOWN);2641 2642	if (cmd_ver == IWL_FW_CMD_VER_UNKNOWN)2643		cmd.len[0] = 0;2644 2645	lockdep_assert_held(&mvm->mutex);2646 2647	ret = iwl_mvm_send_cmd(mvm, &cmd);2648	if (ret) {2649		IWL_ERR(mvm, "failed to query wakeup status (%d)\n", ret);2650		return ERR_PTR(ret);2651	}2652 2653	len = iwl_rx_packet_payload_len(cmd.resp_pkt);2654 2655	/* default to 7 (when we have IWL_UCODE_TLV_API_WOWLAN_KEY_MATERIAL) */2656	notif_ver = iwl_mvm_lookup_wowlan_status_ver(mvm);2657 2658	if (notif_ver < 7) {2659		struct iwl_wowlan_status_v6 *v6 = (void *)cmd.resp_pkt->data;2660 2661		status = iwl_mvm_parse_wowlan_status_common_v6(mvm, v6, len);2662		if (!status)2663			goto out_free_resp;2664 2665		BUILD_BUG_ON(sizeof(v6->gtk.decrypt_key) >2666			     sizeof(status->gtk[0].key));2667		BUILD_BUG_ON(NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY +2668			     sizeof(v6->gtk.tkip_mic_key) >2669			     sizeof(status->gtk[0].key));2670 2671		/* copy GTK info to the right place */2672		memcpy(status->gtk[0].key, v6->gtk.decrypt_key,2673		       sizeof(v6->gtk.decrypt_key));2674		memcpy(status->gtk[0].key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,2675		       v6->gtk.tkip_mic_key,2676		       sizeof(v6->gtk.tkip_mic_key));2677 2678		iwl_mvm_convert_key_counters(status, &v6->gtk.rsc.all_tsc_rsc);2679 2680		/* hardcode the key length to 16 since v6 only supports 16 */2681		status->gtk[0].len = 16;2682 2683		/*2684		 * The key index only uses 2 bits (values 0 to 3) and2685		 * we always set bit 7 which means this is the2686		 * currently used key.2687		 */2688		status->gtk[0].flags = v6->gtk.key_index | BIT(7);2689	} else if (notif_ver == 7) {2690		struct iwl_wowlan_status_v7 *v7 = (void *)cmd.resp_pkt->data;2691 2692		status = iwl_mvm_parse_wowlan_status_common_v7(mvm, v7, len);2693		if (!status)2694			goto out_free_resp;2695 2696		iwl_mvm_convert_key_counters(status, &v7->gtk[0].rsc.all_tsc_rsc);2697		iwl_mvm_convert_gtk_v2(status, &v7->gtk[0]);2698		iwl_mvm_convert_igtk(status, &v7->igtk[0]);2699	} else if (notif_ver == 9 || notif_ver == 10 || notif_ver == 11) {2700		struct iwl_wowlan_status_v9 *v9 = (void *)cmd.resp_pkt->data;2701 2702		/* these three command versions have same layout and size, the2703		 * difference is only in a few not used (reserved) fields.2704		 */2705		status = iwl_mvm_parse_wowlan_status_common_v9(mvm, v9, len);2706		if (!status)2707			goto out_free_resp;2708 2709		iwl_mvm_convert_key_counters(status, &v9->gtk[0].rsc.all_tsc_rsc);2710		iwl_mvm_convert_gtk_v2(status, &v9->gtk[0]);2711		iwl_mvm_convert_igtk(status, &v9->igtk[0]);2712 2713		status->tid_tear_down = v9->tid_tear_down;2714	} else if (notif_ver == 12) {2715		struct iwl_wowlan_status_v12 *v12 = (void *)cmd.resp_pkt->data;2716 2717		status = iwl_mvm_parse_wowlan_status_common_v12(mvm, v12, len);2718		if (!status)2719			goto out_free_resp;2720 2721		iwl_mvm_convert_key_counters_v5(status, &v12->gtk[0].sc);2722		iwl_mvm_convert_gtk_v3(status, v12->gtk);2723		iwl_mvm_convert_igtk(status, &v12->igtk[0]);2724 2725		status->tid_tear_down = v12->tid_tear_down;2726	} else {2727		IWL_ERR(mvm,2728			"Firmware advertises unknown WoWLAN status response %d!\n",2729			notif_ver);2730		status = NULL;2731	}2732 2733out_free_resp:2734	iwl_free_resp(&cmd);2735	return status;2736}2737 2738/* releases the MVM mutex */2739static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,2740					 struct ieee80211_vif *vif,2741					 struct iwl_wowlan_status_data *status)2742{2743	int i;2744	bool keep = false;2745	struct iwl_mvm_sta *mvm_ap_sta;2746	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);2747	int link_id = vif->active_links ? __ffs(vif->active_links) : 0;2748	struct iwl_mvm_vif_link_info *mvm_link = mvmvif->link[link_id];2749 2750	if (WARN_ON(!mvm_link))2751		goto out_unlock;2752 2753	if (!status)2754		goto out_unlock;2755 2756	IWL_DEBUG_WOWLAN(mvm, "wakeup reason 0x%x\n",2757			 status->wakeup_reasons);2758 2759	mvm_ap_sta = iwl_mvm_sta_from_staid_protected(mvm, mvm_link->ap_sta_id);2760	if (!mvm_ap_sta)2761		goto out_unlock;2762 2763	for (i = 0; i < IWL_MAX_TID_COUNT; i++) {2764		u16 seq = status->qos_seq_ctr[i];2765		/* firmware stores last-used value, we store next value */2766		seq += 0x10;2767		mvm_ap_sta->tid_data[i].seq_number = seq;2768	}2769 2770	if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_22000) {2771		i = mvm->offload_tid;2772		iwl_trans_set_q_ptrs(mvm->trans,2773				     mvm_ap_sta->tid_data[i].txq_id,2774				     mvm_ap_sta->tid_data[i].seq_number >> 4);2775	}2776 2777	iwl_mvm_report_wakeup_reasons(mvm, vif, status);2778 2779	keep = iwl_mvm_setup_connection_keep(mvm, vif, status);2780out_unlock:2781	mutex_unlock(&mvm->mutex);2782	return keep;2783}2784 2785#define ND_QUERY_BUF_LEN (sizeof(struct iwl_scan_offload_profile_match) * \2786			  IWL_SCAN_MAX_PROFILES)2787 2788struct iwl_mvm_nd_results {2789	u32 matched_profiles;2790	u8 matches[ND_QUERY_BUF_LEN];2791};2792 2793static int2794iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,2795				struct iwl_mvm_nd_results *results)2796{2797	struct iwl_scan_offload_match_info *query;2798	struct iwl_host_cmd cmd = {2799		.id = SCAN_OFFLOAD_PROFILES_QUERY_CMD,2800		.flags = CMD_WANT_SKB,2801	};2802	int ret, len;2803	size_t query_len, matches_len;2804	int max_profiles = iwl_umac_scan_get_max_profiles(mvm->fw);2805 2806	ret = iwl_mvm_send_cmd(mvm, &cmd);2807	if (ret) {2808		IWL_ERR(mvm, "failed to query matched profiles (%d)\n", ret);2809		return ret;2810	}2811 2812	if (fw_has_api(&mvm->fw->ucode_capa,2813		       IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {2814		query_len = sizeof(struct iwl_scan_offload_match_info);2815		matches_len = sizeof(struct iwl_scan_offload_profile_match) *2816			max_profiles;2817	} else {2818		query_len = sizeof(struct iwl_scan_offload_profiles_query_v1);2819		matches_len = sizeof(struct iwl_scan_offload_profile_match_v1) *2820			max_profiles;2821	}2822 2823	len = iwl_rx_packet_payload_len(cmd.resp_pkt);2824	if (len < query_len) {2825		IWL_ERR(mvm, "Invalid scan offload profiles query response!\n");2826		ret = -EIO;2827		goto out_free_resp;2828	}2829 2830	query = (void *)cmd.resp_pkt->data;2831 2832	results->matched_profiles = le32_to_cpu(query->matched_profiles);2833	memcpy(results->matches, query->matches, matches_len);2834 2835#ifdef CONFIG_IWLWIFI_DEBUGFS2836	mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);2837#endif2838 2839out_free_resp:2840	iwl_free_resp(&cmd);2841	return ret;2842}2843 2844static int iwl_mvm_query_num_match_chans(struct iwl_mvm *mvm,2845					 struct iwl_mvm_nd_results *results,2846					 int idx)2847{2848	int n_chans = 0, i;2849 2850	if (fw_has_api(&mvm->fw->ucode_capa,2851		       IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {2852		struct iwl_scan_offload_profile_match *matches =2853			(void *)results->matches;2854 2855		for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; i++)2856			n_chans += hweight8(matches[idx].matching_channels[i]);2857	} else {2858		struct iwl_scan_offload_profile_match_v1 *matches =2859			(void *)results->matches;2860 2861		for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1; i++)2862			n_chans += hweight8(matches[idx].matching_channels[i]);2863	}2864 2865	return n_chans;2866}2867 2868static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,2869				    struct iwl_mvm_nd_results *results,2870				    struct cfg80211_wowlan_nd_match *match,2871				    int idx)2872{2873	int i;2874 2875	if (fw_has_api(&mvm->fw->ucode_capa,2876		       IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {2877		struct iwl_scan_offload_profile_match *matches =2878			 (void *)results->matches;2879 2880		for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++)2881			if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))2882				match->channels[match->n_channels++] =2883					mvm->nd_channels[i]->center_freq;2884	} else {2885		struct iwl_scan_offload_profile_match_v1 *matches =2886			 (void *)results->matches;2887 2888		for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++)2889			if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))2890				match->channels[match->n_channels++] =2891					mvm->nd_channels[i]->center_freq;2892	}2893}2894 2895/**2896 * enum iwl_d3_notif - d3 notifications2897 * @IWL_D3_NOTIF_WOWLAN_INFO: WOWLAN_INFO_NOTIF was received2898 * @IWL_D3_NOTIF_WOWLAN_WAKE_PKT: WOWLAN_WAKE_PKT_NOTIF was received2899 * @IWL_D3_NOTIF_PROT_OFFLOAD: PROT_OFFLOAD_NOTIF was received2900 * @IWL_D3_ND_MATCH_INFO: OFFLOAD_MATCH_INFO_NOTIF was received2901 * @IWL_D3_NOTIF_D3_END_NOTIF: D3_END_NOTIF was received2902 */2903enum iwl_d3_notif {2904	IWL_D3_NOTIF_WOWLAN_INFO =	BIT(0),2905	IWL_D3_NOTIF_WOWLAN_WAKE_PKT =	BIT(1),2906	IWL_D3_NOTIF_PROT_OFFLOAD =	BIT(2),2907	IWL_D3_ND_MATCH_INFO      =     BIT(3),2908	IWL_D3_NOTIF_D3_END_NOTIF =	BIT(4)2909};2910 2911/* manage d3 resume data */2912struct iwl_d3_data {2913	struct iwl_wowlan_status_data *status;2914	bool test;2915	u32 d3_end_flags;2916	u32 notif_expected;	/* bitmap - see &enum iwl_d3_notif */2917	u32 notif_received;	/* bitmap - see &enum iwl_d3_notif */2918	struct iwl_mvm_nd_results *nd_results;2919	bool nd_results_valid;2920};2921 2922static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,2923					    struct ieee80211_vif *vif,2924					    struct iwl_d3_data *d3_data)2925{2926	struct cfg80211_wowlan_nd_info *net_detect = NULL;2927	struct cfg80211_wowlan_wakeup wakeup = {2928		.pattern_idx = -1,2929	};2930	struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;2931	unsigned long matched_profiles;2932	u32 reasons = 0;2933	int i, n_matches, ret;2934 2935	if (WARN_ON(!d3_data || !d3_data->status))2936		goto out;2937 2938	reasons = d3_data->status->wakeup_reasons;2939 2940	if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)2941		wakeup.rfkill_release = true;2942 2943	if (reasons != IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS)2944		goto out;2945 2946	if (!iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,2947				     WOWLAN_INFO_NOTIFICATION, 0)) {2948		IWL_INFO(mvm, "Query FW for ND results\n");2949		ret = iwl_mvm_netdetect_query_results(mvm, d3_data->nd_results);2950 2951	} else {2952		IWL_INFO(mvm, "Notification based ND results\n");2953		ret = d3_data->nd_results_valid ? 0 : -1;2954	}2955 2956	if (ret || !d3_data->nd_results->matched_profiles) {2957		wakeup_report = NULL;2958		goto out;2959	}2960 2961	matched_profiles = d3_data->nd_results->matched_profiles;2962	if (mvm->n_nd_match_sets) {2963		n_matches = hweight_long(matched_profiles);2964	} else {2965		IWL_ERR(mvm, "no net detect match information available\n");2966		n_matches = 0;2967	}2968 2969	net_detect = kzalloc(struct_size(net_detect, matches, n_matches),2970			     GFP_KERNEL);2971	if (!net_detect || !n_matches)2972		goto out_report_nd;2973 2974	for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {2975		struct cfg80211_wowlan_nd_match *match;2976		int idx, n_channels = 0;2977 2978		n_channels = iwl_mvm_query_num_match_chans(mvm,2979							   d3_data->nd_results,2980							   i);2981 2982		match = kzalloc(struct_size(match, channels, n_channels),2983				GFP_KERNEL);2984		if (!match)2985			goto out_report_nd;2986 2987		net_detect->matches[net_detect->n_matches++] = match;2988 2989		/* We inverted the order of the SSIDs in the scan2990		 * request, so invert the index here.2991		 */2992		idx = mvm->n_nd_match_sets - i - 1;2993		match->ssid.ssid_len = mvm->nd_match_sets[idx].ssid.ssid_len;2994		memcpy(match->ssid.ssid, mvm->nd_match_sets[idx].ssid.ssid,2995		       match->ssid.ssid_len);2996 2997		if (mvm->n_nd_channels < n_channels)2998			continue;2999 3000		iwl_mvm_query_set_freqs(mvm, d3_data->nd_results, match, i);3001	}3002 3003out_report_nd:3004	wakeup.net_detect = net_detect;3005out:3006	iwl_mvm_free_nd(mvm);3007 3008	mutex_unlock(&mvm->mutex);3009	ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);3010 3011	if (net_detect) {3012		for (i = 0; i < net_detect->n_matches; i++)3013			kfree(net_detect->matches[i]);3014		kfree(net_detect);3015	}3016}3017 3018static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,3019				       struct ieee80211_vif *vif)3020{3021	/* skip the one we keep connection on */3022	if (data == vif)3023		return;3024 3025	if (vif->type == NL80211_IFTYPE_STATION)3026		ieee80211_resume_disconnect(vif);3027}3028 3029static bool iwl_mvm_rt_status(struct iwl_trans *trans, u32 base, u32 *err_id)3030{3031	struct error_table_start {3032		/* cf. struct iwl_error_event_table */3033		u32 valid;3034		__le32 err_id;3035	} err_info;3036 3037	if (!base)3038		return false;3039 3040	iwl_trans_read_mem_bytes(trans, base,3041				 &err_info, sizeof(err_info));3042	if (err_info.valid && err_id)3043		*err_id = le32_to_cpu(err_info.err_id);3044 3045	return !!err_info.valid;3046}3047 3048static bool iwl_mvm_check_rt_status(struct iwl_mvm *mvm,3049				   struct ieee80211_vif *vif)3050{3051	u32 err_id;3052 3053	/* check for lmac1 error */3054	if (iwl_mvm_rt_status(mvm->trans,3055			      mvm->trans->dbg.lmac_error_event_table[0],3056			      &err_id)) {3057		if (err_id == RF_KILL_INDICATOR_FOR_WOWLAN && vif) {3058			struct cfg80211_wowlan_wakeup wakeup = {3059				.rfkill_release = true,3060			};3061			ieee80211_report_wowlan_wakeup(vif, &wakeup,3062						       GFP_KERNEL);3063		}3064		return true;3065	}3066 3067	/* check if we have lmac2 set and check for error */3068	if (iwl_mvm_rt_status(mvm->trans,3069			      mvm->trans->dbg.lmac_error_event_table[1], NULL))3070		return true;3071 3072	/* check for umac error */3073	if (iwl_mvm_rt_status(mvm->trans,3074			      mvm->trans->dbg.umac_error_event_table, NULL))3075		return true;3076 3077	return false;3078}3079 3080/*3081 * This function assumes:3082 *	1. The mutex is already held.3083 *	2. The callee functions unlock the mutex.3084 */3085static bool3086iwl_mvm_choose_query_wakeup_reasons(struct iwl_mvm *mvm,3087				    struct ieee80211_vif *vif,3088				    struct iwl_d3_data *d3_data)3089{3090	lockdep_assert_held(&mvm->mutex);3091 3092	/* if FW uses status notification, status shouldn't be NULL here */3093	if (!d3_data->status) {3094		struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);3095		u8 sta_id = mvm->net_detect ? IWL_MVM_INVALID_STA :3096					      mvmvif->deflink.ap_sta_id;3097 3098		/* bug - FW with MLO has status notification */3099		WARN_ON(ieee80211_vif_is_mld(vif));3100 3101		d3_data->status = iwl_mvm_send_wowlan_get_status(mvm, sta_id);3102	}3103 3104	if (mvm->net_detect) {3105		iwl_mvm_query_netdetect_reasons(mvm, vif, d3_data);3106	} else {3107		bool keep = iwl_mvm_query_wakeup_reasons(mvm, vif,3108							 d3_data->status);3109 3110#ifdef CONFIG_IWLWIFI_DEBUGFS3111		if (keep)3112			mvm->keep_vif = vif;3113#endif3114 3115		return keep;3116	}3117	return false;3118}3119 3120#define IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT (IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET | \3121						 IWL_WOWLAN_WAKEUP_BY_PATTERN | \3122						 IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN |\3123						 IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN_WILDCARD |\3124						 IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN |\3125						 IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN_WILDCARD)3126 3127static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm,3128					 struct iwl_wowlan_wake_pkt_notif *notif,3129					 struct iwl_wowlan_status_data *status,3130					 u32 len)3131{3132	u32 data_size, packet_len = le32_to_cpu(notif->wake_packet_length);3133 3134	if (len < sizeof(*notif)) {3135		IWL_ERR(mvm, "Invalid WoWLAN wake packet notification!\n");3136		return -EIO;3137	}3138 3139	if (WARN_ON(!status)) {3140		IWL_ERR(mvm, "Got wake packet notification but wowlan status data is NULL\n");3141		return -EIO;3142	}3143 3144	if (WARN_ON(!(status->wakeup_reasons &3145		      IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT))) {3146		IWL_ERR(mvm, "Got wakeup packet but wakeup reason is %x\n",3147			status->wakeup_reasons);3148		return -EIO;3149	}3150 3151	data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif, wake_packet);3152 3153	/* data_size got the padding from the notification, remove it. */3154	if (packet_len < data_size)3155		data_size = packet_len;3156 3157	status->wake_packet = kmemdup(notif->wake_packet, data_size,3158				      GFP_ATOMIC);3159 3160	if (!status->wake_packet)3161		return -ENOMEM;3162 3163	status->wake_packet_length = packet_len;3164	status->wake_packet_bufsize = data_size;3165 3166	return 0;3167}3168 3169static void iwl_mvm_nd_match_info_handler(struct iwl_mvm *mvm,3170					  struct iwl_d3_data *d3_data,3171					  struct iwl_scan_offload_match_info *notif,3172					  u32 len)3173{3174	struct iwl_wowlan_status_data *status = d3_data->status;3175	struct ieee80211_vif *vif = iwl_mvm_get_bss_vif(mvm);3176	struct iwl_mvm_nd_results *results = d3_data->nd_results;3177	size_t i, matches_len = sizeof(struct iwl_scan_offload_profile_match) *3178		iwl_umac_scan_get_max_profiles(mvm->fw);3179 3180	if (IS_ERR_OR_NULL(vif))3181		return;3182 3183	if (len < sizeof(struct iwl_scan_offload_match_info)) {3184		IWL_ERR(mvm, "Invalid scan match info notification\n");3185		return;3186	}3187 3188	if (!mvm->net_detect) {3189		IWL_ERR(mvm, "Unexpected scan match info notification\n");3190		return;3191	}3192 3193	if (!status || status->wakeup_reasons != IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) {3194		IWL_ERR(mvm,3195			"Ignore scan match info notification: no reason\n");3196		return;3197	}3198 3199#ifdef CONFIG_IWLWIFI_DEBUGFS3200	mvm->last_netdetect_scans = le32_to_cpu(notif->n_scans_done);3201#endif3202 3203	results->matched_profiles = le32_to_cpu(notif->matched_profiles);3204	IWL_INFO(mvm, "number of matched profiles=%u\n",3205		 results->matched_profiles);3206 3207	if (results->matched_profiles) {3208		memcpy(results->matches, notif->matches, matches_len);3209		d3_data->nd_results_valid = true;3210	}3211 3212	/* no scan should be active at this point */3213	mvm->scan_status = 0;3214	for (i = 0; i < mvm->max_scans; i++)3215		mvm->scan_uid_status[i] = 0;3216}3217 3218static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait,3219				  struct iwl_rx_packet *pkt, void *data)3220{3221	struct iwl_mvm *mvm =3222		container_of(notif_wait, struct iwl_mvm, notif_wait);3223	struct iwl_d3_data *d3_data = data;3224	u32 len = iwl_rx_packet_payload_len(pkt);3225	int ret;3226	int wowlan_info_ver = iwl_fw_lookup_notif_ver(mvm->fw,3227						      PROT_OFFLOAD_GROUP,3228						      WOWLAN_INFO_NOTIFICATION,3229						      IWL_FW_CMD_VER_UNKNOWN);3230 3231 3232	switch (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) {3233	case WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_INFO_NOTIFICATION): {3234 3235		if (d3_data->notif_received & IWL_D3_NOTIF_WOWLAN_INFO) {3236			/* We might get two notifications due to dual bss */3237			IWL_DEBUG_WOWLAN(mvm,3238					 "Got additional wowlan info notification\n");3239			break;3240		}3241 3242		if (wowlan_info_ver < 2) {3243			struct iwl_wowlan_info_notif_v1 *notif_v1 =3244				(void *)pkt->data;3245			struct iwl_wowlan_info_notif_v2 *notif_v2;3246 3247			notif_v2 = kmemdup(notif_v1, sizeof(*notif_v2), GFP_ATOMIC);3248 3249			if (!notif_v2)3250				return false;3251 3252			notif_v2->tid_tear_down = notif_v1->tid_tear_down;3253			notif_v2->station_id = notif_v1->station_id;3254			memset_after(notif_v2, 0, station_id);3255			iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,3256							   d3_data->status,3257							   len);3258			kfree(notif_v2);3259 3260		} else if (wowlan_info_ver == 2) {3261			struct iwl_wowlan_info_notif_v2 *notif_v2 =3262				(void *)pkt->data;3263 3264			iwl_mvm_parse_wowlan_info_notif_v2(mvm, notif_v2,3265							   d3_data->status,3266							   len);3267		} else {3268			struct iwl_wowlan_info_notif *notif =3269				(void *)pkt->data;3270 3271			iwl_mvm_parse_wowlan_info_notif(mvm, notif,3272							d3_data->status, len,3273							wowlan_info_ver > 3);3274		}3275 3276		d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_INFO;3277 3278		if (d3_data->status &&3279		    d3_data->status->wakeup_reasons & IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT)3280			/* We are supposed to get also wake packet notif */3281			d3_data->notif_expected |= IWL_D3_NOTIF_WOWLAN_WAKE_PKT;3282 3283		break;3284	}3285	case WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_WAKE_PKT_NOTIFICATION): {3286		struct iwl_wowlan_wake_pkt_notif *notif = (void *)pkt->data;3287 3288		if (d3_data->notif_received & IWL_D3_NOTIF_WOWLAN_WAKE_PKT) {3289			/* We shouldn't get two wake packet notifications */3290			IWL_ERR(mvm,3291				"Got additional wowlan wake packet notification\n");3292		} else {3293			d3_data->notif_received |= IWL_D3_NOTIF_WOWLAN_WAKE_PKT;3294			len =  iwl_rx_packet_payload_len(pkt);3295			ret = iwl_mvm_wowlan_store_wake_pkt(mvm, notif,3296							    d3_data->status,3297							    len);3298			if (ret)3299				IWL_ERR(mvm,3300					"Can't parse WOWLAN_WAKE_PKT_NOTIFICATION\n");3301		}3302 3303		break;3304	}3305	case WIDE_ID(SCAN_GROUP, OFFLOAD_MATCH_INFO_NOTIF): {3306		struct iwl_scan_offload_match_info *notif = (void *)pkt->data;3307 3308		if (d3_data->notif_received & IWL_D3_ND_MATCH_INFO) {3309			IWL_ERR(mvm,3310				"Got additional netdetect match info\n");3311			break;3312		}3313 3314		d3_data->notif_received |= IWL_D3_ND_MATCH_INFO;3315 3316		/* explicitly set this in the 'expected' as well */3317		d3_data->notif_expected |= IWL_D3_ND_MATCH_INFO;3318 3319		len = iwl_rx_packet_payload_len(pkt);3320		iwl_mvm_nd_match_info_handler(mvm, d3_data, notif, len);3321		break;3322	}3323	case WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION): {3324		struct iwl_mvm_d3_end_notif *notif = (void *)pkt->data;3325 3326		d3_data->d3_end_flags = __le32_to_cpu(notif->flags);3327		d3_data->notif_received |= IWL_D3_NOTIF_D3_END_NOTIF;3328 3329		break;3330	}3331	default:3332		WARN_ON(1);3333	}3334 3335	return d3_data->notif_received == d3_data->notif_expected;3336}3337 3338static int iwl_mvm_resume_firmware(struct iwl_mvm *mvm, bool test)3339{3340	int ret;3341	enum iwl_d3_status d3_status;3342	struct iwl_host_cmd cmd = {3343			.id = D0I3_END_CMD,3344			.flags = CMD_WANT_SKB | CMD_SEND_IN_D3,3345		};3346	bool reset = fw_has_capa(&mvm->fw->ucode_capa,3347				 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);3348 3349	ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !reset);3350	if (ret)3351		return ret;3352 3353	if (d3_status != IWL_D3_STATUS_ALIVE) {3354		IWL_INFO(mvm, "Device was reset during suspend\n");3355		return -ENOENT;3356	}3357 3358	/*3359	 * We should trigger resume flow using command only for 22000 family3360	 * AX210 and above don't need the command since they have3361	 * the doorbell interrupt.3362	 */3363	if (mvm->trans->trans_cfg->device_family <= IWL_DEVICE_FAMILY_22000 &&3364	    fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_D0I3_END_FIRST)) {3365		ret = iwl_mvm_send_cmd(mvm, &cmd);3366		if (ret < 0)3367			IWL_ERR(mvm, "Failed to send D0I3_END_CMD first (%d)\n",3368				ret);3369	}3370 3371	return ret;3372}3373 3374#define IWL_MVM_D3_NOTIF_TIMEOUT (HZ / 3)3375 3376static int iwl_mvm_d3_notif_wait(struct iwl_mvm *mvm,3377				 struct iwl_d3_data *d3_data)3378{3379	static const u16 d3_resume_notif[] = {3380		WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_INFO_NOTIFICATION),3381		WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_WAKE_PKT_NOTIFICATION),3382		WIDE_ID(SCAN_GROUP, OFFLOAD_MATCH_INFO_NOTIF),3383		WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION)3384	};3385	static const u16 d3_fast_resume_notif[] = {3386		WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION)3387	};3388	struct iwl_notification_wait wait_d3_notif;3389	int ret;3390 3391	if (mvm->fast_resume)3392		iwl_init_notification_wait(&mvm->notif_wait, &wait_d3_notif,3393					   d3_fast_resume_notif,3394					   ARRAY_SIZE(d3_fast_resume_notif),3395					   iwl_mvm_wait_d3_notif, d3_data);3396	else3397		iwl_init_notification_wait(&mvm->notif_wait, &wait_d3_notif,3398					   d3_resume_notif,3399					   ARRAY_SIZE(d3_resume_notif),3400					   iwl_mvm_wait_d3_notif, d3_data);3401 3402	ret = iwl_mvm_resume_firmware(mvm, d3_data->test);3403	if (ret) {3404		iwl_remove_notification(&mvm->notif_wait, &wait_d3_notif);3405		return ret;3406	}3407 3408	return iwl_wait_notification(&mvm->notif_wait, &wait_d3_notif,3409				     IWL_MVM_D3_NOTIF_TIMEOUT);3410}3411 3412static inline bool iwl_mvm_d3_resume_notif_based(struct iwl_mvm *mvm)3413{3414	return iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,3415				       WOWLAN_INFO_NOTIFICATION, 0) &&3416		iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,3417					WOWLAN_WAKE_PKT_NOTIFICATION, 0) &&3418		iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,3419					D3_END_NOTIFICATION, 0);3420}3421 3422static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)3423{3424	struct ieee80211_vif *vif = NULL;3425	int ret = 1;3426	struct iwl_mvm_nd_results results = {};3427	struct iwl_d3_data d3_data = {3428		.test = test,3429		.notif_expected =3430			IWL_D3_NOTIF_WOWLAN_INFO |3431			IWL_D3_NOTIF_D3_END_NOTIF,3432		.nd_results_valid = false,3433		.nd_results = &results,3434	};3435	bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,3436					 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);3437	bool d0i3_first = fw_has_capa(&mvm->fw->ucode_capa,3438				      IWL_UCODE_TLV_CAPA_D0I3_END_FIRST);3439	bool resume_notif_based = iwl_mvm_d3_resume_notif_based(mvm);3440	bool keep = false;3441 3442	mutex_lock(&mvm->mutex);3443 3444	/* Apparently, the device went away and device_powered_off() was called,3445	 * don't even try to read the rt_status, the device is currently3446	 * inaccessible.3447	 */3448	if (!test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status)) {3449		IWL_INFO(mvm,3450			 "Can't resume, device_powered_off() was called during wowlan\n");3451		goto err;3452	}3453 3454	mvm->last_reset_or_resume_time_jiffies = jiffies;3455 3456	/* get the BSS vif pointer again */3457	vif = iwl_mvm_get_bss_vif(mvm);3458	if (IS_ERR_OR_NULL(vif))3459		goto err;3460 3461	iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);3462 3463	if (iwl_mvm_check_rt_status(mvm, vif)) {3464		set_bit(STATUS_FW_ERROR, &mvm->trans->status);3465		iwl_mvm_dump_nic_error_log(mvm);3466		iwl_dbg_tlv_time_point(&mvm->fwrt,3467				       IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);3468		iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,3469					false, 0);3470		ret = 1;3471		goto err;3472	}3473 3474	if (resume_notif_based) {3475		d3_data.status = kzalloc(sizeof(*d3_data.status), GFP_KERNEL);3476		if (!d3_data.status) {3477			IWL_ERR(mvm, "Failed to allocate wowlan status\n");3478			ret = -ENOMEM;3479			goto err;3480		}3481 3482		ret = iwl_mvm_d3_notif_wait(mvm, &d3_data);3483		if (ret)3484			goto err;3485	} else {3486		ret = iwl_mvm_resume_firmware(mvm, test);3487		if (ret < 0)3488			goto err;3489	}3490 3491	iwl_mvm_unblock_esr(mvm, vif, IWL_MVM_ESR_BLOCKED_WOWLAN);3492 3493	/* after the successful handshake, we're out of D3 */3494	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;3495 3496	/* when reset is required we can't send these following commands */3497	if (d3_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE)3498		goto query_wakeup_reasons;3499 3500	/*3501	 * Query the current location and source from the D3 firmware so we3502	 * can play it back when we re-intiailize the D0 firmware3503	 */3504	iwl_mvm_update_changed_regdom(mvm);3505 3506	/* Re-configure PPAG settings */3507	iwl_mvm_ppag_send_cmd(mvm);3508 3509	if (!unified_image)3510		/*  Re-configure default SAR profile */3511		iwl_mvm_sar_select_profile(mvm, 1, 1);3512 3513	if (mvm->net_detect && unified_image) {3514		/* If this is a non-unified image, we restart the FW,3515		 * so no need to stop the netdetect scan.  If that3516		 * fails, continue and try to get the wake-up reasons,3517		 * but trigger a HW restart by keeping a failure code3518		 * in ret.3519		 */3520		ret = iwl_mvm_scan_stop(mvm, IWL_MVM_SCAN_NETDETECT,3521					false);3522	}3523 3524query_wakeup_reasons:3525	keep = iwl_mvm_choose_query_wakeup_reasons(mvm, vif, &d3_data);3526	/* has unlocked the mutex, so skip that */3527	goto out;3528 3529err:3530	mutex_unlock(&mvm->mutex);3531out:3532	if (d3_data.status)3533		kfree(d3_data.status->wake_packet);3534	kfree(d3_data.status);3535	iwl_mvm_free_nd(mvm);3536 3537	if (!d3_data.test && !mvm->net_detect)3538		ieee80211_iterate_active_interfaces_mtx(mvm->hw,3539							IEEE80211_IFACE_ITER_NORMAL,3540							iwl_mvm_d3_disconnect_iter,3541							keep ? vif : NULL);3542 3543	clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);3544 3545	/* no need to reset the device in unified images, if successful */3546	if (unified_image && !ret) {3547		/* nothing else to do if we already sent D0I3_END_CMD */3548		if (d0i3_first)3549			return 0;3550 3551		if (!iwl_fw_lookup_notif_ver(mvm->fw, PROT_OFFLOAD_GROUP,3552					     D3_END_NOTIFICATION, 0)) {3553			ret = iwl_mvm_send_cmd_pdu(mvm, D0I3_END_CMD, 0, 0, NULL);3554			if (!ret)3555				return 0;3556		} else if (!(d3_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE)) {3557			return 0;3558		}3559	}3560 3561	/*3562	 * Reconfigure the device in one of the following cases:3563	 * 1. We are not using a unified image3564	 * 2. We are using a unified image but had an error while exiting D33565	 */3566	set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status);3567 3568	/* regardless of what happened, we're now out of D3 */3569	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;3570 3571	return 1;3572}3573 3574int iwl_mvm_resume(struct ieee80211_hw *hw)3575{3576	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);3577	int ret;3578 3579	ret = __iwl_mvm_resume(mvm, false);3580 3581	iwl_mvm_resume_tcm(mvm);3582 3583	iwl_fw_runtime_resume(&mvm->fwrt);3584 3585	return ret;3586}3587 3588void iwl_mvm_set_wakeup(struct ieee80211_hw *hw, bool enabled)3589{3590	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);3591 3592	device_set_wakeup_enable(mvm->trans->dev, enabled);3593}3594 3595void iwl_mvm_fast_suspend(struct iwl_mvm *mvm)3596{3597	struct iwl_d3_manager_config d3_cfg_cmd_data = {};3598	int ret;3599 3600	lockdep_assert_held(&mvm->mutex);3601 3602	IWL_DEBUG_WOWLAN(mvm, "Starting fast suspend flow\n");3603 3604	mvm->fast_resume = true;3605	set_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);3606 3607	WARN_ON(iwl_mvm_power_update_device(mvm));3608	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;3609	ret = iwl_mvm_send_cmd_pdu(mvm, D3_CONFIG_CMD, CMD_SEND_IN_D3,3610				   sizeof(d3_cfg_cmd_data), &d3_cfg_cmd_data);3611	if (ret)3612		IWL_ERR(mvm,3613			"fast suspend: couldn't send D3_CONFIG_CMD %d\n", ret);3614 3615	WARN_ON(iwl_mvm_power_update_mac(mvm));3616 3617	ret = iwl_trans_d3_suspend(mvm->trans, false, false);3618	if (ret)3619		IWL_ERR(mvm, "fast suspend: trans_d3_suspend failed %d\n", ret);3620}3621 3622int iwl_mvm_fast_resume(struct iwl_mvm *mvm)3623{3624	struct iwl_d3_data d3_data = {3625		.notif_expected =3626			IWL_D3_NOTIF_D3_END_NOTIF,3627	};3628	int ret;3629 3630	lockdep_assert_held(&mvm->mutex);3631 3632	IWL_DEBUG_WOWLAN(mvm, "Starting the fast resume flow\n");3633 3634	mvm->last_reset_or_resume_time_jiffies = jiffies;3635	iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);3636 3637	if (iwl_mvm_check_rt_status(mvm, NULL)) {3638		set_bit(STATUS_FW_ERROR, &mvm->trans->status);3639		iwl_mvm_dump_nic_error_log(mvm);3640		iwl_dbg_tlv_time_point(&mvm->fwrt,3641				       IWL_FW_INI_TIME_POINT_FW_ASSERT, NULL);3642		iwl_fw_dbg_collect_desc(&mvm->fwrt, &iwl_dump_desc_assert,3643					false, 0);3644		return -ENODEV;3645	}3646	ret = iwl_mvm_d3_notif_wait(mvm, &d3_data);3647	clear_bit(IWL_MVM_STATUS_IN_D3, &mvm->status);3648	mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;3649	mvm->fast_resume = false;3650 3651	if (ret)3652		IWL_ERR(mvm, "Couldn't get the d3 notif %d\n", ret);3653 3654	return ret;3655}3656 3657#ifdef CONFIG_IWLWIFI_DEBUGFS3658static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)3659{3660	struct iwl_mvm *mvm = inode->i_private;3661	int err;3662 3663	if (mvm->d3_test_active)3664		return -EBUSY;3665 3666	file->private_data = inode->i_private;3667 3668	iwl_mvm_pause_tcm(mvm, true);3669 3670	iwl_fw_runtime_suspend(&mvm->fwrt);3671 3672	/* start pseudo D3 */3673	rtnl_lock();3674	wiphy_lock(mvm->hw->wiphy);3675	err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true);3676	wiphy_unlock(mvm->hw->wiphy);3677	rtnl_unlock();3678	if (err > 0)3679		err = -EINVAL;3680	if (err)3681		return err;3682 3683	mvm->d3_test_active = true;3684	mvm->keep_vif = NULL;3685	return 0;3686}3687 3688static ssize_t iwl_mvm_d3_test_read(struct file *file, char __user *user_buf,3689				    size_t count, loff_t *ppos)3690{3691	struct iwl_mvm *mvm = file->private_data;3692	unsigned long end = jiffies + 60 * HZ;3693	u32 pme_asserted;3694 3695	while (true) {3696		/* read pme_ptr if available */3697		if (mvm->d3_test_pme_ptr) {3698			pme_asserted = iwl_trans_read_mem32(mvm->trans,3699						mvm->d3_test_pme_ptr);3700			if (pme_asserted)3701				break;3702		}3703 3704		if (msleep_interruptible(100))3705			break;3706 3707		if (time_is_before_jiffies(end)) {3708			IWL_ERR(mvm,3709				"ending pseudo-D3 with timeout after ~60 seconds\n");3710			return -ETIMEDOUT;3711		}3712	}3713 3714	return 0;3715}3716 3717static void iwl_mvm_d3_test_disconn_work_iter(void *_data, u8 *mac,3718					      struct ieee80211_vif *vif)3719{3720	/* skip the one we keep connection on */3721	if (_data == vif)3722		return;3723 3724	if (vif->type == NL80211_IFTYPE_STATION)3725		ieee80211_connection_loss(vif);3726}3727 3728static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)3729{3730	struct iwl_mvm *mvm = inode->i_private;3731	bool unified_image = fw_has_capa(&mvm->fw->ucode_capa,3732					 IWL_UCODE_TLV_CAPA_CNSLDTD_D3_D0_IMG);3733 3734	mvm->d3_test_active = false;3735 3736	iwl_fw_dbg_read_d3_debug_data(&mvm->fwrt);3737 3738	rtnl_lock();3739	wiphy_lock(mvm->hw->wiphy);3740	__iwl_mvm_resume(mvm, true);3741	wiphy_unlock(mvm->hw->wiphy);3742	rtnl_unlock();3743 3744	iwl_mvm_resume_tcm(mvm);3745 3746	iwl_fw_runtime_resume(&mvm->fwrt);3747 3748	iwl_abort_notification_waits(&mvm->notif_wait);3749	if (!unified_image) {3750		int remaining_time = 10;3751 3752		ieee80211_restart_hw(mvm->hw);3753 3754		/* wait for restart and disconnect all interfaces */3755		while (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&3756		       remaining_time > 0) {3757			remaining_time--;3758			msleep(1000);3759		}3760 3761		if (remaining_time == 0)3762			IWL_ERR(mvm, "Timed out waiting for HW restart!\n");3763	}3764 3765	ieee80211_iterate_active_interfaces_atomic(3766		mvm->hw, IEEE80211_IFACE_ITER_NORMAL,3767		iwl_mvm_d3_test_disconn_work_iter, mvm->keep_vif);3768 3769	return 0;3770}3771 3772const struct file_operations iwl_dbgfs_d3_test_ops = {3773	.open = iwl_mvm_d3_test_open,3774	.read = iwl_mvm_d3_test_read,3775	.release = iwl_mvm_d3_test_release,3776};3777#endif3778