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