File Index
Files and directories
Sign in
FILE

d3.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/mld/d3.c C
   1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
   2/*
   3 * Copyright (C) 2024-2025 Intel Corporation
   4 */
   5#include "mld.h"
   6
   7#include "d3.h"
   8#include "power.h"
   9#include "hcmd.h"
  10#include "iface.h"
  11#include "mcc.h"
  12#include "sta.h"
  13#include "mlo.h"
  14#include "key.h"
  15
  16#include "fw/api/d3.h"
  17#include "fw/api/offload.h"
  18#include "fw/api/sta.h"
  19#include "fw/dbg.h"
  20
  21#include <net/ipv6.h>
  22#include <net/addrconf.h>
  23#include <linux/bitops.h>
  24
  25/**
  26 * enum iwl_mld_d3_notif - d3 notifications
  27 * @IWL_D3_NOTIF_WOWLAN_INFO: WOWLAN_INFO_NOTIF is expected/was received
  28 * @IWL_D3_NOTIF_WOWLAN_WAKE_PKT: WOWLAN_WAKE_PKT_NOTIF is expected/was received
  29 * @IWL_D3_NOTIF_PROT_OFFLOAD: PROT_OFFLOAD_NOTIF is expected/was received
  30 * @IWL_D3_ND_MATCH_INFO: OFFLOAD_MATCH_INFO_NOTIF is expected/was received
  31 * @IWL_D3_NOTIF_D3_END_NOTIF: D3_END_NOTIF is expected/was received
  32 */
  33enum iwl_mld_d3_notif {
  34	IWL_D3_NOTIF_WOWLAN_INFO =	BIT(0),
  35	IWL_D3_NOTIF_WOWLAN_WAKE_PKT =	BIT(1),
  36	IWL_D3_NOTIF_PROT_OFFLOAD =	BIT(2),
  37	IWL_D3_ND_MATCH_INFO      =     BIT(3),
  38	IWL_D3_NOTIF_D3_END_NOTIF =	BIT(4)
  39};
  40
  41struct iwl_mld_resume_key_iter_data {
  42	struct iwl_mld *mld;
  43	struct iwl_mld_wowlan_status *wowlan_status;
  44};
  45
  46struct iwl_mld_suspend_key_iter_data {
  47	struct iwl_wowlan_rsc_tsc_params_cmd *rsc;
  48	bool have_rsc;
  49	int gtks;
  50	int found_gtk_idx[4];
  51	__le32 gtk_cipher;
  52	__le32 igtk_cipher;
  53	__le32 bigtk_cipher;
  54};
  55
  56struct iwl_mld_mcast_key_data {
  57	u8 key[WOWLAN_KEY_MAX_SIZE];
  58	u8 len;
  59	u8 flags;
  60	u8 id;
  61	union {
  62		struct {
  63			struct ieee80211_key_seq aes_seq[IWL_MAX_TID_COUNT];
  64			struct ieee80211_key_seq tkip_seq[IWL_MAX_TID_COUNT];
  65		} gtk;
  66		struct {
  67			struct ieee80211_key_seq cmac_gmac_seq;
  68		} igtk_bigtk;
  69	};
  70
  71};
  72
  73struct iwl_mld_wowlan_mlo_key {
  74	u8 key[WOWLAN_KEY_MAX_SIZE];
  75	u8 idx, type, link_id;
  76	u8 pn[6];
  77};
  78
  79/**
  80 * struct iwl_mld_wowlan_status - contains wowlan status data from
  81 * all wowlan notifications
  82 * @wakeup_reasons: wakeup reasons, see &enum iwl_wowlan_wakeup_reason
  83 * @replay_ctr: GTK rekey replay counter
  84 * @pattern_number: number of the matched patterns on packets
  85 * @last_qos_seq: QoS sequence counter of offloaded tid
  86 * @num_of_gtk_rekeys: number of GTK rekeys during D3
  87 * @tid_offloaded_tx: tid used by the firmware to transmit data packets
  88 *	while in wowlan
  89 * @wake_packet: wakeup packet received
  90 * @wake_packet_length: wake packet length
  91 * @wake_packet_bufsize: wake packet bufsize
  92 * @gtk: data of the last two used gtk's by the FW upon resume
  93 * @igtk: data of the last used igtk by the FW upon resume
  94 * @bigtk: data of the last two used gtk's by the FW upon resume
  95 * @ptk: last seq numbers per tid passed by the FW,
  96 *	holds both in tkip and aes formats
  97 * @num_mlo_keys: number of &struct iwl_mld_wowlan_mlo_key structs
  98 * @mlo_keys: array of MLO keys
  99 */
 100struct iwl_mld_wowlan_status {
 101	u32 wakeup_reasons;
 102	u64 replay_ctr;
 103	u16 pattern_number;
 104	u16 last_qos_seq;
 105	u32 num_of_gtk_rekeys;
 106	u8 tid_offloaded_tx;
 107	u8 *wake_packet;
 108	u32 wake_packet_length;
 109	u32 wake_packet_bufsize;
 110	struct iwl_mld_mcast_key_data gtk[WOWLAN_GTK_KEYS_NUM];
 111	struct iwl_mld_mcast_key_data igtk;
 112	struct iwl_mld_mcast_key_data bigtk[WOWLAN_BIGTK_KEYS_NUM];
 113	struct {
 114		struct ieee80211_key_seq aes_seq[IWL_MAX_TID_COUNT];
 115		struct ieee80211_key_seq tkip_seq[IWL_MAX_TID_COUNT];
 116
 117	} ptk;
 118
 119	int num_mlo_keys;
 120	struct iwl_mld_wowlan_mlo_key mlo_keys[WOWLAN_MAX_MLO_KEYS];
 121};
 122
 123#define NETDETECT_QUERY_BUF_LEN \
 124	(sizeof(struct iwl_scan_offload_profile_match) * \
 125	 IWL_SCAN_MAX_PROFILES_V2)
 126
 127/**
 128 * struct iwl_mld_netdetect_res - contains netdetect results from
 129 * match_info_notif
 130 * @matched_profiles: bitmap of matched profiles, referencing the
 131 *	matches passed in the scan offload request
 132 * @matches: array of match information, one for each match
 133 */
 134struct iwl_mld_netdetect_res {
 135	u32 matched_profiles;
 136	u8 matches[NETDETECT_QUERY_BUF_LEN];
 137};
 138
 139/**
 140 * struct iwl_mld_resume_data - d3 resume flow data
 141 * @notifs_expected: bitmap of expected notifications from fw,
 142 *	see &enum iwl_mld_d3_notif
 143 * @notifs_received: bitmap of received notifications from fw,
 144 *	see &enum iwl_mld_d3_notif
 145 * @d3_end_flags: bitmap of flags from d3_end_notif
 146 * @notif_handling_err: error handling one of the resume notifications
 147 * @wowlan_status: wowlan status data from all wowlan notifications
 148 * @netdetect_res: contains netdetect results from match_info_notif
 149 */
 150struct iwl_mld_resume_data {
 151	u32 notifs_expected;
 152	u32 notifs_received;
 153	u32 d3_end_flags;
 154	bool notif_handling_err;
 155	struct iwl_mld_wowlan_status *wowlan_status;
 156	struct iwl_mld_netdetect_res *netdetect_res;
 157};
 158
 159#define IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT \
 160	(IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET | \
 161	IWL_WOWLAN_WAKEUP_BY_PATTERN | \
 162	IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN |\
 163	IWL_WAKEUP_BY_PATTERN_IPV4_TCP_SYN_WILDCARD |\
 164	IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN |\
 165	IWL_WAKEUP_BY_PATTERN_IPV6_TCP_SYN_WILDCARD)
 166
 167#define IWL_WOWLAN_OFFLOAD_TID 0
 168
 169void iwl_mld_set_rekey_data(struct ieee80211_hw *hw,
 170			    struct ieee80211_vif *vif,
 171			    struct cfg80211_gtk_rekey_data *data)
 172{
 173	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
 174	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
 175	struct iwl_mld_wowlan_data *wowlan_data = &mld_vif->wowlan_data;
 176
 177	lockdep_assert_wiphy(mld->wiphy);
 178
 179	wowlan_data->rekey_data.kek_len = data->kek_len;
 180	wowlan_data->rekey_data.kck_len = data->kck_len;
 181	memcpy(wowlan_data->rekey_data.kek, data->kek, data->kek_len);
 182	memcpy(wowlan_data->rekey_data.kck, data->kck, data->kck_len);
 183	wowlan_data->rekey_data.akm = data->akm & 0xFF;
 184	wowlan_data->rekey_data.replay_ctr =
 185		cpu_to_le64(be64_to_cpup((const __be64 *)data->replay_ctr));
 186	wowlan_data->rekey_data.valid = true;
 187}
 188
 189#if IS_ENABLED(CONFIG_IPV6)
 190void iwl_mld_ipv6_addr_change(struct ieee80211_hw *hw,
 191			      struct ieee80211_vif *vif,
 192			      struct inet6_dev *idev)
 193{
 194	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
 195	struct iwl_mld_wowlan_data *wowlan_data = &mld_vif->wowlan_data;
 196	struct inet6_ifaddr *ifa;
 197	int idx = 0;
 198
 199	memset(wowlan_data->tentative_addrs, 0,
 200	       sizeof(wowlan_data->tentative_addrs));
 201
 202	read_lock_bh(&idev->lock);
 203	list_for_each_entry(ifa, &idev->addr_list, if_list) {
 204		wowlan_data->target_ipv6_addrs[idx] = ifa->addr;
 205		if (ifa->flags & IFA_F_TENTATIVE)
 206			__set_bit(idx, wowlan_data->tentative_addrs);
 207		idx++;
 208		if (idx >= IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_MAX)
 209			break;
 210	}
 211	read_unlock_bh(&idev->lock);
 212
 213	wowlan_data->num_target_ipv6_addrs = idx;
 214}
 215#endif
 216
 217static int
 218iwl_mld_netdetect_config(struct iwl_mld *mld,
 219			 struct ieee80211_vif *vif,
 220			 const struct cfg80211_wowlan *wowlan)
 221{
 222	int ret;
 223	struct cfg80211_sched_scan_request *netdetect_cfg =
 224		wowlan->nd_config;
 225	struct ieee80211_scan_ies ies = {};
 226
 227	ret = iwl_mld_scan_stop(mld, IWL_MLD_SCAN_SCHED, true);
 228	if (ret)
 229		return ret;
 230
 231	ret = iwl_mld_sched_scan_start(mld, vif, netdetect_cfg, &ies,
 232				       IWL_MLD_SCAN_NETDETECT);
 233	return ret;
 234}
 235
 236static void
 237iwl_mld_le64_to_tkip_seq(__le64 le_pn, struct ieee80211_key_seq *seq)
 238{
 239	u64 pn = le64_to_cpu(le_pn);
 240
 241	seq->tkip.iv16 = (u16)pn;
 242	seq->tkip.iv32 = (u32)(pn >> 16);
 243}
 244
 245static void
 246iwl_mld_le64_to_aes_seq(__le64 le_pn, struct ieee80211_key_seq *seq)
 247{
 248	u64 pn = le64_to_cpu(le_pn);
 249
 250	seq->ccmp.pn[0] = pn >> 40;
 251	seq->ccmp.pn[1] = pn >> 32;
 252	seq->ccmp.pn[2] = pn >> 24;
 253	seq->ccmp.pn[3] = pn >> 16;
 254	seq->ccmp.pn[4] = pn >> 8;
 255	seq->ccmp.pn[5] = pn;
 256}
 257
 258static void
 259iwl_mld_convert_gtk_resume_seq(struct iwl_mld_mcast_key_data *gtk_data,
 260			       const struct iwl_wowlan_all_rsc_tsc_v5 *sc,
 261			       int rsc_idx)
 262{
 263	struct ieee80211_key_seq *aes_seq = gtk_data->gtk.aes_seq;
 264	struct ieee80211_key_seq *tkip_seq = gtk_data->gtk.tkip_seq;
 265
 266	if (rsc_idx >= ARRAY_SIZE(sc->mcast_rsc))
 267		return;
 268
 269	/* We store both the TKIP and AES representations coming from the
 270	 * FW because we decode the data from there before we iterate
 271	 * the keys and know which type is used.
 272	 */
 273	for (int tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
 274		iwl_mld_le64_to_tkip_seq(sc->mcast_rsc[rsc_idx][tid],
 275					 &tkip_seq[tid]);
 276		iwl_mld_le64_to_aes_seq(sc->mcast_rsc[rsc_idx][tid],
 277					&aes_seq[tid]);
 278	}
 279}
 280
 281static void
 282iwl_mld_convert_gtk_resume_data(struct iwl_mld *mld,
 283				struct iwl_mld_wowlan_status *wowlan_status,
 284				const struct iwl_wowlan_gtk_status *gtk_data,
 285				const struct iwl_wowlan_all_rsc_tsc_v5 *sc)
 286{
 287	int status_idx = 0;
 288
 289	BUILD_BUG_ON(sizeof(wowlan_status->gtk[0].key) <
 290		     sizeof(gtk_data[0].key));
 291	BUILD_BUG_ON(ARRAY_SIZE(wowlan_status->gtk) < WOWLAN_GTK_KEYS_NUM);
 292
 293	for (int notif_idx = 0; notif_idx < ARRAY_SIZE(wowlan_status->gtk);
 294	     notif_idx++) {
 295		int rsc_idx;
 296		u8 key_status = gtk_data[notif_idx].key_status;
 297
 298		if (!key_status)
 299			continue;
 300
 301		wowlan_status->gtk[status_idx].len =
 302			gtk_data[notif_idx].key_len;
 303		wowlan_status->gtk[status_idx].flags =
 304			gtk_data[notif_idx].key_flags;
 305		wowlan_status->gtk[status_idx].id =
 306			wowlan_status->gtk[status_idx].flags &
 307			IWL_WOWLAN_GTK_IDX_MASK;
 308		/* The rsc for both gtk keys are stored in gtk[0]->sc->mcast_rsc
 309		 * The gtk ids can be any two numbers between 0 and 3,
 310		 * the id_map maps between the key id and the index in sc->mcast
 311		 */
 312		rsc_idx =
 313			sc->mcast_key_id_map[wowlan_status->gtk[status_idx].id];
 314		iwl_mld_convert_gtk_resume_seq(&wowlan_status->gtk[status_idx],
 315					       sc, rsc_idx);
 316
 317		if (key_status == IWL_WOWLAN_STATUS_NEW_KEY) {
 318			memcpy(wowlan_status->gtk[status_idx].key,
 319			       gtk_data[notif_idx].key,
 320			       sizeof(gtk_data[notif_idx].key));
 321
 322			/* if it's as long as the TKIP encryption key,
 323			 * copy MIC key
 324			 */
 325			if (wowlan_status->gtk[status_idx].len ==
 326			    NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
 327				memcpy(wowlan_status->gtk[status_idx].key +
 328				       NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY,
 329				       gtk_data[notif_idx].tkip_mic_key,
 330				       sizeof(gtk_data[notif_idx].tkip_mic_key));
 331		} else {
 332			/* If the key status is WOWLAN_STATUS_OLD_KEY, it
 333			 * indicates that no key material is present, Set the
 334			 * key length to 0 as an indication
 335			 */
 336			wowlan_status->gtk[status_idx].len = 0;
 337		}
 338		status_idx++;
 339	}
 340}
 341
 342static void
 343iwl_mld_convert_ptk_resume_seq(struct iwl_mld *mld,
 344			       struct iwl_mld_wowlan_status *wowlan_status,
 345			       const struct iwl_wowlan_all_rsc_tsc_v5 *sc)
 346{
 347	struct ieee80211_key_seq *aes_seq = wowlan_status->ptk.aes_seq;
 348	struct ieee80211_key_seq *tkip_seq = wowlan_status->ptk.tkip_seq;
 349
 350	BUILD_BUG_ON(ARRAY_SIZE(sc->ucast_rsc) != IWL_MAX_TID_COUNT);
 351
 352	for (int tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
 353		iwl_mld_le64_to_aes_seq(sc->ucast_rsc[tid], &aes_seq[tid]);
 354		iwl_mld_le64_to_tkip_seq(sc->ucast_rsc[tid], &tkip_seq[tid]);
 355	}
 356}
 357
 358static void
 359iwl_mld_convert_mcast_ipn(struct iwl_mld_mcast_key_data *key_status,
 360			  const struct iwl_wowlan_igtk_status *key)
 361{
 362	struct ieee80211_key_seq *seq =
 363		&key_status->igtk_bigtk.cmac_gmac_seq;
 364	u8 ipn_len = ARRAY_SIZE(key->ipn);
 365
 366	BUILD_BUG_ON(ipn_len != ARRAY_SIZE(seq->aes_gmac.pn));
 367	BUILD_BUG_ON(ipn_len != ARRAY_SIZE(seq->aes_cmac.pn));
 368	BUILD_BUG_ON(offsetof(struct ieee80211_key_seq, aes_gmac) !=
 369		     offsetof(struct ieee80211_key_seq, aes_cmac));
 370
 371	/* mac80211 expects big endian for memcmp() to work, convert.
 372	 * We don't have the key cipher yet so copy to both to cmac and gmac
 373	 */
 374	for (int i = 0; i < ipn_len; i++) {
 375		seq->aes_gmac.pn[i] = key->ipn[ipn_len - i - 1];
 376		seq->aes_cmac.pn[i] = key->ipn[ipn_len - i - 1];
 377	}
 378}
 379
 380static void
 381iwl_mld_convert_igtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
 382				 const struct iwl_wowlan_igtk_status *igtk)
 383{
 384	if (!igtk->key_status)
 385		return;
 386
 387	BUILD_BUG_ON(sizeof(wowlan_status->igtk.key) < sizeof(igtk->key));
 388
 389	wowlan_status->igtk.len = igtk->key_len;
 390	wowlan_status->igtk.flags = igtk->key_flags;
 391	wowlan_status->igtk.id =
 392		u32_get_bits(igtk->key_flags,
 393			     IWL_WOWLAN_IGTK_BIGTK_IDX_MASK) +
 394		WOWLAN_IGTK_MIN_INDEX;
 395
 396	if (igtk->key_status == IWL_WOWLAN_STATUS_NEW_KEY)
 397		memcpy(wowlan_status->igtk.key, igtk->key, sizeof(igtk->key));
 398	else
 399		/* If the key status is WOWLAN_STATUS_OLD_KEY, it indicates
 400		 * that no key material is present. Set the key length to 0
 401		 * as an indication.
 402		 */
 403		wowlan_status->igtk.len = 0;
 404
 405	iwl_mld_convert_mcast_ipn(&wowlan_status->igtk, igtk);
 406}
 407
 408static void
 409iwl_mld_convert_bigtk_resume_data(struct iwl_mld_wowlan_status *wowlan_status,
 410				  const struct iwl_wowlan_igtk_status *bigtk)
 411{
 412	int status_idx = 0;
 413
 414	BUILD_BUG_ON(ARRAY_SIZE(wowlan_status->bigtk) < WOWLAN_BIGTK_KEYS_NUM);
 415
 416	for (int notif_idx = 0; notif_idx < WOWLAN_BIGTK_KEYS_NUM;
 417	     notif_idx++) {
 418		if (!bigtk[notif_idx].key_status)
 419			continue;
 420
 421		wowlan_status->bigtk[status_idx].len = bigtk[notif_idx].key_len;
 422		wowlan_status->bigtk[status_idx].flags =
 423			bigtk[notif_idx].key_flags;
 424		wowlan_status->bigtk[status_idx].id =
 425			u32_get_bits(bigtk[notif_idx].key_flags,
 426				     IWL_WOWLAN_IGTK_BIGTK_IDX_MASK)
 427			+ WOWLAN_BIGTK_MIN_INDEX;
 428
 429		BUILD_BUG_ON(sizeof(wowlan_status->bigtk[status_idx].key) <
 430			     sizeof(bigtk[notif_idx].key));
 431		if (bigtk[notif_idx].key_status == IWL_WOWLAN_STATUS_NEW_KEY)
 432			memcpy(wowlan_status->bigtk[status_idx].key,
 433			       bigtk[notif_idx].key,
 434			       sizeof(bigtk[notif_idx].key));
 435		else
 436			/* If the key status is WOWLAN_STATUS_OLD_KEY, it
 437			 * indicates that no key material is present. Set the
 438			 * key length to 0 as an indication.
 439			 */
 440			wowlan_status->bigtk[status_idx].len = 0;
 441
 442		iwl_mld_convert_mcast_ipn(&wowlan_status->bigtk[status_idx],
 443					  &bigtk[notif_idx]);
 444		status_idx++;
 445	}
 446}
 447
 448static void
 449iwl_mld_convert_mlo_keys(struct iwl_mld *mld,
 450			 const struct iwl_wowlan_info_notif *notif,
 451			 struct iwl_mld_wowlan_status *wowlan_status)
 452{
 453	if (!notif->num_mlo_link_keys)
 454		return;
 455
 456	wowlan_status->num_mlo_keys = notif->num_mlo_link_keys;
 457
 458	if (IWL_FW_CHECK(mld, wowlan_status->num_mlo_keys > WOWLAN_MAX_MLO_KEYS,
 459			 "Too many MLO keys: %d, max %d\n",
 460			 wowlan_status->num_mlo_keys, WOWLAN_MAX_MLO_KEYS))
 461		wowlan_status->num_mlo_keys = WOWLAN_MAX_MLO_KEYS;
 462
 463	for (int i = 0; i < wowlan_status->num_mlo_keys; i++) {
 464		const struct iwl_wowlan_mlo_gtk *fw_mlo_key = &notif->mlo_gtks[i];
 465		struct iwl_mld_wowlan_mlo_key *driver_mlo_key =
 466			&wowlan_status->mlo_keys[i];
 467		u16 flags = le16_to_cpu(fw_mlo_key->flags);
 468
 469		driver_mlo_key->link_id =
 470			u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_LINK_ID_MSK);
 471		driver_mlo_key->type =
 472			u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_TYPE_MSK);
 473		driver_mlo_key->idx =
 474			u16_get_bits(flags, WOWLAN_MLO_GTK_FLAG_KEY_ID_MSK);
 475
 476		BUILD_BUG_ON(sizeof(driver_mlo_key->key) != sizeof(fw_mlo_key->key));
 477		BUILD_BUG_ON(sizeof(driver_mlo_key->pn) != sizeof(fw_mlo_key->pn));
 478
 479		memcpy(driver_mlo_key->key, fw_mlo_key->key, sizeof(fw_mlo_key->key));
 480		memcpy(driver_mlo_key->pn, fw_mlo_key->pn, sizeof(fw_mlo_key->pn));
 481	}
 482}
 483
 484static void
 485iwl_mld_convert_wowlan_notif_v5(const struct iwl_wowlan_info_notif_v5 *notif_v5,
 486				struct iwl_wowlan_info_notif *notif)
 487{
 488	/* Convert GTK from v3 to the new format */
 489	BUILD_BUG_ON(ARRAY_SIZE(notif->gtk) != ARRAY_SIZE(notif_v5->gtk));
 490
 491	for (int i = 0; i < ARRAY_SIZE(notif_v5->gtk); i++) {
 492		const struct iwl_wowlan_gtk_status_v3 *gtk_v3 = &notif_v5->gtk[i];
 493		struct iwl_wowlan_gtk_status *gtk = &notif->gtk[i];
 494
 495		/* Copy key material and metadata */
 496		BUILD_BUG_ON(sizeof(gtk->key) != sizeof(gtk_v3->key));
 497		BUILD_BUG_ON(sizeof(gtk->tkip_mic_key) != sizeof(gtk_v3->tkip_mic_key));
 498
 499		memcpy(gtk->key, gtk_v3->key, sizeof(gtk_v3->key));
 500
 501		gtk->key_len = gtk_v3->key_len;
 502		gtk->key_flags = gtk_v3->key_flags;
 503
 504		memcpy(gtk->tkip_mic_key, gtk_v3->tkip_mic_key,
 505		       sizeof(gtk_v3->tkip_mic_key));
 506		gtk->sc = gtk_v3->sc;
 507
 508		/* Set key_status based on whether key material is present.
 509		 * in v5, a key is either invalid (should be skipped) or has
 510		 * both meta data and the key itself.
 511		 */
 512		if (gtk_v3->key_len)
 513			gtk->key_status = IWL_WOWLAN_STATUS_NEW_KEY;
 514	}
 515
 516	/* Convert IGTK from v1 to the new format, only one IGTK is passed by FW */
 517	BUILD_BUG_ON(offsetof(struct iwl_wowlan_igtk_status, key_status) !=
 518		     sizeof(struct iwl_wowlan_igtk_status_v1));
 519
 520	memcpy(&notif->igtk[0], &notif_v5->igtk[0],
 521	       offsetof(struct iwl_wowlan_igtk_status, key_status));
 522
 523	/* Set key_status based on whether key material is present.
 524	 * in v5, a key is either invalid (should be skipped) or has
 525	 * both meta data and the key itself.
 526	 */
 527	if (notif_v5->igtk[0].key_len)
 528		notif->igtk[0].key_status = IWL_WOWLAN_STATUS_NEW_KEY;
 529
 530	/* Convert BIGTK from v1 to the new format */
 531	BUILD_BUG_ON(ARRAY_SIZE(notif->bigtk) != ARRAY_SIZE(notif_v5->bigtk));
 532
 533	for (int i = 0; i < ARRAY_SIZE(notif_v5->bigtk); i++) {
 534		/* Copy everything until key_status */
 535		memcpy(&notif->bigtk[i], &notif_v5->bigtk[i],
 536		       offsetof(struct iwl_wowlan_igtk_status, key_status));
 537
 538		/* Set key_status based on whether key material is present.
 539		 * in v5, a key is either invalid (should be skipped) or has
 540		 * both meta data and the key itself.
 541		 */
 542		if (notif_v5->bigtk[i].key_len)
 543			notif->bigtk[i].key_status = IWL_WOWLAN_STATUS_NEW_KEY;
 544	}
 545
 546	notif->replay_ctr = notif_v5->replay_ctr;
 547	notif->pattern_number = notif_v5->pattern_number;
 548	notif->qos_seq_ctr = notif_v5->qos_seq_ctr;
 549	notif->wakeup_reasons = notif_v5->wakeup_reasons;
 550	notif->num_of_gtk_rekeys = notif_v5->num_of_gtk_rekeys;
 551	notif->transmitted_ndps = notif_v5->transmitted_ndps;
 552	notif->received_beacons = notif_v5->received_beacons;
 553	notif->tid_tear_down = notif_v5->tid_tear_down;
 554	notif->station_id = notif_v5->station_id;
 555	notif->num_mlo_link_keys = notif_v5->num_mlo_link_keys;
 556	notif->tid_offloaded_tx = notif_v5->tid_offloaded_tx;
 557
 558	/* Copy MLO GTK keys */
 559	if (notif_v5->num_mlo_link_keys) {
 560		memcpy(notif->mlo_gtks, notif_v5->mlo_gtks,
 561		       notif_v5->num_mlo_link_keys * sizeof(struct iwl_wowlan_mlo_gtk));
 562	}
 563}
 564
 565static bool iwl_mld_validate_wowlan_notif_size(struct iwl_mld *mld,
 566					       u32 len,
 567					       u32 expected_len,
 568					       u8 num_mlo_keys,
 569					       int version)
 570{
 571	u32 len_with_mlo_keys;
 572
 573	if (IWL_FW_CHECK(mld, len < expected_len,
 574			 "Invalid wowlan_info_notif v%d (expected=%u got=%u)\n",
 575			 version, expected_len, len))
 576		return false;
 577
 578	len_with_mlo_keys = expected_len +
 579		(num_mlo_keys * sizeof(struct iwl_wowlan_mlo_gtk));
 580
 581	if (IWL_FW_CHECK(mld, len < len_with_mlo_keys,
 582			 "Invalid wowlan_info_notif v%d with MLO keys (expected=%u got=%u)\n",
 583			 version, len_with_mlo_keys, len))
 584		return false;
 585
 586	return true;
 587}
 588
 589static bool
 590iwl_mld_handle_wowlan_info_notif(struct iwl_mld *mld,
 591				 struct iwl_mld_wowlan_status *wowlan_status,
 592				 struct iwl_rx_packet *pkt)
 593{
 594	const struct iwl_wowlan_info_notif *notif;
 595	struct iwl_wowlan_info_notif *converted_notif __free(kfree) = NULL;
 596	u32 len = iwl_rx_packet_payload_len(pkt);
 597	int wowlan_info_ver = iwl_fw_lookup_notif_ver(mld->fw,
 598						      PROT_OFFLOAD_GROUP,
 599						      WOWLAN_INFO_NOTIFICATION,
 600						      IWL_FW_CMD_VER_UNKNOWN);
 601
 602	if (wowlan_info_ver == 5) {
 603		/* v5 format - validate before conversion */
 604		const struct iwl_wowlan_info_notif_v5 *notif_v5 = (void *)pkt->data;
 605
 606		if (!iwl_mld_validate_wowlan_notif_size(mld, len,
 607							sizeof(*notif_v5),
 608							notif_v5->num_mlo_link_keys,
 609							5))
 610			return true;
 611
 612		converted_notif = kzalloc(struct_size(converted_notif,
 613						      mlo_gtks,
 614						      notif_v5->num_mlo_link_keys),
 615					  GFP_ATOMIC);
 616		if (!converted_notif) {
 617			IWL_ERR(mld,
 618				"Failed to allocate memory for converted wowlan_info_notif\n");
 619			return true;
 620		}
 621
 622		iwl_mld_convert_wowlan_notif_v5(notif_v5,
 623						converted_notif);
 624		notif = converted_notif;
 625	} else if (wowlan_info_ver == 6) {
 626		notif = (void *)pkt->data;
 627		if (!iwl_mld_validate_wowlan_notif_size(mld, len,
 628							sizeof(*notif),
 629							notif->num_mlo_link_keys,
 630							6))
 631			return true;
 632	} else {
 633		/* smaller versions are not supported */
 634		IWL_WARN(mld,
 635			 "Unsupported wowlan_info_notif version %d\n",
 636			 wowlan_info_ver);
 637		return true;
 638	}
 639
 640	if (IWL_FW_CHECK(mld, notif->tid_offloaded_tx != IWL_WOWLAN_OFFLOAD_TID,
 641			 "Invalid tid_offloaded_tx %d\n",
 642			 notif->tid_offloaded_tx))
 643		return true;
 644
 645	iwl_mld_convert_gtk_resume_data(mld, wowlan_status, notif->gtk,
 646					&notif->gtk[0].sc);
 647	iwl_mld_convert_ptk_resume_seq(mld, wowlan_status, &notif->gtk[0].sc);
 648	/* only one igtk is passed by FW */
 649	iwl_mld_convert_igtk_resume_data(wowlan_status, &notif->igtk[0]);
 650	iwl_mld_convert_bigtk_resume_data(wowlan_status, notif->bigtk);
 651
 652	wowlan_status->replay_ctr = le64_to_cpu(notif->replay_ctr);
 653	wowlan_status->pattern_number = le16_to_cpu(notif->pattern_number);
 654
 655	wowlan_status->tid_offloaded_tx = notif->tid_offloaded_tx;
 656	wowlan_status->last_qos_seq = le16_to_cpu(notif->qos_seq_ctr);
 657	wowlan_status->num_of_gtk_rekeys =
 658		le32_to_cpu(notif->num_of_gtk_rekeys);
 659	wowlan_status->wakeup_reasons = le32_to_cpu(notif->wakeup_reasons);
 660
 661	iwl_mld_convert_mlo_keys(mld, notif, wowlan_status);
 662
 663	return false;
 664}
 665
 666static bool
 667iwl_mld_handle_wake_pkt_notif(struct iwl_mld *mld,
 668			      struct iwl_mld_wowlan_status *wowlan_status,
 669			      struct iwl_rx_packet *pkt)
 670{
 671	const struct iwl_wowlan_wake_pkt_notif *notif = (void *)pkt->data;
 672	u32 actual_size, len = iwl_rx_packet_payload_len(pkt);
 673	u32 expected_size = le32_to_cpu(notif->wake_packet_length);
 674
 675	if (IWL_FW_CHECK(mld, len < sizeof(*notif),
 676			 "Invalid WoWLAN wake packet notification (expected size=%zu got=%u)\n",
 677			 sizeof(*notif), len))
 678		return true;
 679
 680	if (IWL_FW_CHECK(mld, !(wowlan_status->wakeup_reasons &
 681				IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT),
 682			 "Got wake packet but wakeup reason is %x\n",
 683			 wowlan_status->wakeup_reasons))
 684		return true;
 685
 686	actual_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif,
 687				     wake_packet);
 688
 689	/* actual_size got the padding from the notification, remove it. */
 690	if (expected_size < actual_size)
 691		actual_size = expected_size;
 692	wowlan_status->wake_packet = kmemdup(notif->wake_packet, actual_size,
 693					     GFP_ATOMIC);
 694	if (!wowlan_status->wake_packet)
 695		return true;
 696
 697	wowlan_status->wake_packet_length = expected_size;
 698	wowlan_status->wake_packet_bufsize = actual_size;
 699
 700	return false;
 701}
 702
 703static void
 704iwl_mld_set_wake_packet(struct iwl_mld *mld,
 705			struct ieee80211_vif *vif,
 706			const struct iwl_mld_wowlan_status *wowlan_status,
 707			struct cfg80211_wowlan_wakeup *wakeup,
 708			struct sk_buff **_pkt)
 709{
 710	int pkt_bufsize = wowlan_status->wake_packet_bufsize;
 711	int expected_pktlen = wowlan_status->wake_packet_length;
 712	const u8 *pktdata = wowlan_status->wake_packet;
 713	const struct ieee80211_hdr *hdr = (const void *)pktdata;
 714	int truncated = expected_pktlen - pkt_bufsize;
 715
 716	if (ieee80211_is_data(hdr->frame_control)) {
 717		int hdrlen = ieee80211_hdrlen(hdr->frame_control);
 718		int ivlen = 0, icvlen = 4; /* also FCS */
 719
 720		struct sk_buff *pkt = alloc_skb(pkt_bufsize, GFP_KERNEL);
 721		*_pkt = pkt;
 722		if (!pkt)
 723			return;
 724
 725		skb_put_data(pkt, pktdata, hdrlen);
 726		pktdata += hdrlen;
 727		pkt_bufsize -= hdrlen;
 728
 729		/* if truncated, FCS/ICV is (partially) gone */
 730		if (truncated >= icvlen) {
 731			truncated -= icvlen;
 732			icvlen = 0;
 733		} else {
 734			icvlen -= truncated;
 735			truncated = 0;
 736		}
 737
 738		pkt_bufsize -= ivlen + icvlen;
 739		pktdata += ivlen;
 740
 741		skb_put_data(pkt, pktdata, pkt_bufsize);
 742
 743		if (ieee80211_data_to_8023(pkt, vif->addr, vif->type))
 744			return;
 745		wakeup->packet = pkt->data;
 746		wakeup->packet_present_len = pkt->len;
 747		wakeup->packet_len = pkt->len - truncated;
 748		wakeup->packet_80211 = false;
 749	} else {
 750		int fcslen = 4;
 751
 752		if (truncated >= 4) {
 753			truncated -= 4;
 754			fcslen = 0;
 755		} else {
 756			fcslen -= truncated;
 757			truncated = 0;
 758		}
 759		pkt_bufsize -= fcslen;
 760		wakeup->packet = wowlan_status->wake_packet;
 761		wakeup->packet_present_len = pkt_bufsize;
 762		wakeup->packet_len = expected_pktlen - truncated;
 763		wakeup->packet_80211 = true;
 764	}
 765}
 766
 767static void
 768iwl_mld_report_wowlan_wakeup(struct iwl_mld *mld,
 769			     struct ieee80211_vif *vif,
 770			     struct iwl_mld_wowlan_status *wowlan_status)
 771{
 772	struct sk_buff *pkt = NULL;
 773	struct cfg80211_wowlan_wakeup wakeup = {
 774		.pattern_idx = -1,
 775	};
 776	u32 reasons = wowlan_status->wakeup_reasons;
 777
 778	if (reasons == IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS) {
 779		ieee80211_report_wowlan_wakeup(vif, NULL, GFP_KERNEL);
 780		return;
 781	}
 782
 783	pm_wakeup_event(mld->dev, 0);
 784
 785	if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET)
 786		wakeup.magic_pkt = true;
 787
 788	if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN)
 789		wakeup.pattern_idx =
 790			wowlan_status->pattern_number;
 791
 792	if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
 793		       IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH |
 794		       IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE))
 795		wakeup.disconnect = true;
 796
 797	if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE)
 798		wakeup.gtk_rekey_failure = true;
 799
 800	if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
 801		wakeup.rfkill_release = true;
 802
 803	if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST)
 804		wakeup.eap_identity_req = true;
 805
 806	if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE)
 807		wakeup.four_way_handshake = true;
 808
 809	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_LINK_LOSS)
 810		wakeup.tcp_connlost = true;
 811
 812	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_SIGNATURE_TABLE)
 813		wakeup.tcp_nomoretokens = true;
 814
 815	if (reasons & IWL_WOWLAN_WAKEUP_BY_REM_WAKE_WAKEUP_PACKET)
 816		wakeup.tcp_match = true;
 817
 818	if (reasons & IWL_WAKEUP_BY_11W_UNPROTECTED_DEAUTH_OR_DISASSOC)
 819		wakeup.unprot_deauth_disassoc = true;
 820
 821	if (wowlan_status->wake_packet)
 822		iwl_mld_set_wake_packet(mld, vif, wowlan_status, &wakeup, &pkt);
 823
 824	ieee80211_report_wowlan_wakeup(vif, &wakeup, GFP_KERNEL);
 825	kfree_skb(pkt);
 826}
 827
 828static void
 829iwl_mld_set_key_rx_seq_tids(struct ieee80211_key_conf *key,
 830			    struct ieee80211_key_seq *seq)
 831{
 832	int tid;
 833
 834	for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
 835		ieee80211_set_key_rx_seq(key, tid, &seq[tid]);
 836}
 837
 838static void
 839iwl_mld_update_mcast_rx_seq(struct ieee80211_key_conf *key,
 840			    struct iwl_mld_mcast_key_data *key_data)
 841{
 842	switch (key->cipher) {
 843	case WLAN_CIPHER_SUITE_CCMP:
 844	case WLAN_CIPHER_SUITE_GCMP:
 845	case WLAN_CIPHER_SUITE_GCMP_256:
 846		iwl_mld_set_key_rx_seq_tids(key,
 847					    key_data->gtk.aes_seq);
 848		break;
 849	case WLAN_CIPHER_SUITE_TKIP:
 850		iwl_mld_set_key_rx_seq_tids(key,
 851					    key_data->gtk.tkip_seq);
 852		break;
 853	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
 854	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
 855	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
 856	case WLAN_CIPHER_SUITE_AES_CMAC:
 857		/* igtk/bigtk ciphers*/
 858		ieee80211_set_key_rx_seq(key, 0,
 859					 &key_data->igtk_bigtk.cmac_gmac_seq);
 860		break;
 861	default:
 862		WARN_ON(1);
 863	}
 864}
 865
 866static void
 867iwl_mld_update_ptk_rx_seq(struct iwl_mld *mld,
 868			  struct iwl_mld_wowlan_status *wowlan_status,
 869			  struct ieee80211_sta *sta,
 870			  struct ieee80211_key_conf *key,
 871			  bool is_tkip)
 872{
 873	struct iwl_mld_sta *mld_sta =
 874		iwl_mld_sta_from_mac80211(sta);
 875	struct iwl_mld_ptk_pn *mld_ptk_pn =
 876		wiphy_dereference(mld->wiphy,
 877				  mld_sta->ptk_pn[key->keyidx]);
 878
 879	iwl_mld_set_key_rx_seq_tids(key, is_tkip ?
 880				    wowlan_status->ptk.tkip_seq :
 881				    wowlan_status->ptk.aes_seq);
 882	if (is_tkip)
 883		return;
 884
 885	if (WARN_ON(!mld_ptk_pn))
 886		return;
 887
 888	for (int tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
 889		for (int i = 1; i < mld->trans->info.num_rxqs; i++)
 890			memcpy(mld_ptk_pn->q[i].pn[tid],
 891			       wowlan_status->ptk.aes_seq[tid].ccmp.pn,
 892			       IEEE80211_CCMP_PN_LEN);
 893	}
 894}
 895
 896static void
 897iwl_mld_resume_keys_iter(struct ieee80211_hw *hw,
 898			 struct ieee80211_vif *vif,
 899			 struct ieee80211_sta *sta,
 900			 struct ieee80211_key_conf *key,
 901			 void *_data)
 902{
 903	struct iwl_mld_resume_key_iter_data *data = _data;
 904	struct iwl_mld_wowlan_status *wowlan_status = data->wowlan_status;
 905	u8 status_idx;
 906
 907	if (key->keyidx >= 0 && key->keyidx <= 3) {
 908		/* PTK */
 909		if (sta) {
 910			iwl_mld_update_ptk_rx_seq(data->mld, wowlan_status,
 911						  sta, key,
 912						  key->cipher ==
 913						  WLAN_CIPHER_SUITE_TKIP);
 914		/* GTK */
 915		} else {
 916			status_idx = key->keyidx == wowlan_status->gtk[1].id;
 917			iwl_mld_update_mcast_rx_seq(key,
 918						    &wowlan_status->gtk[status_idx]);
 919		}
 920	}
 921
 922	/* IGTK */
 923	if (key->keyidx == 4 || key->keyidx == 5) {
 924		if (key->keyidx == wowlan_status->igtk.id)
 925			iwl_mld_update_mcast_rx_seq(key, &wowlan_status->igtk);
 926	}
 927
 928	/* BIGTK */
 929	if (key->keyidx == 6 || key->keyidx == 7) {
 930		status_idx = key->keyidx == wowlan_status->bigtk[1].id;
 931		iwl_mld_update_mcast_rx_seq(key,
 932					    &wowlan_status->bigtk[status_idx]);
 933	}
 934}
 935
 936static void
 937iwl_mld_add_mcast_rekey(struct ieee80211_vif *vif,
 938			struct iwl_mld *mld,
 939			struct iwl_mld_mcast_key_data *key_data,
 940			struct ieee80211_bss_conf *link_conf)
 941{
 942	struct ieee80211_key_conf *key_config;
 943	int link_id = vif->active_links ? __ffs(vif->active_links) : -1;
 944
 945	if (!key_data->len)
 946		return;
 947
 948	key_config = ieee80211_gtk_rekey_add(vif, key_data->id, key_data->key,
 949					     sizeof(key_data->key), link_id);
 950	if (IS_ERR(key_config))
 951		return;
 952
 953	iwl_mld_update_mcast_rx_seq(key_config, key_data);
 954
 955	/* The FW holds only one igtk so we keep track of the valid one */
 956	if (key_config->keyidx == 4 || key_config->keyidx == 5) {
 957		struct iwl_mld_link *mld_link =
 958			iwl_mld_link_from_mac80211(link_conf);
 959
 960		/* If we had more than one rekey, mac80211 will tell us to
 961		 * remove the old and add the new so we will update the IGTK in
 962		 * drv_set_key
 963		 */
 964		if (mld_link->igtk && mld_link->igtk != key_config) {
 965			/* mark the old IGTK as not in FW */
 966			mld_link->igtk->hw_key_idx = STA_KEY_IDX_INVALID;
 967			mld_link->igtk = key_config;
 968		}
 969	}
 970
 971	/* Also keep track of the new BIGTK */
 972	if (key_config->keyidx == 6 || key_config->keyidx == 7)
 973		iwl_mld_track_bigtk(mld, vif, key_config, true);
 974}
 975
 976static void
 977iwl_mld_add_all_rekeys(struct iwl_mld *mld,
 978		       struct ieee80211_vif *vif,
 979		       struct iwl_mld_wowlan_status *wowlan_status,
 980		       struct ieee80211_bss_conf *link_conf)
 981{
 982	int i;
 983
 984	for (i = 0; i < ARRAY_SIZE(wowlan_status->gtk); i++)
 985		iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->gtk[i],
 986					link_conf);
 987
 988	iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->igtk, link_conf);
 989
 990	for (i = 0; i < ARRAY_SIZE(wowlan_status->bigtk); i++)
 991		iwl_mld_add_mcast_rekey(vif, mld, &wowlan_status->bigtk[i],
 992					link_conf);
 993}
 994
 995static void iwl_mld_mlo_rekey(struct iwl_mld *mld,
 996			      struct iwl_mld_wowlan_status *wowlan_status,
 997			      struct ieee80211_vif *vif)
 998{
 999	struct iwl_mld_old_mlo_keys *old_keys __free(kfree) = NULL;
1000
1001	IWL_DEBUG_WOWLAN(mld, "Num of MLO Keys: %d\n", wowlan_status->num_mlo_keys);
1002
1003	if (!wowlan_status->num_mlo_keys)
1004		return;
1005
1006	for (int i = 0; i < wowlan_status->num_mlo_keys; i++) {
1007		struct iwl_mld_wowlan_mlo_key *mlo_key = &wowlan_status->mlo_keys[i];
1008		struct ieee80211_key_conf *key;
1009		struct ieee80211_key_seq seq;
1010		u8 link_id = mlo_key->link_id;
1011
1012		if (IWL_FW_CHECK(mld, mlo_key->link_id >= IEEE80211_MLD_MAX_NUM_LINKS ||
1013				      mlo_key->idx >= 8 ||
1014				      mlo_key->type >= WOWLAN_MLO_GTK_KEY_NUM_TYPES,
1015				      "Invalid MLO key link_id %d, idx %d, type %d\n",
1016				      mlo_key->link_id, mlo_key->idx, mlo_key->type))
1017			continue;
1018
1019		if (!(vif->valid_links & BIT(link_id)) ||
1020		    (vif->active_links & BIT(link_id)))
1021			continue;
1022
1023		IWL_DEBUG_WOWLAN(mld, "Add MLO key id %d, link id %d\n",
1024				 mlo_key->idx, link_id);
1025
1026		key = ieee80211_gtk_rekey_add(vif, mlo_key->idx, mlo_key->key,
1027					      sizeof(mlo_key->key), link_id);
1028
1029		if (IS_ERR(key))
1030			continue;
1031
1032		/*
1033		 * mac80211 expects the PN in big-endian
1034		 * also note that seq is a union of all cipher types
1035		 * (ccmp, gcmp, cmac, gmac), and they all have the same
1036		 * pn field (of length 6) so just copy it to ccmp.pn.
1037		 */
1038		for (int j = 5; j >= 0; j--)
1039			seq.ccmp.pn[5 - j] = mlo_key->pn[j];
1040
1041		/* group keys are non-QoS and use TID 0 */
1042		ieee80211_set_key_rx_seq(key, 0, &seq);
1043	}
1044}
1045
1046static bool
1047iwl_mld_update_sec_keys(struct iwl_mld *mld,
1048			struct ieee80211_vif *vif,
1049			struct iwl_mld_wowlan_status *wowlan_status)
1050{
1051	int link_id = vif->active_links ? __ffs(vif->active_links) : 0;
1052	struct ieee80211_bss_conf *link_conf =
1053		link_conf_dereference_protected(vif, link_id);
1054	__be64 replay_ctr = cpu_to_be64(wowlan_status->replay_ctr);
1055	struct iwl_mld_resume_key_iter_data key_iter_data = {
1056		.mld = mld,
1057		.wowlan_status = wowlan_status,
1058	};
1059
1060	if (WARN_ON(!link_conf))
1061		return false;
1062
1063	ieee80211_iter_keys(mld->hw, vif, iwl_mld_resume_keys_iter,
1064			    &key_iter_data);
1065
1066	IWL_DEBUG_WOWLAN(mld, "Number of rekeys: %d\n",
1067			 wowlan_status->num_of_gtk_rekeys);
1068
1069	if (!wowlan_status->num_of_gtk_rekeys)
1070		return true;
1071
1072	iwl_mld_add_all_rekeys(mld, vif, wowlan_status,
1073			       link_conf);
1074
1075	iwl_mld_mlo_rekey(mld, wowlan_status, vif);
1076
1077	ieee80211_gtk_rekey_notify(vif, link_conf->bssid,
1078				   (void *)&replay_ctr, GFP_KERNEL);
1079	return true;
1080}
1081
1082static bool
1083iwl_mld_process_wowlan_status(struct iwl_mld *mld,
1084			      struct ieee80211_vif *vif,
1085			      struct iwl_mld_wowlan_status *wowlan_status)
1086{
1087	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1088	struct ieee80211_sta *ap_sta = mld_vif->ap_sta;
1089	struct iwl_mld_txq *mld_txq;
1090
1091	iwl_mld_report_wowlan_wakeup(mld, vif, wowlan_status);
1092
1093	if (WARN_ON(!ap_sta))
1094		return false;
1095
1096	mld_txq =
1097		iwl_mld_txq_from_mac80211(ap_sta->txq[wowlan_status->tid_offloaded_tx]);
1098
1099	/* Update the pointers of the Tx queue that may have moved during
1100	 * suspend if the firmware sent frames.
1101	 * The firmware stores last-used value, we store next value.
1102	 */
1103	WARN_ON(!mld_txq->status.allocated);
1104	iwl_trans_set_q_ptrs(mld->trans, mld_txq->fw_id,
1105			     (wowlan_status->last_qos_seq +
1106			     0x10) >> 4);
1107
1108	if (!iwl_mld_update_sec_keys(mld, vif, wowlan_status))
1109		return false;
1110
1111	if (wowlan_status->wakeup_reasons &
1112	    (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON |
1113	     IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH |
1114	     IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE))
1115		return false;
1116
1117	return true;
1118}
1119
1120static bool
1121iwl_mld_netdetect_match_info_handler(struct iwl_mld *mld,
1122				     struct iwl_mld_resume_data *resume_data,
1123				     struct iwl_rx_packet *pkt)
1124{
1125	struct iwl_mld_netdetect_res *results = resume_data->netdetect_res;
1126	const struct iwl_scan_offload_match_info *notif = (void *)pkt->data;
1127	u32 len = iwl_rx_packet_payload_len(pkt);
1128
1129	if (IWL_FW_CHECK(mld, !mld->netdetect,
1130			 "Got scan match info notif when mld->netdetect==%d\n",
1131			 mld->netdetect))
1132		return true;
1133
1134	if (IWL_FW_CHECK(mld, len < sizeof(*notif),
1135			 "Invalid scan offload match notif of length: %d\n",
1136			 len))
1137		return true;
1138
1139	if (IWL_FW_CHECK(mld, resume_data->wowlan_status->wakeup_reasons !=
1140			 IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS,
1141			 "Ignore scan match info: unexpected wakeup reason (expected=0x%x got=0x%x)\n",
1142			 IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS,
1143			 resume_data->wowlan_status->wakeup_reasons))
1144		return true;
1145
1146	results->matched_profiles = le32_to_cpu(notif->matched_profiles);
1147	IWL_DEBUG_WOWLAN(mld, "number of matched profiles=%u\n",
1148			 results->matched_profiles);
1149
1150	if (results->matched_profiles)
1151		memcpy(results->matches, notif->matches,
1152		       NETDETECT_QUERY_BUF_LEN);
1153
1154	/* No scan should be active at this point */
1155	mld->scan.status = 0;
1156	memset(mld->scan.uid_status, 0, sizeof(mld->scan.uid_status));
1157	return false;
1158}
1159
1160static void
1161iwl_mld_set_netdetect_info(struct iwl_mld *mld,
1162			   const struct cfg80211_sched_scan_request *netdetect_cfg,
1163			   struct cfg80211_wowlan_nd_info *netdetect_info,
1164			   struct iwl_mld_netdetect_res *netdetect_res,
1165			   unsigned long matched_profiles)
1166{
1167	int i;
1168
1169	for_each_set_bit(i, &matched_profiles, netdetect_cfg->n_match_sets) {
1170		struct cfg80211_wowlan_nd_match *match;
1171		int idx, j, n_channels = 0;
1172		struct iwl_scan_offload_profile_match *matches =
1173			(void *)netdetect_res->matches;
1174
1175		for (int k = 0; k < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; k++)
1176			n_channels +=
1177				hweight8(matches[i].matching_channels[k]);
1178		match = kzalloc(struct_size(match, channels, n_channels),
1179				GFP_KERNEL);
1180		if (!match)
1181			return;
1182
1183		netdetect_info->matches[netdetect_info->n_matches] = match;
1184		netdetect_info->n_matches++;
1185
1186		/* We inverted the order of the SSIDs in the scan
1187		 * request, so invert the index here.
1188		 */
1189		idx = netdetect_cfg->n_match_sets - i - 1;
1190		match->ssid.ssid_len =
1191			netdetect_cfg->match_sets[idx].ssid.ssid_len;
1192		memcpy(match->ssid.ssid,
1193		       netdetect_cfg->match_sets[idx].ssid.ssid,
1194		       match->ssid.ssid_len);
1195
1196		if (netdetect_cfg->n_channels < n_channels)
1197			continue;
1198
1199		for_each_set_bit(j,
1200				 (unsigned long *)&matches[i].matching_channels[0],
1201				 sizeof(matches[i].matching_channels)) {
1202			match->channels[match->n_channels] =
1203				netdetect_cfg->channels[j]->center_freq;
1204			match->n_channels++;
1205		}
1206	}
1207}
1208
1209static void
1210iwl_mld_process_netdetect_res(struct iwl_mld *mld,
1211			      struct ieee80211_vif *vif,
1212			      struct iwl_mld_resume_data *resume_data)
1213{
1214	struct cfg80211_wowlan_nd_info *netdetect_info = NULL;
1215	const struct cfg80211_sched_scan_request *netdetect_cfg;
1216	struct cfg80211_wowlan_wakeup wakeup = {
1217		.pattern_idx = -1,
1218	};
1219	struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
1220	unsigned long matched_profiles;
1221	u32 wakeup_reasons;
1222	int n_matches;
1223
1224	lockdep_assert_wiphy(mld->wiphy);
1225
1226	if (WARN_ON(!mld->wiphy->wowlan_config ||
1227		    !mld->wiphy->wowlan_config->nd_config)) {
1228		IWL_DEBUG_WOWLAN(mld,
1229				 "Netdetect isn't configured on resume flow\n");
1230		goto out;
1231	}
1232
1233	netdetect_cfg = mld->wiphy->wowlan_config->nd_config;
1234	wakeup_reasons = resume_data->wowlan_status->wakeup_reasons;
1235
1236	if (wakeup_reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
1237		wakeup.rfkill_release = true;
1238
1239	if (wakeup_reasons != IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS)
1240		goto out;
1241
1242	if (!resume_data->netdetect_res->matched_profiles) {
1243		IWL_DEBUG_WOWLAN(mld,
1244				 "Netdetect results aren't valid\n");
1245		wakeup_report = NULL;
1246		goto out;
1247	}
1248
1249	matched_profiles = resume_data->netdetect_res->matched_profiles;
1250	if (!netdetect_cfg->n_match_sets) {
1251		IWL_DEBUG_WOWLAN(mld,
1252				 "No netdetect match sets are configured\n");
1253		goto out;
1254	}
1255	n_matches = hweight_long(matched_profiles);
1256	netdetect_info = kzalloc(struct_size(netdetect_info, matches,
1257					     n_matches), GFP_KERNEL);
1258	if (netdetect_info)
1259		iwl_mld_set_netdetect_info(mld, netdetect_cfg, netdetect_info,
1260					   resume_data->netdetect_res,
1261					   matched_profiles);
1262
1263	wakeup.net_detect = netdetect_info;
1264 out:
1265	ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);
1266	if (netdetect_info) {
1267		for (int i = 0; i < netdetect_info->n_matches; i++)
1268			kfree(netdetect_info->matches[i]);
1269		kfree(netdetect_info);
1270	}
1271}
1272
1273static bool iwl_mld_handle_d3_notif(struct iwl_notif_wait_data *notif_wait,
1274				    struct iwl_rx_packet *pkt, void *data)
1275{
1276	struct iwl_mld_resume_data *resume_data = data;
1277	struct iwl_mld *mld =
1278		container_of(notif_wait, struct iwl_mld, notif_wait);
1279
1280	switch (WIDE_ID(pkt->hdr.group_id, pkt->hdr.cmd)) {
1281	case WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_INFO_NOTIFICATION): {
1282		if (resume_data->notifs_received & IWL_D3_NOTIF_WOWLAN_INFO) {
1283			IWL_DEBUG_WOWLAN(mld,
1284					 "got additional wowlan_info notif\n");
1285			break;
1286		}
1287		resume_data->notif_handling_err =
1288			iwl_mld_handle_wowlan_info_notif(mld,
1289							 resume_data->wowlan_status,
1290							 pkt);
1291		resume_data->notifs_received |= IWL_D3_NOTIF_WOWLAN_INFO;
1292
1293		if (resume_data->wowlan_status->wakeup_reasons &
1294		    IWL_WOWLAN_WAKEUP_REASON_HAS_WAKEUP_PKT)
1295			resume_data->notifs_expected |=
1296				IWL_D3_NOTIF_WOWLAN_WAKE_PKT;
1297		break;
1298	}
1299	case WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_WAKE_PKT_NOTIFICATION): {
1300		if (resume_data->notifs_received &
1301		    IWL_D3_NOTIF_WOWLAN_WAKE_PKT) {
1302			/* We shouldn't get two wake packet notifications */
1303			IWL_DEBUG_WOWLAN(mld,
1304					 "Got additional wowlan wake packet notification\n");
1305			break;
1306		}
1307		resume_data->notif_handling_err =
1308			iwl_mld_handle_wake_pkt_notif(mld,
1309						      resume_data->wowlan_status,
1310						      pkt);
1311		resume_data->notifs_received |= IWL_D3_NOTIF_WOWLAN_WAKE_PKT;
1312		break;
1313	}
1314	case WIDE_ID(SCAN_GROUP, OFFLOAD_MATCH_INFO_NOTIF): {
1315		if (resume_data->notifs_received & IWL_D3_ND_MATCH_INFO) {
1316			IWL_ERR(mld,
1317				"Got additional netdetect match info\n");
1318			break;
1319		}
1320
1321		resume_data->notif_handling_err =
1322			iwl_mld_netdetect_match_info_handler(mld, resume_data,
1323							     pkt);
1324		resume_data->notifs_received |= IWL_D3_ND_MATCH_INFO;
1325		break;
1326	}
1327	case WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION): {
1328		struct iwl_d3_end_notif *notif = (void *)pkt->data;
1329
1330		resume_data->d3_end_flags = le32_to_cpu(notif->flags);
1331		resume_data->notifs_received |= IWL_D3_NOTIF_D3_END_NOTIF;
1332		break;
1333	}
1334	default:
1335		WARN_ON(1);
1336	}
1337
1338	return resume_data->notifs_received == resume_data->notifs_expected;
1339}
1340
1341#define IWL_MLD_D3_NOTIF_TIMEOUT (HZ / 3)
1342
1343static int iwl_mld_wait_d3_notif(struct iwl_mld *mld,
1344				 struct iwl_mld_resume_data *resume_data,
1345				 bool with_wowlan)
1346{
1347	static const u16 wowlan_resume_notif[] = {
1348		WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_INFO_NOTIFICATION),
1349		WIDE_ID(PROT_OFFLOAD_GROUP, WOWLAN_WAKE_PKT_NOTIFICATION),
1350		WIDE_ID(SCAN_GROUP, OFFLOAD_MATCH_INFO_NOTIF),
1351		WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION)
1352	};
1353	static const u16 d3_resume_notif[] = {
1354		WIDE_ID(PROT_OFFLOAD_GROUP, D3_END_NOTIFICATION)
1355	};
1356	struct iwl_notification_wait wait_d3_notif;
1357	int ret;
1358
1359	if (with_wowlan)
1360		iwl_init_notification_wait(&mld->notif_wait, &wait_d3_notif,
1361					   wowlan_resume_notif,
1362					   ARRAY_SIZE(wowlan_resume_notif),
1363					   iwl_mld_handle_d3_notif,
1364					   resume_data);
1365	else
1366		iwl_init_notification_wait(&mld->notif_wait, &wait_d3_notif,
1367					   d3_resume_notif,
1368					   ARRAY_SIZE(d3_resume_notif),
1369					   iwl_mld_handle_d3_notif,
1370					   resume_data);
1371
1372	ret = iwl_trans_d3_resume(mld->trans, false);
1373	if (ret) {
1374		/* Avoid sending commands if the FW is dead */
1375		iwl_trans_notify_fw_error(mld->trans);
1376		iwl_remove_notification(&mld->notif_wait, &wait_d3_notif);
1377		return ret;
1378	}
1379
1380	ret = iwl_wait_notification(&mld->notif_wait, &wait_d3_notif,
1381				    IWL_MLD_D3_NOTIF_TIMEOUT);
1382	if (ret)
1383		IWL_ERR(mld, "Couldn't get the d3 notif %d\n", ret);
1384
1385	if (resume_data->notif_handling_err)
1386		ret = -EIO;
1387
1388	return ret;
1389}
1390
1391int iwl_mld_no_wowlan_suspend(struct iwl_mld *mld)
1392{
1393	struct iwl_d3_manager_config d3_cfg_cmd_data = {};
1394	int ret;
1395
1396	if (mld->debug_max_sleep) {
1397		d3_cfg_cmd_data.wakeup_host_timer =
1398			cpu_to_le32(mld->debug_max_sleep);
1399		d3_cfg_cmd_data.wakeup_flags =
1400			cpu_to_le32(IWL_WAKEUP_D3_HOST_TIMER);
1401	}
1402
1403	lockdep_assert_wiphy(mld->wiphy);
1404
1405	IWL_DEBUG_WOWLAN(mld, "Starting the no wowlan suspend flow\n");
1406
1407	iwl_mld_low_latency_stop(mld);
1408
1409	ret = iwl_mld_update_device_power(mld, true);
1410	if (ret) {
1411		IWL_ERR(mld,
1412			"d3 suspend: couldn't send power_device %d\n", ret);
1413		return ret;
1414	}
1415
1416	ret = iwl_mld_send_cmd_pdu(mld, D3_CONFIG_CMD,
1417				   &d3_cfg_cmd_data);
1418	if (ret) {
1419		IWL_ERR(mld,
1420			"d3 suspend: couldn't send D3_CONFIG_CMD %d\n", ret);
1421		return ret;
1422	}
1423
1424	ret = iwl_trans_d3_suspend(mld->trans, false);
1425	if (ret) {
1426		IWL_ERR(mld, "d3 suspend: trans_d3_suspend failed %d\n", ret);
1427		/* We are going to stop the FW. Avoid sending commands in that flow */
1428		iwl_trans_notify_fw_error(mld->trans);
1429	} else {
1430		/* Async notification might send hcmds, which is not allowed in suspend */
1431		iwl_mld_cancel_async_notifications(mld);
1432		mld->fw_status.in_d3 = true;
1433	}
1434
1435	return ret;
1436}
1437
1438int iwl_mld_no_wowlan_resume(struct iwl_mld *mld)
1439{
1440	struct iwl_mld_resume_data resume_data = {
1441		.notifs_expected =
1442			IWL_D3_NOTIF_D3_END_NOTIF,
1443	};
1444	int ret;
1445
1446	lockdep_assert_wiphy(mld->wiphy);
1447
1448	IWL_DEBUG_WOWLAN(mld, "Starting the no wowlan resume flow\n");
1449
1450	mld->fw_status.in_d3 = false;
1451	iwl_fw_dbg_read_d3_debug_data(&mld->fwrt);
1452
1453	ret = iwl_mld_wait_d3_notif(mld, &resume_data, false);
1454	if (ret)
1455		return ret;
1456
1457	if (!ret && (resume_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE))
1458		return -ENODEV;
1459
1460	iwl_mld_low_latency_restart(mld);
1461
1462	return iwl_mld_update_device_power(mld, false);
1463}
1464
1465static void
1466iwl_mld_aes_seq_to_le64_pn(struct ieee80211_key_conf *key,
1467			   __le64 *key_rsc)
1468{
1469	for (int i = 0; i < IWL_MAX_TID_COUNT; i++) {
1470		struct ieee80211_key_seq seq;
1471		u8 *pn = key->cipher == WLAN_CIPHER_SUITE_CCMP ? seq.ccmp.pn :
1472			seq.gcmp.pn;
1473
1474		ieee80211_get_key_rx_seq(key, i, &seq);
1475		key_rsc[i] = cpu_to_le64((u64)pn[5] |
1476					 ((u64)pn[4] << 8) |
1477					 ((u64)pn[3] << 16) |
1478					 ((u64)pn[2] << 24) |
1479					 ((u64)pn[1] << 32) |
1480					 ((u64)pn[0] << 40));
1481	}
1482}
1483
1484static void
1485iwl_mld_suspend_set_ucast_pn(struct iwl_mld *mld, struct ieee80211_sta *sta,
1486			     struct ieee80211_key_conf *key, __le64 *key_rsc)
1487{
1488	struct iwl_mld_sta *mld_sta =
1489		iwl_mld_sta_from_mac80211(sta);
1490	struct iwl_mld_ptk_pn *mld_ptk_pn;
1491
1492	if (WARN_ON(key->keyidx >= ARRAY_SIZE(mld_sta->ptk_pn)))
1493		return;
1494
1495	mld_ptk_pn = wiphy_dereference(mld->wiphy,
1496				       mld_sta->ptk_pn[key->keyidx]);
1497	if (WARN_ON(!mld_ptk_pn))
1498		return;
1499
1500	for (int tid = 0; tid < IWL_MAX_TID_COUNT; tid++) {
1501		struct ieee80211_key_seq seq;
1502		u8 *max_pn = seq.ccmp.pn;
1503
1504		/* get the PN from mac80211, used on the default queue */
1505		ieee80211_get_key_rx_seq(key, tid, &seq);
1506
1507		/* and use the internal data for all queues */
1508		for (int que = 1; que < mld->trans->info.num_rxqs; que++) {
1509			u8 *cur_pn = mld_ptk_pn->q[que].pn[tid];
1510
1511			if (memcmp(max_pn, cur_pn, IEEE80211_CCMP_PN_LEN) < 0)
1512				max_pn = cur_pn;
1513		}
1514		key_rsc[tid] = cpu_to_le64((u64)max_pn[5] |
1515					   ((u64)max_pn[4] << 8) |
1516					   ((u64)max_pn[3] << 16) |
1517					   ((u64)max_pn[2] << 24) |
1518					   ((u64)max_pn[1] << 32) |
1519					   ((u64)max_pn[0] << 40));
1520	}
1521}
1522
1523static void
1524iwl_mld_suspend_convert_tkip_ipn(struct ieee80211_key_conf *key,
1525				 __le64 *rsc)
1526{
1527	struct ieee80211_key_seq seq;
1528
1529	for (int i = 0; i < IWL_MAX_TID_COUNT; i++) {
1530		ieee80211_get_key_rx_seq(key, i, &seq);
1531		rsc[i] =
1532			cpu_to_le64(((u64)seq.tkip.iv32 << 16) |
1533				    seq.tkip.iv16);
1534	}
1535}
1536
1537static void
1538iwl_mld_suspend_key_data_iter(struct ieee80211_hw *hw,
1539			      struct ieee80211_vif *vif,
1540			      struct ieee80211_sta *sta,
1541			      struct ieee80211_key_conf *key,
1542			      void *_data)
1543{
1544	struct iwl_mld *mld = IWL_MAC80211_GET_MLD(hw);
1545	struct iwl_mld_suspend_key_iter_data *data = _data;
1546	__le64 *key_rsc;
1547	__le32 cipher = 0;
1548
1549	switch (key->cipher) {
1550	case WLAN_CIPHER_SUITE_CCMP:
1551		cipher = cpu_to_le32(STA_KEY_FLG_CCM);
1552		fallthrough;
1553	case WLAN_CIPHER_SUITE_GCMP:
1554	case WLAN_CIPHER_SUITE_GCMP_256:
1555		if (!cipher)
1556			cipher = cpu_to_le32(STA_KEY_FLG_GCMP);
1557		fallthrough;
1558	case WLAN_CIPHER_SUITE_TKIP:
1559		if (!cipher)
1560			cipher = cpu_to_le32(STA_KEY_FLG_TKIP);
1561		if (sta) {
1562			key_rsc = data->rsc->ucast_rsc;
1563			if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
1564				iwl_mld_suspend_convert_tkip_ipn(key, key_rsc);
1565			else
1566				iwl_mld_suspend_set_ucast_pn(mld, sta, key,
1567							     key_rsc);
1568
1569			data->have_rsc = true;
1570			return;
1571		}
1572		/* We're iterating from old to new, there're 4 possible
1573		 * gtk ids, and only the last two keys matter
1574		 */
1575		if (WARN_ON(data->gtks >=
1576				ARRAY_SIZE(data->found_gtk_idx)))
1577			return;
1578
1579		if (WARN_ON(key->keyidx >=
1580				ARRAY_SIZE(data->rsc->mcast_key_id_map)))
1581			return;
1582		data->gtk_cipher = cipher;
1583		data->found_gtk_idx[data->gtks] = key->keyidx;
1584		key_rsc = data->rsc->mcast_rsc[data->gtks % 2];
1585		data->rsc->mcast_key_id_map[key->keyidx] =
1586			data->gtks % 2;
1587
1588		if (data->gtks >= 2) {
1589			int prev = data->gtks % 2;
1590			int prev_idx = data->found_gtk_idx[prev];
1591
1592			data->rsc->mcast_key_id_map[prev_idx] =
1593				IWL_MCAST_KEY_MAP_INVALID;
1594		}
1595
1596		if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
1597			iwl_mld_suspend_convert_tkip_ipn(key, key_rsc);
1598		else
1599			iwl_mld_aes_seq_to_le64_pn(key, key_rsc);
1600
1601		data->gtks++;
1602		data->have_rsc = true;
1603		break;
1604	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
1605	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
1606		cipher = cpu_to_le32(STA_KEY_FLG_GCMP);
1607		fallthrough;
1608	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
1609	case WLAN_CIPHER_SUITE_AES_CMAC:
1610		if (!cipher)
1611			cipher = cpu_to_le32(STA_KEY_FLG_CCM);
1612		if (key->keyidx == 4 || key->keyidx == 5)
1613			data->igtk_cipher = cipher;
1614
1615		if (key->keyidx == 6 || key->keyidx == 7)
1616			data->bigtk_cipher = cipher;
1617
1618		break;
1619	}
1620}
1621
1622static int
1623iwl_mld_send_kek_kck_cmd(struct iwl_mld *mld,
1624			 struct iwl_mld_vif *mld_vif,
1625			 struct iwl_mld_suspend_key_iter_data data,
1626			 int ap_sta_id)
1627{
1628	struct iwl_wowlan_kek_kck_material_cmd_v4 kek_kck_cmd = {};
1629	struct iwl_mld_rekey_data *rekey_data =
1630		&mld_vif->wowlan_data.rekey_data;
1631
1632	memcpy(kek_kck_cmd.kck, rekey_data->kck,
1633	       rekey_data->kck_len);
1634	kek_kck_cmd.kck_len = cpu_to_le16(rekey_data->kck_len);
1635	memcpy(kek_kck_cmd.kek, rekey_data->kek,
1636	       rekey_data->kek_len);
1637	kek_kck_cmd.kek_len = cpu_to_le16(rekey_data->kek_len);
1638	kek_kck_cmd.replay_ctr = rekey_data->replay_ctr;
1639	kek_kck_cmd.akm = cpu_to_le32(rekey_data->akm);
1640	kek_kck_cmd.sta_id = cpu_to_le32(ap_sta_id);
1641	kek_kck_cmd.gtk_cipher = data.gtk_cipher;
1642	kek_kck_cmd.igtk_cipher = data.igtk_cipher;
1643	kek_kck_cmd.bigtk_cipher = data.bigtk_cipher;
1644
1645	IWL_DEBUG_WOWLAN(mld, "setting akm %d\n",
1646			 rekey_data->akm);
1647
1648	return iwl_mld_send_cmd_pdu(mld, WOWLAN_KEK_KCK_MATERIAL,
1649				    &kek_kck_cmd);
1650}
1651
1652static int
1653iwl_mld_suspend_send_security_cmds(struct iwl_mld *mld,
1654				   struct ieee80211_vif *vif,
1655				   struct iwl_mld_vif *mld_vif,
1656				   int ap_sta_id)
1657{
1658	struct iwl_mld_suspend_key_iter_data data = {};
1659	int ret;
1660
1661	data.rsc = kzalloc(sizeof(*data.rsc), GFP_KERNEL);
1662	if (!data.rsc)
1663		return -ENOMEM;
1664
1665	memset(data.rsc->mcast_key_id_map, IWL_MCAST_KEY_MAP_INVALID,
1666	       ARRAY_SIZE(data.rsc->mcast_key_id_map));
1667
1668	data.rsc->sta_id = cpu_to_le32(ap_sta_id);
1669	ieee80211_iter_keys(mld->hw, vif,
1670			    iwl_mld_suspend_key_data_iter,
1671			    &data);
1672
1673	if (data.have_rsc)
1674		ret = iwl_mld_send_cmd_pdu(mld, WOWLAN_TSC_RSC_PARAM,
1675					   data.rsc);
1676	else
1677		ret = 0;
1678
1679	if (!ret && mld_vif->wowlan_data.rekey_data.valid)
1680		ret = iwl_mld_send_kek_kck_cmd(mld, mld_vif, data, ap_sta_id);
1681
1682	kfree(data.rsc);
1683
1684	return ret;
1685}
1686
1687static void
1688iwl_mld_set_wowlan_config_cmd(struct iwl_mld *mld,
1689			      struct cfg80211_wowlan *wowlan,
1690			      struct iwl_wowlan_config_cmd *wowlan_config_cmd,
1691			      struct ieee80211_sta *ap_sta,
1692			      struct ieee80211_bss_conf *link)
1693{
1694	wowlan_config_cmd->is_11n_connection =
1695					ap_sta->deflink.ht_cap.ht_supported;
1696	wowlan_config_cmd->flags = ENABLE_L3_FILTERING |
1697		ENABLE_NBNS_FILTERING | ENABLE_DHCP_FILTERING;
1698
1699	if (ap_sta->mfp)
1700		wowlan_config_cmd->flags |= IS_11W_ASSOC;
1701
1702	if (iwl_mld_beacon_protection_enabled(mld, link))
1703		wowlan_config_cmd->flags |= HAS_BEACON_PROTECTION;
1704
1705	if (wowlan->disconnect)
1706		wowlan_config_cmd->wakeup_filter |=
1707			cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
1708				    IWL_WOWLAN_WAKEUP_LINK_CHANGE);
1709	if (wowlan->magic_pkt)
1710		wowlan_config_cmd->wakeup_filter |=
1711			cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);
1712	if (wowlan->gtk_rekey_failure)
1713		wowlan_config_cmd->wakeup_filter |=
1714			cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
1715	if (wowlan->eap_identity_req)
1716		wowlan_config_cmd->wakeup_filter |=
1717			cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);
1718	if (wowlan->four_way_handshake)
1719		wowlan_config_cmd->wakeup_filter |=
1720			cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
1721	if (wowlan->n_patterns)
1722		wowlan_config_cmd->wakeup_filter |=
1723			cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
1724
1725	if (wowlan->rfkill_release)
1726		wowlan_config_cmd->wakeup_filter |=
1727			cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
1728
1729	if (wowlan->any) {
1730		wowlan_config_cmd->wakeup_filter |=
1731			cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
1732				    IWL_WOWLAN_WAKEUP_LINK_CHANGE |
1733				    IWL_WOWLAN_WAKEUP_RX_FRAME |
1734				    IWL_WOWLAN_WAKEUP_BCN_FILTERING);
1735	}
1736}
1737
1738static int iwl_mld_send_patterns(struct iwl_mld *mld,
1739				 struct cfg80211_wowlan *wowlan,
1740				 int ap_sta_id)
1741{
1742	struct iwl_wowlan_patterns_cmd *pattern_cmd;
1743	struct iwl_host_cmd cmd = {
1744		.id = WOWLAN_PATTERNS,
1745		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
1746	};
1747	int ret;
1748
1749	if (!wowlan->n_patterns)
1750		return 0;
1751
1752	cmd.len[0] = struct_size(pattern_cmd, patterns, wowlan->n_patterns);
1753
1754	pattern_cmd = kzalloc(cmd.len[0], GFP_KERNEL);
1755	if (!pattern_cmd)
1756		return -ENOMEM;
1757
1758	pattern_cmd->n_patterns = wowlan->n_patterns;
1759	pattern_cmd->sta_id = ap_sta_id;
1760
1761	for (int i = 0; i < wowlan->n_patterns; i++) {
1762		int mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
1763
1764		pattern_cmd->patterns[i].pattern_type =
1765			WOWLAN_PATTERN_TYPE_BITMASK;
1766
1767		memcpy(&pattern_cmd->patterns[i].u.bitmask.mask,
1768		       wowlan->patterns[i].mask, mask_len);
1769		memcpy(&pattern_cmd->patterns[i].u.bitmask.pattern,
1770		       wowlan->patterns[i].pattern,
1771		       wowlan->patterns[i].pattern_len);
1772		pattern_cmd->patterns[i].u.bitmask.mask_size = mask_len;
1773		pattern_cmd->patterns[i].u.bitmask.pattern_size =
1774			wowlan->patterns[i].pattern_len;
1775	}
1776
1777	cmd.data[0] = pattern_cmd;
1778	ret = iwl_mld_send_cmd(mld, &cmd);
1779	kfree(pattern_cmd);
1780	return ret;
1781}
1782
1783static int
1784iwl_mld_send_proto_offload(struct iwl_mld *mld,
1785			   struct ieee80211_vif *vif,
1786			   u8 ap_sta_id)
1787{
1788	struct iwl_proto_offload_cmd_v4 *cmd __free(kfree);
1789	struct iwl_host_cmd hcmd = {
1790		.id = PROT_OFFLOAD_CONFIG_CMD,
1791		.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
1792		.len[0] = sizeof(*cmd),
1793	};
1794	u32 enabled = 0;
1795
1796	cmd = kzalloc(hcmd.len[0], GFP_KERNEL);
1797	if (!cmd) {
1798		IWL_DEBUG_WOWLAN(mld, "Failed to allocate proto offload cmd\n");
1799		return -ENOMEM;
1800	}
1801
1802#if IS_ENABLED(CONFIG_IPV6)
1803	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1804	struct iwl_mld_wowlan_data *wowlan_data = &mld_vif->wowlan_data;
1805	struct iwl_ns_config *nsc;
1806	struct iwl_targ_addr *addrs;
1807	int n_nsc, n_addrs;
1808	int i, c;
1809	int num_skipped = 0;
1810
1811	nsc = cmd->ns_config;
1812	n_nsc = IWL_PROTO_OFFLOAD_NUM_NS_CONFIG_V3L;
1813	addrs = cmd->targ_addrs;
1814	n_addrs = IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V3L;
1815
1816	/* For each address we have (and that will fit) fill a target
1817	 * address struct and combine for NS offload structs with the
1818	 * solicited node addresses.
1819	 */
1820	for (i = 0, c = 0;
1821		i < wowlan_data->num_target_ipv6_addrs &&
1822		i < n_addrs && c < n_nsc; i++) {
1823		int j;
1824		struct in6_addr solicited_addr;
1825
1826		/* Because ns is offloaded skip tentative address to avoid
1827		 * violating RFC4862.
1828		 */
1829		if (test_bit(i, wowlan_data->tentative_addrs)) {
1830			num_skipped++;
1831			continue;
1832		}
1833
1834		addrconf_addr_solict_mult(&wowlan_data->target_ipv6_addrs[i],
1835					  &solicited_addr);
1836		for (j = 0; j < n_nsc && j < c; j++)
1837			if (ipv6_addr_cmp(&nsc[j].dest_ipv6_addr,
1838					  &solicited_addr) == 0)
1839				break;
1840		if (j == c)
1841			c++;
1842		addrs[i].addr = wowlan_data->target_ipv6_addrs[i];
1843		addrs[i].config_num = cpu_to_le32(j);
1844		nsc[j].dest_ipv6_addr = solicited_addr;
1845		memcpy(nsc[j].target_mac_addr, vif->addr, ETH_ALEN);
1846	}
1847
1848	if (wowlan_data->num_target_ipv6_addrs - num_skipped)
1849		enabled |= IWL_D3_PROTO_IPV6_VALID;
1850
1851	cmd->num_valid_ipv6_addrs = cpu_to_le32(i - num_skipped);
1852	if (enabled & IWL_D3_PROTO_IPV6_VALID)
1853		enabled |= IWL_D3_PROTO_OFFLOAD_NS;
1854#endif
1855
1856	if (vif->cfg.arp_addr_cnt) {
1857		enabled |= IWL_D3_PROTO_OFFLOAD_ARP | IWL_D3_PROTO_IPV4_VALID;
1858		cmd->common.host_ipv4_addr = vif->cfg.arp_addr_list[0];
1859		ether_addr_copy(cmd->common.arp_mac_addr, vif->addr);
1860	}
1861
1862	enabled |= IWL_D3_PROTO_OFFLOAD_BTM;
1863	cmd->common.enabled = cpu_to_le32(enabled);
1864	cmd->sta_id = cpu_to_le32(ap_sta_id);
1865	hcmd.data[0] = cmd;
1866	return iwl_mld_send_cmd(mld, &hcmd);
1867}
1868
1869static int
1870iwl_mld_wowlan_config(struct iwl_mld *mld, struct ieee80211_vif *bss_vif,
1871		      struct cfg80211_wowlan *wowlan)
1872{
1873	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(bss_vif);
1874	struct ieee80211_sta *ap_sta = mld_vif->ap_sta;
1875	struct iwl_wowlan_config_cmd wowlan_config_cmd = {
1876			.offloading_tid = IWL_WOWLAN_OFFLOAD_TID,
1877	};
1878	u32 sta_id_mask;
1879	int ap_sta_id, ret;
1880	int link_id = iwl_mld_get_primary_link(bss_vif);
1881	struct ieee80211_bss_conf *link_conf;
1882
1883	ret = iwl_mld_block_emlsr_sync(mld, bss_vif,
1884				       IWL_MLD_EMLSR_BLOCKED_WOWLAN, link_id);
1885	if (ret)
1886		return ret;
1887
1888	link_conf = link_conf_dereference_protected(bss_vif, link_id);
1889
1890	if (WARN_ON(!ap_sta || !link_conf))
1891		return -EINVAL;
1892
1893	sta_id_mask = iwl_mld_fw_sta_id_mask(mld, ap_sta);
1894	if (WARN_ON(hweight32(sta_id_mask) != 1))
1895		return -EINVAL;
1896
1897	ap_sta_id = __ffs(sta_id_mask);
1898	wowlan_config_cmd.sta_id = ap_sta_id;
1899
1900	ret = iwl_mld_ensure_queue(mld,
1901				   ap_sta->txq[wowlan_config_cmd.offloading_tid]);
1902	if (ret)
1903		return ret;
1904
1905	iwl_mld_set_wowlan_config_cmd(mld, wowlan,
1906				      &wowlan_config_cmd, ap_sta, link_conf);
1907	ret = iwl_mld_send_cmd_pdu(mld, WOWLAN_CONFIGURATION,
1908				   &wowlan_config_cmd);
1909	if (ret)
1910		return ret;
1911
1912	ret = iwl_mld_suspend_send_security_cmds(mld, bss_vif, mld_vif,
1913						 ap_sta_id);
1914	if (ret)
1915		return ret;
1916
1917	ret = iwl_mld_send_patterns(mld, wowlan, ap_sta_id);
1918	if (ret)
1919		return ret;
1920
1921	ret = iwl_mld_send_proto_offload(mld, bss_vif, ap_sta_id);
1922	if (ret)
1923		return ret;
1924
1925	iwl_mld_enable_beacon_filter(mld, link_conf, true);
1926	return iwl_mld_update_mac_power(mld, bss_vif, true);
1927}
1928
1929int iwl_mld_wowlan_suspend(struct iwl_mld *mld, struct cfg80211_wowlan *wowlan)
1930{
1931	struct ieee80211_vif *bss_vif;
1932
1933	lockdep_assert_wiphy(mld->wiphy);
1934
1935	if (WARN_ON(!wowlan))
1936		return 1;
1937
1938	IWL_DEBUG_WOWLAN(mld, "Starting the wowlan suspend flow\n");
1939
1940	bss_vif = iwl_mld_get_bss_vif(mld);
1941	if (WARN_ON(!bss_vif))
1942		return 1;
1943
1944	if (!bss_vif->cfg.assoc) {
1945		int ret;
1946		/* If we're not associated, this must be netdetect */
1947		if (WARN_ON(!wowlan->nd_config))
1948			return 1;
1949
1950		ret = iwl_mld_netdetect_config(mld, bss_vif, wowlan);
1951		if (!ret)
1952			mld->netdetect = true;
1953
1954		return ret;
1955	}
1956
1957	return iwl_mld_wowlan_config(mld, bss_vif, wowlan);
1958}
1959
1960/* Returns 0 on success, 1 if an error occurred in firmware during d3,
1961 * A negative value is expected only in unrecovreable cases.
1962 */
1963int iwl_mld_wowlan_resume(struct iwl_mld *mld)
1964{
1965	struct ieee80211_vif *bss_vif;
1966	struct ieee80211_bss_conf *link_conf;
1967	struct iwl_mld_netdetect_res netdetect_res;
1968	struct iwl_mld_resume_data resume_data = {
1969		.notifs_expected =
1970			IWL_D3_NOTIF_WOWLAN_INFO |
1971			IWL_D3_NOTIF_D3_END_NOTIF,
1972		.netdetect_res = &netdetect_res,
1973	};
1974	int link_id;
1975	int ret;
1976
1977	lockdep_assert_wiphy(mld->wiphy);
1978
1979	IWL_DEBUG_WOWLAN(mld, "Starting the wowlan resume flow\n");
1980
1981	if (!mld->fw_status.in_d3) {
1982		IWL_DEBUG_WOWLAN(mld,
1983				 "Device_powered_off() was called during wowlan\n");
1984		goto err;
1985	}
1986
1987	mld->fw_status.resuming = true;
1988	mld->fw_status.in_d3 = false;
1989	mld->scan.last_start_time_jiffies = jiffies;
1990
1991	bss_vif = iwl_mld_get_bss_vif(mld);
1992	if (WARN_ON(!bss_vif))
1993		goto err;
1994
1995	/* We can't have several links upon wowlan entry,
1996	 * this is enforced in the suspend flow.
1997	 */
1998	WARN_ON(hweight16(bss_vif->active_links) > 1);
1999	link_id = bss_vif->active_links ? __ffs(bss_vif->active_links) : 0;
2000	link_conf = link_conf_dereference_protected(bss_vif, link_id);
2001
2002	if (WARN_ON(!link_conf))
2003		goto err;
2004
2005	iwl_fw_dbg_read_d3_debug_data(&mld->fwrt);
2006
2007	resume_data.wowlan_status = kzalloc(sizeof(*resume_data.wowlan_status),
2008					    GFP_KERNEL);
2009	if (!resume_data.wowlan_status)
2010		return -ENOMEM;
2011
2012	if (mld->netdetect)
2013		resume_data.notifs_expected |= IWL_D3_ND_MATCH_INFO;
2014
2015	ret = iwl_mld_wait_d3_notif(mld, &resume_data, true);
2016	if (ret) {
2017		IWL_ERR(mld, "Couldn't get the d3 notifs %d\n", ret);
2018		goto err;
2019	}
2020
2021	if (resume_data.d3_end_flags & IWL_D0I3_RESET_REQUIRE) {
2022		mld->fw_status.in_hw_restart = true;
2023		goto process_wakeup_results;
2024	}
2025
2026	iwl_mld_update_changed_regdomain(mld);
2027	iwl_mld_update_mac_power(mld, bss_vif, false);
2028	iwl_mld_enable_beacon_filter(mld, link_conf, false);
2029	iwl_mld_update_device_power(mld, false);
2030
2031	if (mld->netdetect)
2032		ret = iwl_mld_scan_stop(mld, IWL_MLD_SCAN_NETDETECT, false);
2033
2034 process_wakeup_results:
2035	if (mld->netdetect) {
2036		iwl_mld_process_netdetect_res(mld, bss_vif, &resume_data);
2037		mld->netdetect = false;
2038	} else {
2039		bool keep_connection =
2040			iwl_mld_process_wowlan_status(mld, bss_vif,
2041						      resume_data.wowlan_status);
2042
2043		/* EMLSR state will be cleared if the connection is not kept */
2044		if (keep_connection)
2045			iwl_mld_unblock_emlsr(mld, bss_vif,
2046					      IWL_MLD_EMLSR_BLOCKED_WOWLAN);
2047		else
2048			ieee80211_resume_disconnect(bss_vif);
2049	}
2050
2051	goto out;
2052
2053 err:
2054	mld->fw_status.in_hw_restart = true;
2055	ret = 1;
2056 out:
2057	mld->fw_status.resuming = false;
2058
2059	if (resume_data.wowlan_status) {
2060		kfree(resume_data.wowlan_status->wake_packet);
2061		kfree(resume_data.wowlan_status);
2062	}
2063
2064	return ret;
2065}
~/ Read-only file preview.