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