1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2/* Copyright(c) 2019-2020 Realtek Corporation
3 */
4
5#include "cam.h"
6#include "chan.h"
7#include "coex.h"
8#include "debug.h"
9#include "fw.h"
10#include "mac.h"
11#include "phy.h"
12#include "ps.h"
13#include "reg.h"
14#include "util.h"
15
16static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C};
17
18union rtw89_fw_element_arg {
19 size_t offset;
20 enum rtw89_rf_path rf_path;
21 enum rtw89_fw_type fw_type;
22};
23
24struct rtw89_fw_element_handler {
25 int (*fn)(struct rtw89_dev *rtwdev,
26 const struct rtw89_fw_element_hdr *elm,
27 const union rtw89_fw_element_arg arg);
28 const union rtw89_fw_element_arg arg;
29 const char *name;
30};
31
32static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
33 struct sk_buff *skb);
34static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
35 struct rtw89_wait_info *wait, unsigned int cond);
36
37static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len,
38 bool header)
39{
40 struct sk_buff *skb;
41 u32 header_len = 0;
42 u32 h2c_desc_size = rtwdev->chip->h2c_desc_size;
43
44 if (header)
45 header_len = H2C_HEADER_LEN;
46
47 skb = dev_alloc_skb(length: len + header_len + h2c_desc_size);
48 if (!skb)
49 return NULL;
50 skb_reserve(skb, len: header_len + h2c_desc_size);
51 memset(skb->data, 0, len);
52
53 return skb;
54}
55
56struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len)
57{
58 return rtw89_fw_h2c_alloc_skb(rtwdev, len, header: true);
59}
60
61struct sk_buff *rtw89_fw_h2c_alloc_skb_no_hdr(struct rtw89_dev *rtwdev, u32 len)
62{
63 return rtw89_fw_h2c_alloc_skb(rtwdev, len, header: false);
64}
65
66int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev, enum rtw89_fwdl_check_type type)
67{
68 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
69 u8 val;
70 int ret;
71
72 ret = read_poll_timeout_atomic(mac->fwdl_get_status, val,
73 val == RTW89_FWDL_WCPU_FW_INIT_RDY,
74 1, FWDL_WAIT_CNT, false, rtwdev, type);
75 if (ret) {
76 switch (val) {
77 case RTW89_FWDL_CHECKSUM_FAIL:
78 rtw89_err(rtwdev, "fw checksum fail\n");
79 return -EINVAL;
80
81 case RTW89_FWDL_SECURITY_FAIL:
82 rtw89_err(rtwdev, "fw security fail\n");
83 return -EINVAL;
84
85 case RTW89_FWDL_CV_NOT_MATCH:
86 rtw89_err(rtwdev, "fw cv not match\n");
87 return -EINVAL;
88
89 default:
90 rtw89_err(rtwdev, "fw unexpected status %d\n", val);
91 return -EBUSY;
92 }
93 }
94
95 set_bit(nr: RTW89_FLAG_FW_RDY, addr: rtwdev->flags);
96
97 return 0;
98}
99
100static int rtw89_fw_hdr_parser_v0(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
101 struct rtw89_fw_bin_info *info)
102{
103 const struct rtw89_fw_hdr *fw_hdr = (const struct rtw89_fw_hdr *)fw;
104 struct rtw89_fw_hdr_section_info *section_info;
105 const struct rtw89_fw_dynhdr_hdr *fwdynhdr;
106 const struct rtw89_fw_hdr_section *section;
107 const u8 *fw_end = fw + len;
108 const u8 *bin;
109 u32 base_hdr_len;
110 u32 mssc_len = 0;
111 u32 i;
112
113 if (!info)
114 return -EINVAL;
115
116 info->section_num = le32_get_bits(v: fw_hdr->w6, FW_HDR_W6_SEC_NUM);
117 base_hdr_len = struct_size(fw_hdr, sections, info->section_num);
118 info->dynamic_hdr_en = le32_get_bits(v: fw_hdr->w7, FW_HDR_W7_DYN_HDR);
119
120 if (info->dynamic_hdr_en) {
121 info->hdr_len = le32_get_bits(v: fw_hdr->w3, FW_HDR_W3_LEN);
122 info->dynamic_hdr_len = info->hdr_len - base_hdr_len;
123 fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len);
124 if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) {
125 rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n");
126 return -EINVAL;
127 }
128 } else {
129 info->hdr_len = base_hdr_len;
130 info->dynamic_hdr_len = 0;
131 }
132
133 bin = fw + info->hdr_len;
134
135 /* jump to section header */
136 section_info = info->section_info;
137 for (i = 0; i < info->section_num; i++) {
138 section = &fw_hdr->sections[i];
139 section_info->type =
140 le32_get_bits(v: section->w1, FWSECTION_HDR_W1_SECTIONTYPE);
141 if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
142 section_info->mssc =
143 le32_get_bits(v: section->w2, FWSECTION_HDR_W2_MSSC);
144 mssc_len += section_info->mssc * FWDL_SECURITY_SIGLEN;
145 } else {
146 section_info->mssc = 0;
147 }
148
149 section_info->len = le32_get_bits(v: section->w1, FWSECTION_HDR_W1_SEC_SIZE);
150 if (le32_get_bits(v: section->w1, FWSECTION_HDR_W1_CHECKSUM))
151 section_info->len += FWDL_SECTION_CHKSUM_LEN;
152 section_info->redl = le32_get_bits(v: section->w1, FWSECTION_HDR_W1_REDL);
153 section_info->dladdr =
154 le32_get_bits(v: section->w0, FWSECTION_HDR_W0_DL_ADDR) & 0x1fffffff;
155 section_info->addr = bin;
156 bin += section_info->len;
157 section_info++;
158 }
159
160 if (fw_end != bin + mssc_len) {
161 rtw89_err(rtwdev, "[ERR]fw bin size\n");
162 return -EINVAL;
163 }
164
165 return 0;
166}
167
168static int __get_mssc_key_idx(struct rtw89_dev *rtwdev,
169 const struct rtw89_fw_mss_pool_hdr *mss_hdr,
170 u32 rmp_tbl_size, u32 *key_idx)
171{
172 struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
173 u32 sel_byte_idx;
174 u32 mss_sel_idx;
175 u8 sel_bit_idx;
176 int i;
177
178 if (sec->mss_dev_type == RTW89_FW_MSS_DEV_TYPE_FWSEC_DEF) {
179 if (!mss_hdr->defen)
180 return -ENOENT;
181
182 mss_sel_idx = sec->mss_cust_idx * le16_to_cpu(mss_hdr->msskey_num_max) +
183 sec->mss_key_num;
184 } else {
185 if (mss_hdr->defen)
186 mss_sel_idx = FWDL_MSS_POOL_DEFKEYSETS_SIZE << 3;
187 else
188 mss_sel_idx = 0;
189 mss_sel_idx += sec->mss_dev_type * le16_to_cpu(mss_hdr->msskey_num_max) *
190 le16_to_cpu(mss_hdr->msscust_max) +
191 sec->mss_cust_idx * le16_to_cpu(mss_hdr->msskey_num_max) +
192 sec->mss_key_num;
193 }
194
195 sel_byte_idx = mss_sel_idx >> 3;
196 sel_bit_idx = mss_sel_idx & 0x7;
197
198 if (sel_byte_idx >= rmp_tbl_size)
199 return -EFAULT;
200
201 if (!(mss_hdr->rmp_tbl[sel_byte_idx] & BIT(sel_bit_idx)))
202 return -ENOENT;
203
204 *key_idx = hweight8(mss_hdr->rmp_tbl[sel_byte_idx] & (BIT(sel_bit_idx) - 1));
205
206 for (i = 0; i < sel_byte_idx; i++)
207 *key_idx += hweight8(mss_hdr->rmp_tbl[i]);
208
209 return 0;
210}
211
212static int __parse_formatted_mssc(struct rtw89_dev *rtwdev,
213 struct rtw89_fw_bin_info *info,
214 struct rtw89_fw_hdr_section_info *section_info,
215 const struct rtw89_fw_hdr_section_v1 *section,
216 const void *content,
217 u32 *mssc_len)
218{
219 const struct rtw89_fw_mss_pool_hdr *mss_hdr = content + section_info->len;
220 const union rtw89_fw_section_mssc_content *section_content = content;
221 struct rtw89_fw_secure *sec = &rtwdev->fw.sec;
222 u32 rmp_tbl_size;
223 u32 key_sign_len;
224 u32 real_key_idx;
225 u32 sb_sel_ver;
226 int ret;
227
228 if (memcmp(p: mss_signature, q: mss_hdr->signature, size: sizeof(mss_signature)) != 0) {
229 rtw89_err(rtwdev, "[ERR] wrong MSS signature\n");
230 return -ENOENT;
231 }
232
233 if (mss_hdr->rmpfmt == MSS_POOL_RMP_TBL_BITMASK) {
234 rmp_tbl_size = (le16_to_cpu(mss_hdr->msskey_num_max) *
235 le16_to_cpu(mss_hdr->msscust_max) *
236 mss_hdr->mssdev_max) >> 3;
237 if (mss_hdr->defen)
238 rmp_tbl_size += FWDL_MSS_POOL_DEFKEYSETS_SIZE;
239 } else {
240 rtw89_err(rtwdev, "[ERR] MSS Key Pool Remap Table Format Unsupport:%X\n",
241 mss_hdr->rmpfmt);
242 return -EINVAL;
243 }
244
245 if (rmp_tbl_size + sizeof(*mss_hdr) != le32_to_cpu(mss_hdr->key_raw_offset)) {
246 rtw89_err(rtwdev, "[ERR] MSS Key Pool Format Error:0x%X + 0x%X != 0x%X\n",
247 rmp_tbl_size, (int)sizeof(*mss_hdr),
248 le32_to_cpu(mss_hdr->key_raw_offset));
249 return -EINVAL;
250 }
251
252 key_sign_len = le16_to_cpu(section_content->key_sign_len.v) >> 2;
253 if (!key_sign_len)
254 key_sign_len = 512;
255
256 if (info->dsp_checksum)
257 key_sign_len += FWDL_SECURITY_CHKSUM_LEN;
258
259 *mssc_len = sizeof(*mss_hdr) + rmp_tbl_size +
260 le16_to_cpu(mss_hdr->keypair_num) * key_sign_len;
261
262 if (!sec->secure_boot)
263 goto out;
264
265 sb_sel_ver = le32_to_cpu(section_content->sb_sel_ver.v);
266 if (sb_sel_ver && sb_sel_ver != sec->sb_sel_mgn)
267 goto ignore;
268
269 ret = __get_mssc_key_idx(rtwdev, mss_hdr, rmp_tbl_size, key_idx: &real_key_idx);
270 if (ret)
271 goto ignore;
272
273 section_info->key_addr = content + section_info->len +
274 le32_to_cpu(mss_hdr->key_raw_offset) +
275 key_sign_len * real_key_idx;
276 section_info->key_len = key_sign_len;
277 section_info->key_idx = real_key_idx;
278
279out:
280 if (info->secure_section_exist) {
281 section_info->ignore = true;
282 return 0;
283 }
284
285 info->secure_section_exist = true;
286
287 return 0;
288
289ignore:
290 section_info->ignore = true;
291
292 return 0;
293}
294
295static int __parse_security_section(struct rtw89_dev *rtwdev,
296 struct rtw89_fw_bin_info *info,
297 struct rtw89_fw_hdr_section_info *section_info,
298 const struct rtw89_fw_hdr_section_v1 *section,
299 const void *content,
300 u32 *mssc_len)
301{
302 int ret;
303
304 section_info->mssc =
305 le32_get_bits(v: section->w2, FWSECTION_HDR_V1_W2_MSSC);
306
307 if (section_info->mssc == FORMATTED_MSSC) {
308 ret = __parse_formatted_mssc(rtwdev, info, section_info,
309 section, content, mssc_len);
310 if (ret)
311 return -EINVAL;
312 } else {
313 *mssc_len = section_info->mssc * FWDL_SECURITY_SIGLEN;
314 if (info->dsp_checksum)
315 *mssc_len += section_info->mssc * FWDL_SECURITY_CHKSUM_LEN;
316
317 info->secure_section_exist = true;
318 }
319
320 return 0;
321}
322
323static int rtw89_fw_hdr_parser_v1(struct rtw89_dev *rtwdev, const u8 *fw, u32 len,
324 struct rtw89_fw_bin_info *info)
325{
326 const struct rtw89_fw_hdr_v1 *fw_hdr = (const struct rtw89_fw_hdr_v1 *)fw;
327 struct rtw89_fw_hdr_section_info *section_info;
328 const struct rtw89_fw_dynhdr_hdr *fwdynhdr;
329 const struct rtw89_fw_hdr_section_v1 *section;
330 const u8 *fw_end = fw + len;
331 const u8 *bin;
332 u32 base_hdr_len;
333 u32 mssc_len;
334 int ret;
335 u32 i;
336
337 info->section_num = le32_get_bits(v: fw_hdr->w6, FW_HDR_V1_W6_SEC_NUM);
338 info->dsp_checksum = le32_get_bits(v: fw_hdr->w6, FW_HDR_V1_W6_DSP_CHKSUM);
339 base_hdr_len = struct_size(fw_hdr, sections, info->section_num);
340 info->dynamic_hdr_en = le32_get_bits(v: fw_hdr->w7, FW_HDR_V1_W7_DYN_HDR);
341
342 if (info->dynamic_hdr_en) {
343 info->hdr_len = le32_get_bits(v: fw_hdr->w5, FW_HDR_V1_W5_HDR_SIZE);
344 info->dynamic_hdr_len = info->hdr_len - base_hdr_len;
345 fwdynhdr = (const struct rtw89_fw_dynhdr_hdr *)(fw + base_hdr_len);
346 if (le32_to_cpu(fwdynhdr->hdr_len) != info->dynamic_hdr_len) {
347 rtw89_err(rtwdev, "[ERR]invalid fw dynamic header len\n");
348 return -EINVAL;
349 }
350 } else {
351 info->hdr_len = base_hdr_len;
352 info->dynamic_hdr_len = 0;
353 }
354
355 bin = fw + info->hdr_len;
356
357 /* jump to section header */
358 section_info = info->section_info;
359 for (i = 0; i < info->section_num; i++) {
360 section = &fw_hdr->sections[i];
361
362 section_info->type =
363 le32_get_bits(v: section->w1, FWSECTION_HDR_V1_W1_SECTIONTYPE);
364 section_info->len =
365 le32_get_bits(v: section->w1, FWSECTION_HDR_V1_W1_SEC_SIZE);
366 if (le32_get_bits(v: section->w1, FWSECTION_HDR_V1_W1_CHECKSUM))
367 section_info->len += FWDL_SECTION_CHKSUM_LEN;
368 section_info->redl = le32_get_bits(v: section->w1, FWSECTION_HDR_V1_W1_REDL);
369 section_info->dladdr =
370 le32_get_bits(v: section->w0, FWSECTION_HDR_V1_W0_DL_ADDR);
371 section_info->addr = bin;
372
373 if (section_info->type == FWDL_SECURITY_SECTION_TYPE) {
374 ret = __parse_security_section(rtwdev, info, section_info,
375 section, content: bin, mssc_len: &mssc_len);
376 if (ret)
377 return ret;
378 } else {
379 section_info->mssc = 0;
380 mssc_len = 0;
381 }
382
383 rtw89_debug(rtwdev, mask: RTW89_DBG_FW,
384 fmt: "section[%d] type=%d len=0x%-6x mssc=%d mssc_len=%d addr=%tx\n",
385 i, section_info->type, section_info->len,
386 section_info->mssc, mssc_len, bin - fw);
387 rtw89_debug(rtwdev, mask: RTW89_DBG_FW,
388 fmt: " ignore=%d key_addr=%p (0x%tx) key_len=%d key_idx=%d\n",
389 section_info->ignore, section_info->key_addr,
390 section_info->key_addr ?
391 section_info->key_addr - section_info->addr : 0,
392 section_info->key_len, section_info->key_idx);
393
394 bin += section_info->len + mssc_len;
395 section_info++;
396 }
397
398 if (fw_end != bin) {
399 rtw89_err(rtwdev, "[ERR]fw bin size\n");
400 return -EINVAL;
401 }
402
403 if (!info->secure_section_exist)
404 rtw89_warn(rtwdev, "no firmware secure section\n");
405
406 return 0;
407}
408
409static int rtw89_fw_hdr_parser(struct rtw89_dev *rtwdev,
410 const struct rtw89_fw_suit *fw_suit,
411 struct rtw89_fw_bin_info *info)
412{
413 const u8 *fw = fw_suit->data;
414 u32 len = fw_suit->size;
415
416 if (!fw || !len) {
417 rtw89_err(rtwdev, "fw type %d isn't recognized\n", fw_suit->type);
418 return -ENOENT;
419 }
420
421 switch (fw_suit->hdr_ver) {
422 case 0:
423 return rtw89_fw_hdr_parser_v0(rtwdev, fw, len, info);
424 case 1:
425 return rtw89_fw_hdr_parser_v1(rtwdev, fw, len, info);
426 default:
427 return -ENOENT;
428 }
429}
430
431static
432int rtw89_mfw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
433 struct rtw89_fw_suit *fw_suit, bool nowarn)
434{
435 struct rtw89_fw_info *fw_info = &rtwdev->fw;
436 const struct firmware *firmware = fw_info->req.firmware;
437 const u8 *mfw = firmware->data;
438 u32 mfw_len = firmware->size;
439 const struct rtw89_mfw_hdr *mfw_hdr = (const struct rtw89_mfw_hdr *)mfw;
440 const struct rtw89_mfw_info *mfw_info;
441 int i;
442
443 if (mfw_hdr->sig != RTW89_MFW_SIG) {
444 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "use legacy firmware\n");
445 /* legacy firmware support normal type only */
446 if (type != RTW89_FW_NORMAL)
447 return -EINVAL;
448 fw_suit->data = mfw;
449 fw_suit->size = mfw_len;
450 return 0;
451 }
452
453 for (i = 0; i < mfw_hdr->fw_nr; i++) {
454 mfw_info = &mfw_hdr->info[i];
455 if (mfw_info->type == type) {
456 if (mfw_info->cv == rtwdev->hal.cv && !mfw_info->mp)
457 goto found;
458 if (type == RTW89_FW_LOGFMT)
459 goto found;
460 }
461 }
462
463 if (!nowarn)
464 rtw89_err(rtwdev, "no suitable firmware found\n");
465 return -ENOENT;
466
467found:
468 fw_suit->data = mfw + le32_to_cpu(mfw_info->shift);
469 fw_suit->size = le32_to_cpu(mfw_info->size);
470 return 0;
471}
472
473static u32 rtw89_mfw_get_size(struct rtw89_dev *rtwdev)
474{
475 struct rtw89_fw_info *fw_info = &rtwdev->fw;
476 const struct firmware *firmware = fw_info->req.firmware;
477 const struct rtw89_mfw_hdr *mfw_hdr =
478 (const struct rtw89_mfw_hdr *)firmware->data;
479 const struct rtw89_mfw_info *mfw_info;
480 u32 size;
481
482 if (mfw_hdr->sig != RTW89_MFW_SIG) {
483 rtw89_warn(rtwdev, "not mfw format\n");
484 return 0;
485 }
486
487 mfw_info = &mfw_hdr->info[mfw_hdr->fw_nr - 1];
488 size = le32_to_cpu(mfw_info->shift) + le32_to_cpu(mfw_info->size);
489
490 return size;
491}
492
493static void rtw89_fw_update_ver_v0(struct rtw89_dev *rtwdev,
494 struct rtw89_fw_suit *fw_suit,
495 const struct rtw89_fw_hdr *hdr)
496{
497 fw_suit->major_ver = le32_get_bits(v: hdr->w1, FW_HDR_W1_MAJOR_VERSION);
498 fw_suit->minor_ver = le32_get_bits(v: hdr->w1, FW_HDR_W1_MINOR_VERSION);
499 fw_suit->sub_ver = le32_get_bits(v: hdr->w1, FW_HDR_W1_SUBVERSION);
500 fw_suit->sub_idex = le32_get_bits(v: hdr->w1, FW_HDR_W1_SUBINDEX);
501 fw_suit->commitid = le32_get_bits(v: hdr->w2, FW_HDR_W2_COMMITID);
502 fw_suit->build_year = le32_get_bits(v: hdr->w5, FW_HDR_W5_YEAR);
503 fw_suit->build_mon = le32_get_bits(v: hdr->w4, FW_HDR_W4_MONTH);
504 fw_suit->build_date = le32_get_bits(v: hdr->w4, FW_HDR_W4_DATE);
505 fw_suit->build_hour = le32_get_bits(v: hdr->w4, FW_HDR_W4_HOUR);
506 fw_suit->build_min = le32_get_bits(v: hdr->w4, FW_HDR_W4_MIN);
507 fw_suit->cmd_ver = le32_get_bits(v: hdr->w7, FW_HDR_W7_CMD_VERSERION);
508}
509
510static void rtw89_fw_update_ver_v1(struct rtw89_dev *rtwdev,
511 struct rtw89_fw_suit *fw_suit,
512 const struct rtw89_fw_hdr_v1 *hdr)
513{
514 fw_suit->major_ver = le32_get_bits(v: hdr->w1, FW_HDR_V1_W1_MAJOR_VERSION);
515 fw_suit->minor_ver = le32_get_bits(v: hdr->w1, FW_HDR_V1_W1_MINOR_VERSION);
516 fw_suit->sub_ver = le32_get_bits(v: hdr->w1, FW_HDR_V1_W1_SUBVERSION);
517 fw_suit->sub_idex = le32_get_bits(v: hdr->w1, FW_HDR_V1_W1_SUBINDEX);
518 fw_suit->commitid = le32_get_bits(v: hdr->w2, FW_HDR_V1_W2_COMMITID);
519 fw_suit->build_year = le32_get_bits(v: hdr->w5, FW_HDR_V1_W5_YEAR);
520 fw_suit->build_mon = le32_get_bits(v: hdr->w4, FW_HDR_V1_W4_MONTH);
521 fw_suit->build_date = le32_get_bits(v: hdr->w4, FW_HDR_V1_W4_DATE);
522 fw_suit->build_hour = le32_get_bits(v: hdr->w4, FW_HDR_V1_W4_HOUR);
523 fw_suit->build_min = le32_get_bits(v: hdr->w4, FW_HDR_V1_W4_MIN);
524 fw_suit->cmd_ver = le32_get_bits(v: hdr->w7, FW_HDR_V1_W3_CMD_VERSERION);
525}
526
527static int rtw89_fw_update_ver(struct rtw89_dev *rtwdev,
528 enum rtw89_fw_type type,
529 struct rtw89_fw_suit *fw_suit)
530{
531 const struct rtw89_fw_hdr *v0 = (const struct rtw89_fw_hdr *)fw_suit->data;
532 const struct rtw89_fw_hdr_v1 *v1 = (const struct rtw89_fw_hdr_v1 *)fw_suit->data;
533
534 if (type == RTW89_FW_LOGFMT)
535 return 0;
536
537 fw_suit->type = type;
538 fw_suit->hdr_ver = le32_get_bits(v: v0->w3, FW_HDR_W3_HDR_VER);
539
540 switch (fw_suit->hdr_ver) {
541 case 0:
542 rtw89_fw_update_ver_v0(rtwdev, fw_suit, hdr: v0);
543 break;
544 case 1:
545 rtw89_fw_update_ver_v1(rtwdev, fw_suit, hdr: v1);
546 break;
547 default:
548 rtw89_err(rtwdev, "Unknown firmware header version %u\n",
549 fw_suit->hdr_ver);
550 return -ENOENT;
551 }
552
553 rtw89_info(rtwdev,
554 "Firmware version %u.%u.%u.%u (%08x), cmd version %u, type %u\n",
555 fw_suit->major_ver, fw_suit->minor_ver, fw_suit->sub_ver,
556 fw_suit->sub_idex, fw_suit->commitid, fw_suit->cmd_ver, type);
557
558 return 0;
559}
560
561static
562int __rtw89_fw_recognize(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
563 bool nowarn)
564{
565 struct rtw89_fw_suit *fw_suit = rtw89_fw_suit_get(rtwdev, type);
566 int ret;
567
568 ret = rtw89_mfw_recognize(rtwdev, type, fw_suit, nowarn);
569 if (ret)
570 return ret;
571
572 return rtw89_fw_update_ver(rtwdev, type, fw_suit);
573}
574
575static
576int __rtw89_fw_recognize_from_elm(struct rtw89_dev *rtwdev,
577 const struct rtw89_fw_element_hdr *elm,
578 const union rtw89_fw_element_arg arg)
579{
580 enum rtw89_fw_type type = arg.fw_type;
581 struct rtw89_hal *hal = &rtwdev->hal;
582 struct rtw89_fw_suit *fw_suit;
583
584 if (hal->cv != elm->u.bbmcu.cv)
585 return 1; /* ignore this element */
586
587 fw_suit = rtw89_fw_suit_get(rtwdev, type);
588 fw_suit->data = elm->u.bbmcu.contents;
589 fw_suit->size = le32_to_cpu(elm->size);
590
591 return rtw89_fw_update_ver(rtwdev, type, fw_suit);
592}
593
594#define __DEF_FW_FEAT_COND(__cond, __op) \
595static bool __fw_feat_cond_ ## __cond(u32 suit_ver_code, u32 comp_ver_code) \
596{ \
597 return suit_ver_code __op comp_ver_code; \
598}
599
600__DEF_FW_FEAT_COND(ge, >=); /* greater or equal */
601__DEF_FW_FEAT_COND(le, <=); /* less or equal */
602__DEF_FW_FEAT_COND(lt, <); /* less than */
603
604struct __fw_feat_cfg {
605 enum rtw89_core_chip_id chip_id;
606 enum rtw89_fw_feature feature;
607 u32 ver_code;
608 bool (*cond)(u32 suit_ver_code, u32 comp_ver_code);
609};
610
611#define __CFG_FW_FEAT(_chip, _cond, _maj, _min, _sub, _idx, _feat) \
612 { \
613 .chip_id = _chip, \
614 .feature = RTW89_FW_FEATURE_ ## _feat, \
615 .ver_code = RTW89_FW_VER_CODE(_maj, _min, _sub, _idx), \
616 .cond = __fw_feat_cond_ ## _cond, \
617 }
618
619static const struct __fw_feat_cfg fw_feat_tbl[] = {
620 __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, TX_WAKE),
621 __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, SCAN_OFFLOAD),
622 __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER),
623 __CFG_FW_FEAT(RTL8852A, le, 0, 13, 29, 0, OLD_HT_RA_FORMAT),
624 __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD),
625 __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE),
626 __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 36, 0, CRASH_TRIGGER),
627 __CFG_FW_FEAT(RTL8852A, lt, 0, 13, 38, 0, NO_PACKET_DROP),
628 __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, NO_LPS_PG),
629 __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE),
630 __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER),
631 __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD),
632 __CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS),
633 __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE),
634 __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD),
635 __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 40, 0, CRASH_TRIGGER),
636 __CFG_FW_FEAT(RTL8852C, ge, 0, 27, 56, 10, BEACON_FILTER),
637 __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 30, 0, CRASH_TRIGGER),
638 __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 11, 0, MACID_PAUSE_SLEEP),
639 __CFG_FW_FEAT(RTL8922A, ge, 0, 34, 35, 0, SCAN_OFFLOAD),
640};
641
642static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
643 const struct rtw89_chip_info *chip,
644 u32 ver_code)
645{
646 int i;
647
648 for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) {
649 const struct __fw_feat_cfg *ent = &fw_feat_tbl[i];
650
651 if (chip->chip_id != ent->chip_id)
652 continue;
653
654 if (ent->cond(ver_code, ent->ver_code))
655 RTW89_SET_FW_FEATURE(ent->feature, fw);
656 }
657}
658
659static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
660{
661 const struct rtw89_chip_info *chip = rtwdev->chip;
662 const struct rtw89_fw_suit *fw_suit;
663 u32 suit_ver_code;
664
665 fw_suit = rtw89_fw_suit_get(rtwdev, type: RTW89_FW_NORMAL);
666 suit_ver_code = RTW89_FW_SUIT_VER_CODE(fw_suit);
667
668 rtw89_fw_iterate_feature_cfg(fw: &rtwdev->fw, chip, ver_code: suit_ver_code);
669}
670
671const struct firmware *
672rtw89_early_fw_feature_recognize(struct device *device,
673 const struct rtw89_chip_info *chip,
674 struct rtw89_fw_info *early_fw,
675 int *used_fw_format)
676{
677 const struct firmware *firmware;
678 char fw_name[64];
679 int fw_format;
680 u32 ver_code;
681 int ret;
682
683 for (fw_format = chip->fw_format_max; fw_format >= 0; fw_format--) {
684 rtw89_fw_get_filename(buf: fw_name, size: sizeof(fw_name),
685 fw_basename: chip->fw_basename, fw_format);
686
687 ret = request_firmware(fw: &firmware, name: fw_name, device);
688 if (!ret) {
689 dev_info(device, "loaded firmware %s\n", fw_name);
690 *used_fw_format = fw_format;
691 break;
692 }
693 }
694
695 if (ret) {
696 dev_err(device, "failed to early request firmware: %d\n", ret);
697 return NULL;
698 }
699
700 ver_code = rtw89_compat_fw_hdr_ver_code(fw_buf: firmware->data);
701
702 if (!ver_code)
703 goto out;
704
705 rtw89_fw_iterate_feature_cfg(fw: early_fw, chip, ver_code);
706
707out:
708 return firmware;
709}
710
711int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
712{
713 const struct rtw89_chip_info *chip = rtwdev->chip;
714 int ret;
715
716 if (chip->try_ce_fw) {
717 ret = __rtw89_fw_recognize(rtwdev, type: RTW89_FW_NORMAL_CE, nowarn: true);
718 if (!ret)
719 goto normal_done;
720 }
721
722 ret = __rtw89_fw_recognize(rtwdev, type: RTW89_FW_NORMAL, nowarn: false);
723 if (ret)
724 return ret;
725
726normal_done:
727 /* It still works if wowlan firmware isn't existing. */
728 __rtw89_fw_recognize(rtwdev, type: RTW89_FW_WOWLAN, nowarn: false);
729
730 /* It still works if log format file isn't existing. */
731 __rtw89_fw_recognize(rtwdev, type: RTW89_FW_LOGFMT, nowarn: true);
732
733 rtw89_fw_recognize_features(rtwdev);
734
735 rtw89_coex_recognize_ver(rtwdev);
736
737 return 0;
738}
739
740static
741int rtw89_build_phy_tbl_from_elm(struct rtw89_dev *rtwdev,
742 const struct rtw89_fw_element_hdr *elm,
743 const union rtw89_fw_element_arg arg)
744{
745 struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
746 struct rtw89_phy_table *tbl;
747 struct rtw89_reg2_def *regs;
748 enum rtw89_rf_path rf_path;
749 u32 n_regs, i;
750 u8 idx;
751
752 tbl = kzalloc(size: sizeof(*tbl), GFP_KERNEL);
753 if (!tbl)
754 return -ENOMEM;
755
756 switch (le32_to_cpu(elm->id)) {
757 case RTW89_FW_ELEMENT_ID_BB_REG:
758 elm_info->bb_tbl = tbl;
759 break;
760 case RTW89_FW_ELEMENT_ID_BB_GAIN:
761 elm_info->bb_gain = tbl;
762 break;
763 case RTW89_FW_ELEMENT_ID_RADIO_A:
764 case RTW89_FW_ELEMENT_ID_RADIO_B:
765 case RTW89_FW_ELEMENT_ID_RADIO_C:
766 case RTW89_FW_ELEMENT_ID_RADIO_D:
767 rf_path = arg.rf_path;
768 idx = elm->u.reg2.idx;
769
770 elm_info->rf_radio[idx] = tbl;
771 tbl->rf_path = rf_path;
772 tbl->config = rtw89_phy_config_rf_reg_v1;
773 break;
774 case RTW89_FW_ELEMENT_ID_RF_NCTL:
775 elm_info->rf_nctl = tbl;
776 break;
777 default:
778 kfree(objp: tbl);
779 return -ENOENT;
780 }
781
782 n_regs = le32_to_cpu(elm->size) / sizeof(tbl->regs[0]);
783 regs = kcalloc(n: n_regs, size: sizeof(tbl->regs[0]), GFP_KERNEL);
784 if (!regs)
785 goto out;
786
787 for (i = 0; i < n_regs; i++) {
788 regs[i].addr = le32_to_cpu(elm->u.reg2.regs[i].addr);
789 regs[i].data = le32_to_cpu(elm->u.reg2.regs[i].data);
790 }
791
792 tbl->n_regs = n_regs;
793 tbl->regs = regs;
794
795 return 0;
796
797out:
798 kfree(objp: tbl);
799 return -ENOMEM;
800}
801
802static
803int rtw89_fw_recognize_txpwr_from_elm(struct rtw89_dev *rtwdev,
804 const struct rtw89_fw_element_hdr *elm,
805 const union rtw89_fw_element_arg arg)
806{
807 const struct __rtw89_fw_txpwr_element *txpwr_elm = &elm->u.txpwr;
808 const unsigned long offset = arg.offset;
809 struct rtw89_efuse *efuse = &rtwdev->efuse;
810 struct rtw89_txpwr_conf *conf;
811
812 if (!rtwdev->rfe_data) {
813 rtwdev->rfe_data = kzalloc(size: sizeof(*rtwdev->rfe_data), GFP_KERNEL);
814 if (!rtwdev->rfe_data)
815 return -ENOMEM;
816 }
817
818 conf = (void *)rtwdev->rfe_data + offset;
819
820 /* if multiple matched, take the last eventually */
821 if (txpwr_elm->rfe_type == efuse->rfe_type)
822 goto setup;
823
824 /* without one is matched, accept default */
825 if (txpwr_elm->rfe_type == RTW89_TXPWR_CONF_DFLT_RFE_TYPE &&
826 (!rtw89_txpwr_conf_valid(conf) ||
827 conf->rfe_type == RTW89_TXPWR_CONF_DFLT_RFE_TYPE))
828 goto setup;
829
830 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "skip txpwr element ID %u RFE %u\n",
831 elm->id, txpwr_elm->rfe_type);
832 return 0;
833
834setup:
835 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "take txpwr element ID %u RFE %u\n",
836 elm->id, txpwr_elm->rfe_type);
837
838 conf->rfe_type = txpwr_elm->rfe_type;
839 conf->ent_sz = txpwr_elm->ent_sz;
840 conf->num_ents = le32_to_cpu(txpwr_elm->num_ents);
841 conf->data = txpwr_elm->content;
842 return 0;
843}
844
845static
846int rtw89_build_txpwr_trk_tbl_from_elm(struct rtw89_dev *rtwdev,
847 const struct rtw89_fw_element_hdr *elm,
848 const union rtw89_fw_element_arg arg)
849{
850 struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
851 const struct rtw89_chip_info *chip = rtwdev->chip;
852 u32 needed_bitmap = 0;
853 u32 offset = 0;
854 int subband;
855 u32 bitmap;
856 int type;
857
858 if (chip->support_bands & BIT(NL80211_BAND_6GHZ))
859 needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_6GHZ;
860 if (chip->support_bands & BIT(NL80211_BAND_5GHZ))
861 needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_5GHZ;
862 if (chip->support_bands & BIT(NL80211_BAND_2GHZ))
863 needed_bitmap |= RTW89_DEFAULT_NEEDED_FW_TXPWR_TRK_2GHZ;
864
865 bitmap = le32_to_cpu(elm->u.txpwr_trk.bitmap);
866
867 if ((bitmap & needed_bitmap) != needed_bitmap) {
868 rtw89_warn(rtwdev, "needed txpwr trk bitmap %08x but %0x8x\n",
869 needed_bitmap, bitmap);
870 return -ENOENT;
871 }
872
873 elm_info->txpwr_trk = kzalloc(size: sizeof(*elm_info->txpwr_trk), GFP_KERNEL);
874 if (!elm_info->txpwr_trk)
875 return -ENOMEM;
876
877 for (type = 0; bitmap; type++, bitmap >>= 1) {
878 if (!(bitmap & BIT(0)))
879 continue;
880
881 if (type >= __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_START &&
882 type <= __RTW89_FW_TXPWR_TRK_TYPE_6GHZ_MAX)
883 subband = 4;
884 else if (type >= __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_START &&
885 type <= __RTW89_FW_TXPWR_TRK_TYPE_5GHZ_MAX)
886 subband = 3;
887 else if (type >= __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_START &&
888 type <= __RTW89_FW_TXPWR_TRK_TYPE_2GHZ_MAX)
889 subband = 1;
890 else
891 break;
892
893 elm_info->txpwr_trk->delta[type] = &elm->u.txpwr_trk.contents[offset];
894
895 offset += subband;
896 if (offset * DELTA_SWINGIDX_SIZE > le32_to_cpu(elm->size))
897 goto err;
898 }
899
900 return 0;
901
902err:
903 rtw89_warn(rtwdev, "unexpected txpwr trk offset %d over size %d\n",
904 offset, le32_to_cpu(elm->size));
905 kfree(objp: elm_info->txpwr_trk);
906 elm_info->txpwr_trk = NULL;
907
908 return -EFAULT;
909}
910
911static
912int rtw89_build_rfk_log_fmt_from_elm(struct rtw89_dev *rtwdev,
913 const struct rtw89_fw_element_hdr *elm,
914 const union rtw89_fw_element_arg arg)
915{
916 struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
917 u8 rfk_id;
918
919 if (elm_info->rfk_log_fmt)
920 goto allocated;
921
922 elm_info->rfk_log_fmt = kzalloc(size: sizeof(*elm_info->rfk_log_fmt), GFP_KERNEL);
923 if (!elm_info->rfk_log_fmt)
924 return 1; /* this is an optional element, so just ignore this */
925
926allocated:
927 rfk_id = elm->u.rfk_log_fmt.rfk_id;
928 if (rfk_id >= RTW89_PHY_C2H_RFK_LOG_FUNC_NUM)
929 return 1;
930
931 elm_info->rfk_log_fmt->elm[rfk_id] = elm;
932
933 return 0;
934}
935
936static const struct rtw89_fw_element_handler __fw_element_handlers[] = {
937 [RTW89_FW_ELEMENT_ID_BBMCU0] = {__rtw89_fw_recognize_from_elm,
938 { .fw_type = RTW89_FW_BBMCU0 }, NULL},
939 [RTW89_FW_ELEMENT_ID_BBMCU1] = {.fn: __rtw89_fw_recognize_from_elm,
940 .arg: { .fw_type = RTW89_FW_BBMCU1 }, NULL},
941 [RTW89_FW_ELEMENT_ID_BB_REG] = {.fn: rtw89_build_phy_tbl_from_elm, .arg: {}, .name: "BB"},
942 [RTW89_FW_ELEMENT_ID_BB_GAIN] = {.fn: rtw89_build_phy_tbl_from_elm, .arg: {}, NULL},
943 [RTW89_FW_ELEMENT_ID_RADIO_A] = {.fn: rtw89_build_phy_tbl_from_elm,
944 .arg: { .rf_path = RF_PATH_A }, .name: "radio A"},
945 [RTW89_FW_ELEMENT_ID_RADIO_B] = {.fn: rtw89_build_phy_tbl_from_elm,
946 .arg: { .rf_path = RF_PATH_B }, NULL},
947 [RTW89_FW_ELEMENT_ID_RADIO_C] = {.fn: rtw89_build_phy_tbl_from_elm,
948 .arg: { .rf_path = RF_PATH_C }, NULL},
949 [RTW89_FW_ELEMENT_ID_RADIO_D] = {.fn: rtw89_build_phy_tbl_from_elm,
950 .arg: { .rf_path = RF_PATH_D }, NULL},
951 [RTW89_FW_ELEMENT_ID_RF_NCTL] = {.fn: rtw89_build_phy_tbl_from_elm, .arg: {}, .name: "NCTL"},
952 [RTW89_FW_ELEMENT_ID_TXPWR_BYRATE] = {
953 .fn: rtw89_fw_recognize_txpwr_from_elm,
954 .arg: { .offset = offsetof(struct rtw89_rfe_data, byrate.conf) }, .name: "TXPWR",
955 },
956 [RTW89_FW_ELEMENT_ID_TXPWR_LMT_2GHZ] = {
957 .fn: rtw89_fw_recognize_txpwr_from_elm,
958 .arg: { .offset = offsetof(struct rtw89_rfe_data, lmt_2ghz.conf) }, NULL,
959 },
960 [RTW89_FW_ELEMENT_ID_TXPWR_LMT_5GHZ] = {
961 .fn: rtw89_fw_recognize_txpwr_from_elm,
962 .arg: { .offset = offsetof(struct rtw89_rfe_data, lmt_5ghz.conf) }, NULL,
963 },
964 [RTW89_FW_ELEMENT_ID_TXPWR_LMT_6GHZ] = {
965 .fn: rtw89_fw_recognize_txpwr_from_elm,
966 .arg: { .offset = offsetof(struct rtw89_rfe_data, lmt_6ghz.conf) }, NULL,
967 },
968 [RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_2GHZ] = {
969 .fn: rtw89_fw_recognize_txpwr_from_elm,
970 .arg: { .offset = offsetof(struct rtw89_rfe_data, lmt_ru_2ghz.conf) }, NULL,
971 },
972 [RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_5GHZ] = {
973 .fn: rtw89_fw_recognize_txpwr_from_elm,
974 .arg: { .offset = offsetof(struct rtw89_rfe_data, lmt_ru_5ghz.conf) }, NULL,
975 },
976 [RTW89_FW_ELEMENT_ID_TXPWR_LMT_RU_6GHZ] = {
977 .fn: rtw89_fw_recognize_txpwr_from_elm,
978 .arg: { .offset = offsetof(struct rtw89_rfe_data, lmt_ru_6ghz.conf) }, NULL,
979 },
980 [RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT] = {
981 .fn: rtw89_fw_recognize_txpwr_from_elm,
982 .arg: { .offset = offsetof(struct rtw89_rfe_data, tx_shape_lmt.conf) }, NULL,
983 },
984 [RTW89_FW_ELEMENT_ID_TX_SHAPE_LMT_RU] = {
985 .fn: rtw89_fw_recognize_txpwr_from_elm,
986 .arg: { .offset = offsetof(struct rtw89_rfe_data, tx_shape_lmt_ru.conf) }, NULL,
987 },
988 [RTW89_FW_ELEMENT_ID_TXPWR_TRK] = {
989 .fn: rtw89_build_txpwr_trk_tbl_from_elm, .arg: {}, .name: "PWR_TRK",
990 },
991 [RTW89_FW_ELEMENT_ID_RFKLOG_FMT] = {
992 .fn: rtw89_build_rfk_log_fmt_from_elm, .arg: {}, NULL,
993 },
994};
995
996int rtw89_fw_recognize_elements(struct rtw89_dev *rtwdev)
997{
998 struct rtw89_fw_info *fw_info = &rtwdev->fw;
999 const struct firmware *firmware = fw_info->req.firmware;
1000 const struct rtw89_chip_info *chip = rtwdev->chip;
1001 u32 unrecognized_elements = chip->needed_fw_elms;
1002 const struct rtw89_fw_element_handler *handler;
1003 const struct rtw89_fw_element_hdr *hdr;
1004 u32 elm_size;
1005 u32 elem_id;
1006 u32 offset;
1007 int ret;
1008
1009 BUILD_BUG_ON(sizeof(chip->needed_fw_elms) * 8 < RTW89_FW_ELEMENT_ID_NUM);
1010
1011 offset = rtw89_mfw_get_size(rtwdev);
1012 offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN);
1013 if (offset == 0)
1014 return -EINVAL;
1015
1016 while (offset + sizeof(*hdr) < firmware->size) {
1017 hdr = (const struct rtw89_fw_element_hdr *)(firmware->data + offset);
1018
1019 elm_size = le32_to_cpu(hdr->size);
1020 if (offset + elm_size >= firmware->size) {
1021 rtw89_warn(rtwdev, "firmware element size exceeds\n");
1022 break;
1023 }
1024
1025 elem_id = le32_to_cpu(hdr->id);
1026 if (elem_id >= ARRAY_SIZE(__fw_element_handlers))
1027 goto next;
1028
1029 handler = &__fw_element_handlers[elem_id];
1030 if (!handler->fn)
1031 goto next;
1032
1033 ret = handler->fn(rtwdev, hdr, handler->arg);
1034 if (ret == 1) /* ignore this element */
1035 goto next;
1036 if (ret)
1037 return ret;
1038
1039 if (handler->name)
1040 rtw89_info(rtwdev, "Firmware element %s version: %4ph\n",
1041 handler->name, hdr->ver);
1042
1043 unrecognized_elements &= ~BIT(elem_id);
1044next:
1045 offset += sizeof(*hdr) + elm_size;
1046 offset = ALIGN(offset, RTW89_FW_ELEMENT_ALIGN);
1047 }
1048
1049 if (unrecognized_elements) {
1050 rtw89_err(rtwdev, "Firmware elements 0x%08x are unrecognized\n",
1051 unrecognized_elements);
1052 return -ENOENT;
1053 }
1054
1055 return 0;
1056}
1057
1058void rtw89_h2c_pkt_set_hdr(struct rtw89_dev *rtwdev, struct sk_buff *skb,
1059 u8 type, u8 cat, u8 class, u8 func,
1060 bool rack, bool dack, u32 len)
1061{
1062 struct fwcmd_hdr *hdr;
1063
1064 hdr = (struct fwcmd_hdr *)skb_push(skb, len: 8);
1065
1066 if (!(rtwdev->fw.h2c_seq % 4))
1067 rack = true;
1068 hdr->hdr0 = cpu_to_le32(FIELD_PREP(H2C_HDR_DEL_TYPE, type) |
1069 FIELD_PREP(H2C_HDR_CAT, cat) |
1070 FIELD_PREP(H2C_HDR_CLASS, class) |
1071 FIELD_PREP(H2C_HDR_FUNC, func) |
1072 FIELD_PREP(H2C_HDR_H2C_SEQ, rtwdev->fw.h2c_seq));
1073
1074 hdr->hdr1 = cpu_to_le32(FIELD_PREP(H2C_HDR_TOTAL_LEN,
1075 len + H2C_HEADER_LEN) |
1076 (rack ? H2C_HDR_REC_ACK : 0) |
1077 (dack ? H2C_HDR_DONE_ACK : 0));
1078
1079 rtwdev->fw.h2c_seq++;
1080}
1081
1082static void rtw89_h2c_pkt_set_hdr_fwdl(struct rtw89_dev *rtwdev,
1083 struct sk_buff *skb,
1084 u8 type, u8 cat, u8 class, u8 func,
1085 u32 len)
1086{
1087 struct fwcmd_hdr *hdr;
1088
1089 hdr = (struct fwcmd_hdr *)skb_push(skb, len: 8);
1090
1091 hdr->hdr0 = cpu_to_le32(FIELD_PREP(H2C_HDR_DEL_TYPE, type) |
1092 FIELD_PREP(H2C_HDR_CAT, cat) |
1093 FIELD_PREP(H2C_HDR_CLASS, class) |
1094 FIELD_PREP(H2C_HDR_FUNC, func) |
1095 FIELD_PREP(H2C_HDR_H2C_SEQ, rtwdev->fw.h2c_seq));
1096
1097 hdr->hdr1 = cpu_to_le32(FIELD_PREP(H2C_HDR_TOTAL_LEN,
1098 len + H2C_HEADER_LEN));
1099}
1100
1101static u32 __rtw89_fw_download_tweak_hdr_v0(struct rtw89_dev *rtwdev,
1102 struct rtw89_fw_bin_info *info,
1103 struct rtw89_fw_hdr *fw_hdr)
1104{
1105 le32p_replace_bits(p: &fw_hdr->w7, FWDL_SECTION_PER_PKT_LEN,
1106 FW_HDR_W7_PART_SIZE);
1107
1108 return 0;
1109}
1110
1111static u32 __rtw89_fw_download_tweak_hdr_v1(struct rtw89_dev *rtwdev,
1112 struct rtw89_fw_bin_info *info,
1113 struct rtw89_fw_hdr_v1 *fw_hdr)
1114{
1115 struct rtw89_fw_hdr_section_info *section_info;
1116 struct rtw89_fw_hdr_section_v1 *section;
1117 u8 dst_sec_idx = 0;
1118 u8 sec_idx;
1119
1120 le32p_replace_bits(p: &fw_hdr->w7, FWDL_SECTION_PER_PKT_LEN,
1121 FW_HDR_V1_W7_PART_SIZE);
1122
1123 for (sec_idx = 0; sec_idx < info->section_num; sec_idx++) {
1124 section_info = &info->section_info[sec_idx];
1125 section = &fw_hdr->sections[sec_idx];
1126
1127 if (section_info->ignore)
1128 continue;
1129
1130 if (dst_sec_idx != sec_idx)
1131 fw_hdr->sections[dst_sec_idx] = *section;
1132
1133 dst_sec_idx++;
1134 }
1135
1136 le32p_replace_bits(p: &fw_hdr->w6, val: dst_sec_idx, FW_HDR_V1_W6_SEC_NUM);
1137
1138 return (info->section_num - dst_sec_idx) * sizeof(*section);
1139}
1140
1141static int __rtw89_fw_download_hdr(struct rtw89_dev *rtwdev,
1142 const struct rtw89_fw_suit *fw_suit,
1143 struct rtw89_fw_bin_info *info)
1144{
1145 u32 len = info->hdr_len - info->dynamic_hdr_len;
1146 struct rtw89_fw_hdr_v1 *fw_hdr_v1;
1147 const u8 *fw = fw_suit->data;
1148 struct rtw89_fw_hdr *fw_hdr;
1149 struct sk_buff *skb;
1150 u32 truncated;
1151 u32 ret = 0;
1152
1153 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
1154 if (!skb) {
1155 rtw89_err(rtwdev, "failed to alloc skb for fw hdr dl\n");
1156 return -ENOMEM;
1157 }
1158
1159 skb_put_data(skb, data: fw, len);
1160
1161 switch (fw_suit->hdr_ver) {
1162 case 0:
1163 fw_hdr = (struct rtw89_fw_hdr *)skb->data;
1164 truncated = __rtw89_fw_download_tweak_hdr_v0(rtwdev, info, fw_hdr);
1165 break;
1166 case 1:
1167 fw_hdr_v1 = (struct rtw89_fw_hdr_v1 *)skb->data;
1168 truncated = __rtw89_fw_download_tweak_hdr_v1(rtwdev, info, fw_hdr: fw_hdr_v1);
1169 break;
1170 default:
1171 ret = -EOPNOTSUPP;
1172 goto fail;
1173 }
1174
1175 if (truncated) {
1176 len -= truncated;
1177 skb_trim(skb, len);
1178 }
1179
1180 rtw89_h2c_pkt_set_hdr_fwdl(rtwdev, skb, FWCMD_TYPE_H2C,
1181 H2C_CAT_MAC, H2C_CL_MAC_FWDL,
1182 H2C_FUNC_MAC_FWHDR_DL, len);
1183
1184 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
1185 if (ret) {
1186 rtw89_err(rtwdev, "failed to send h2c\n");
1187 ret = -1;
1188 goto fail;
1189 }
1190
1191 return 0;
1192fail:
1193 dev_kfree_skb_any(skb);
1194
1195 return ret;
1196}
1197
1198static int rtw89_fw_download_hdr(struct rtw89_dev *rtwdev,
1199 const struct rtw89_fw_suit *fw_suit,
1200 struct rtw89_fw_bin_info *info)
1201{
1202 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1203 int ret;
1204
1205 ret = __rtw89_fw_download_hdr(rtwdev, fw_suit, info);
1206 if (ret) {
1207 rtw89_err(rtwdev, "[ERR]FW header download\n");
1208 return ret;
1209 }
1210
1211 ret = mac->fwdl_check_path_ready(rtwdev, false);
1212 if (ret) {
1213 rtw89_err(rtwdev, "[ERR]FWDL path ready\n");
1214 return ret;
1215 }
1216
1217 rtw89_write32(rtwdev, R_AX_HALT_H2C_CTRL, data: 0);
1218 rtw89_write32(rtwdev, R_AX_HALT_C2H_CTRL, data: 0);
1219
1220 return 0;
1221}
1222
1223static int __rtw89_fw_download_main(struct rtw89_dev *rtwdev,
1224 struct rtw89_fw_hdr_section_info *info)
1225{
1226 struct sk_buff *skb;
1227 const u8 *section = info->addr;
1228 u32 residue_len = info->len;
1229 bool copy_key = false;
1230 u32 pkt_len;
1231 int ret;
1232
1233 if (info->ignore)
1234 return 0;
1235
1236 if (info->key_addr && info->key_len) {
1237 if (info->len > FWDL_SECTION_PER_PKT_LEN || info->len < info->key_len)
1238 rtw89_warn(rtwdev, "ignore to copy key data because of len %d, %d, %d\n",
1239 info->len, FWDL_SECTION_PER_PKT_LEN, info->key_len);
1240 else
1241 copy_key = true;
1242 }
1243
1244 while (residue_len) {
1245 if (residue_len >= FWDL_SECTION_PER_PKT_LEN)
1246 pkt_len = FWDL_SECTION_PER_PKT_LEN;
1247 else
1248 pkt_len = residue_len;
1249
1250 skb = rtw89_fw_h2c_alloc_skb_no_hdr(rtwdev, len: pkt_len);
1251 if (!skb) {
1252 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
1253 return -ENOMEM;
1254 }
1255 skb_put_data(skb, data: section, len: pkt_len);
1256
1257 if (copy_key)
1258 memcpy(skb->data + pkt_len - info->key_len,
1259 info->key_addr, info->key_len);
1260
1261 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: true);
1262 if (ret) {
1263 rtw89_err(rtwdev, "failed to send h2c\n");
1264 ret = -1;
1265 goto fail;
1266 }
1267
1268 section += pkt_len;
1269 residue_len -= pkt_len;
1270 }
1271
1272 return 0;
1273fail:
1274 dev_kfree_skb_any(skb);
1275
1276 return ret;
1277}
1278
1279static enum rtw89_fwdl_check_type
1280rtw89_fw_get_fwdl_chk_type_from_suit(struct rtw89_dev *rtwdev,
1281 const struct rtw89_fw_suit *fw_suit)
1282{
1283 switch (fw_suit->type) {
1284 case RTW89_FW_BBMCU0:
1285 return RTW89_FWDL_CHECK_BB0_FWDL_DONE;
1286 case RTW89_FW_BBMCU1:
1287 return RTW89_FWDL_CHECK_BB1_FWDL_DONE;
1288 default:
1289 return RTW89_FWDL_CHECK_WCPU_FWDL_DONE;
1290 }
1291}
1292
1293static int rtw89_fw_download_main(struct rtw89_dev *rtwdev,
1294 const struct rtw89_fw_suit *fw_suit,
1295 struct rtw89_fw_bin_info *info)
1296{
1297 struct rtw89_fw_hdr_section_info *section_info = info->section_info;
1298 const struct rtw89_chip_info *chip = rtwdev->chip;
1299 enum rtw89_fwdl_check_type chk_type;
1300 u8 section_num = info->section_num;
1301 int ret;
1302
1303 while (section_num--) {
1304 ret = __rtw89_fw_download_main(rtwdev, info: section_info);
1305 if (ret)
1306 return ret;
1307 section_info++;
1308 }
1309
1310 if (chip->chip_gen == RTW89_CHIP_AX)
1311 return 0;
1312
1313 chk_type = rtw89_fw_get_fwdl_chk_type_from_suit(rtwdev, fw_suit);
1314 ret = rtw89_fw_check_rdy(rtwdev, type: chk_type);
1315 if (ret) {
1316 rtw89_warn(rtwdev, "failed to download firmware type %u\n",
1317 fw_suit->type);
1318 return ret;
1319 }
1320
1321 return 0;
1322}
1323
1324static void rtw89_fw_prog_cnt_dump(struct rtw89_dev *rtwdev)
1325{
1326 enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
1327 u32 addr = R_AX_DBG_PORT_SEL;
1328 u32 val32;
1329 u16 index;
1330
1331 if (chip_gen == RTW89_CHIP_BE) {
1332 addr = R_BE_WLCPU_PORT_PC;
1333 goto dump;
1334 }
1335
1336 rtw89_write32(rtwdev, R_AX_DBG_CTRL,
1337 FIELD_PREP(B_AX_DBG_SEL0, FW_PROG_CNTR_DBG_SEL) |
1338 FIELD_PREP(B_AX_DBG_SEL1, FW_PROG_CNTR_DBG_SEL));
1339 rtw89_write32_mask(rtwdev, R_AX_SYS_STATUS1, B_AX_SEL_0XC0_MASK, MAC_DBG_SEL);
1340
1341dump:
1342 for (index = 0; index < 15; index++) {
1343 val32 = rtw89_read32(rtwdev, addr);
1344 rtw89_err(rtwdev, "[ERR]fw PC = 0x%x\n", val32);
1345 fsleep(usecs: 10);
1346 }
1347}
1348
1349static void rtw89_fw_dl_fail_dump(struct rtw89_dev *rtwdev)
1350{
1351 u32 val32;
1352 u16 val16;
1353
1354 val32 = rtw89_read32(rtwdev, R_AX_WCPU_FW_CTRL);
1355 rtw89_err(rtwdev, "[ERR]fwdl 0x1E0 = 0x%x\n", val32);
1356
1357 val16 = rtw89_read16(rtwdev, R_AX_BOOT_DBG + 2);
1358 rtw89_err(rtwdev, "[ERR]fwdl 0x83F2 = 0x%x\n", val16);
1359
1360 rtw89_fw_prog_cnt_dump(rtwdev);
1361}
1362
1363static int rtw89_fw_download_suit(struct rtw89_dev *rtwdev,
1364 struct rtw89_fw_suit *fw_suit)
1365{
1366 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1367 struct rtw89_fw_bin_info info = {};
1368 int ret;
1369
1370 ret = rtw89_fw_hdr_parser(rtwdev, fw_suit, info: &info);
1371 if (ret) {
1372 rtw89_err(rtwdev, "parse fw header fail\n");
1373 return ret;
1374 }
1375
1376 if (rtwdev->chip->chip_id == RTL8922A &&
1377 (fw_suit->type == RTW89_FW_NORMAL || fw_suit->type == RTW89_FW_WOWLAN))
1378 rtw89_write32(rtwdev, R_BE_SECURE_BOOT_MALLOC_INFO, data: 0x20248000);
1379
1380 ret = mac->fwdl_check_path_ready(rtwdev, true);
1381 if (ret) {
1382 rtw89_err(rtwdev, "[ERR]H2C path ready\n");
1383 return ret;
1384 }
1385
1386 ret = rtw89_fw_download_hdr(rtwdev, fw_suit, info: &info);
1387 if (ret)
1388 return ret;
1389
1390 ret = rtw89_fw_download_main(rtwdev, fw_suit, info: &info);
1391 if (ret)
1392 return ret;
1393
1394 return 0;
1395}
1396
1397int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type,
1398 bool include_bb)
1399{
1400 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
1401 struct rtw89_fw_info *fw_info = &rtwdev->fw;
1402 struct rtw89_fw_suit *fw_suit = rtw89_fw_suit_get(rtwdev, type);
1403 u8 bbmcu_nr = rtwdev->chip->bbmcu_nr;
1404 int ret;
1405 int i;
1406
1407 mac->disable_cpu(rtwdev);
1408 ret = mac->fwdl_enable_wcpu(rtwdev, 0, true, include_bb);
1409 if (ret)
1410 return ret;
1411
1412 ret = rtw89_fw_download_suit(rtwdev, fw_suit);
1413 if (ret)
1414 goto fwdl_err;
1415
1416 for (i = 0; i < bbmcu_nr && include_bb; i++) {
1417 fw_suit = rtw89_fw_suit_get(rtwdev, type: RTW89_FW_BBMCU0 + i);
1418
1419 ret = rtw89_fw_download_suit(rtwdev, fw_suit);
1420 if (ret)
1421 goto fwdl_err;
1422 }
1423
1424 fw_info->h2c_seq = 0;
1425 fw_info->rec_seq = 0;
1426 fw_info->h2c_counter = 0;
1427 fw_info->c2h_counter = 0;
1428 rtwdev->mac.rpwm_seq_num = RPWM_SEQ_NUM_MAX;
1429 rtwdev->mac.cpwm_seq_num = CPWM_SEQ_NUM_MAX;
1430
1431 mdelay(5);
1432
1433 ret = rtw89_fw_check_rdy(rtwdev, type: RTW89_FWDL_CHECK_FREERTOS_DONE);
1434 if (ret) {
1435 rtw89_warn(rtwdev, "download firmware fail\n");
1436 return ret;
1437 }
1438
1439 return ret;
1440
1441fwdl_err:
1442 rtw89_fw_dl_fail_dump(rtwdev);
1443 return ret;
1444}
1445
1446int rtw89_wait_firmware_completion(struct rtw89_dev *rtwdev)
1447{
1448 struct rtw89_fw_info *fw = &rtwdev->fw;
1449
1450 wait_for_completion(&fw->req.completion);
1451 if (!fw->req.firmware)
1452 return -EINVAL;
1453
1454 return 0;
1455}
1456
1457static int rtw89_load_firmware_req(struct rtw89_dev *rtwdev,
1458 struct rtw89_fw_req_info *req,
1459 const char *fw_name, bool nowarn)
1460{
1461 int ret;
1462
1463 if (req->firmware) {
1464 rtw89_debug(rtwdev, mask: RTW89_DBG_FW,
1465 fmt: "full firmware has been early requested\n");
1466 complete_all(&req->completion);
1467 return 0;
1468 }
1469
1470 if (nowarn)
1471 ret = firmware_request_nowarn(fw: &req->firmware, name: fw_name, device: rtwdev->dev);
1472 else
1473 ret = request_firmware(fw: &req->firmware, name: fw_name, device: rtwdev->dev);
1474
1475 complete_all(&req->completion);
1476
1477 return ret;
1478}
1479
1480void rtw89_load_firmware_work(struct work_struct *work)
1481{
1482 struct rtw89_dev *rtwdev =
1483 container_of(work, struct rtw89_dev, load_firmware_work);
1484 const struct rtw89_chip_info *chip = rtwdev->chip;
1485 char fw_name[64];
1486
1487 rtw89_fw_get_filename(buf: fw_name, size: sizeof(fw_name),
1488 fw_basename: chip->fw_basename, fw_format: rtwdev->fw.fw_format);
1489
1490 rtw89_load_firmware_req(rtwdev, req: &rtwdev->fw.req, fw_name, nowarn: false);
1491}
1492
1493static void rtw89_free_phy_tbl_from_elm(struct rtw89_phy_table *tbl)
1494{
1495 if (!tbl)
1496 return;
1497
1498 kfree(objp: tbl->regs);
1499 kfree(objp: tbl);
1500}
1501
1502static void rtw89_unload_firmware_elements(struct rtw89_dev *rtwdev)
1503{
1504 struct rtw89_fw_elm_info *elm_info = &rtwdev->fw.elm_info;
1505 int i;
1506
1507 rtw89_free_phy_tbl_from_elm(tbl: elm_info->bb_tbl);
1508 rtw89_free_phy_tbl_from_elm(tbl: elm_info->bb_gain);
1509 for (i = 0; i < ARRAY_SIZE(elm_info->rf_radio); i++)
1510 rtw89_free_phy_tbl_from_elm(tbl: elm_info->rf_radio[i]);
1511 rtw89_free_phy_tbl_from_elm(tbl: elm_info->rf_nctl);
1512
1513 kfree(objp: elm_info->txpwr_trk);
1514 kfree(objp: elm_info->rfk_log_fmt);
1515}
1516
1517void rtw89_unload_firmware(struct rtw89_dev *rtwdev)
1518{
1519 struct rtw89_fw_info *fw = &rtwdev->fw;
1520
1521 cancel_work_sync(work: &rtwdev->load_firmware_work);
1522
1523 if (fw->req.firmware) {
1524 release_firmware(fw: fw->req.firmware);
1525
1526 /* assign NULL back in case rtw89_free_ieee80211_hw()
1527 * try to release the same one again.
1528 */
1529 fw->req.firmware = NULL;
1530 }
1531
1532 kfree(objp: fw->log.fmts);
1533 rtw89_unload_firmware_elements(rtwdev);
1534}
1535
1536static u32 rtw89_fw_log_get_fmt_idx(struct rtw89_dev *rtwdev, u32 fmt_id)
1537{
1538 struct rtw89_fw_log *fw_log = &rtwdev->fw.log;
1539 u32 i;
1540
1541 if (fmt_id > fw_log->last_fmt_id)
1542 return 0;
1543
1544 for (i = 0; i < fw_log->fmt_count; i++) {
1545 if (le32_to_cpu(fw_log->fmt_ids[i]) == fmt_id)
1546 return i;
1547 }
1548 return 0;
1549}
1550
1551static int rtw89_fw_log_create_fmts_dict(struct rtw89_dev *rtwdev)
1552{
1553 struct rtw89_fw_log *log = &rtwdev->fw.log;
1554 const struct rtw89_fw_logsuit_hdr *suit_hdr;
1555 struct rtw89_fw_suit *suit = &log->suit;
1556 const void *fmts_ptr, *fmts_end_ptr;
1557 u32 fmt_count;
1558 int i;
1559
1560 suit_hdr = (const struct rtw89_fw_logsuit_hdr *)suit->data;
1561 fmt_count = le32_to_cpu(suit_hdr->count);
1562 log->fmt_ids = suit_hdr->ids;
1563 fmts_ptr = &suit_hdr->ids[fmt_count];
1564 fmts_end_ptr = suit->data + suit->size;
1565 log->fmts = kcalloc(n: fmt_count, size: sizeof(char *), GFP_KERNEL);
1566 if (!log->fmts)
1567 return -ENOMEM;
1568
1569 for (i = 0; i < fmt_count; i++) {
1570 fmts_ptr = memchr_inv(p: fmts_ptr, c: 0, size: fmts_end_ptr - fmts_ptr);
1571 if (!fmts_ptr)
1572 break;
1573
1574 (*log->fmts)[i] = fmts_ptr;
1575 log->last_fmt_id = le32_to_cpu(log->fmt_ids[i]);
1576 log->fmt_count++;
1577 fmts_ptr += strlen(fmts_ptr);
1578 }
1579
1580 return 0;
1581}
1582
1583int rtw89_fw_log_prepare(struct rtw89_dev *rtwdev)
1584{
1585 struct rtw89_fw_log *log = &rtwdev->fw.log;
1586 struct rtw89_fw_suit *suit = &log->suit;
1587
1588 if (!suit || !suit->data) {
1589 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "no log format file\n");
1590 return -EINVAL;
1591 }
1592 if (log->fmts)
1593 return 0;
1594
1595 return rtw89_fw_log_create_fmts_dict(rtwdev);
1596}
1597
1598static void rtw89_fw_log_dump_data(struct rtw89_dev *rtwdev,
1599 const struct rtw89_fw_c2h_log_fmt *log_fmt,
1600 u32 fmt_idx, u8 para_int, bool raw_data)
1601{
1602 const char *(*fmts)[] = rtwdev->fw.log.fmts;
1603 char str_buf[RTW89_C2H_FW_LOG_STR_BUF_SIZE];
1604 u32 args[RTW89_C2H_FW_LOG_MAX_PARA_NUM] = {0};
1605 int i;
1606
1607 if (log_fmt->argc > RTW89_C2H_FW_LOG_MAX_PARA_NUM) {
1608 rtw89_warn(rtwdev, "C2H log: Arg count is unexpected %d\n",
1609 log_fmt->argc);
1610 return;
1611 }
1612
1613 if (para_int)
1614 for (i = 0 ; i < log_fmt->argc; i++)
1615 args[i] = le32_to_cpu(log_fmt->u.argv[i]);
1616
1617 if (raw_data) {
1618 if (para_int)
1619 snprintf(buf: str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE,
1620 fmt: "fw_enc(%d, %d, %d) %*ph", le32_to_cpu(log_fmt->fmt_id),
1621 para_int, log_fmt->argc, (int)sizeof(args), args);
1622 else
1623 snprintf(buf: str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE,
1624 fmt: "fw_enc(%d, %d, %d, %s)", le32_to_cpu(log_fmt->fmt_id),
1625 para_int, log_fmt->argc, log_fmt->u.raw);
1626 } else {
1627 snprintf(buf: str_buf, RTW89_C2H_FW_LOG_STR_BUF_SIZE, fmt: (*fmts)[fmt_idx],
1628 args[0x0], args[0x1], args[0x2], args[0x3], args[0x4],
1629 args[0x5], args[0x6], args[0x7], args[0x8], args[0x9],
1630 args[0xa], args[0xb], args[0xc], args[0xd], args[0xe],
1631 args[0xf]);
1632 }
1633
1634 rtw89_info(rtwdev, "C2H log: %s", str_buf);
1635}
1636
1637void rtw89_fw_log_dump(struct rtw89_dev *rtwdev, u8 *buf, u32 len)
1638{
1639 const struct rtw89_fw_c2h_log_fmt *log_fmt;
1640 u8 para_int;
1641 u32 fmt_idx;
1642
1643 if (len < RTW89_C2H_HEADER_LEN) {
1644 rtw89_err(rtwdev, "c2h log length is wrong!\n");
1645 return;
1646 }
1647
1648 buf += RTW89_C2H_HEADER_LEN;
1649 len -= RTW89_C2H_HEADER_LEN;
1650 log_fmt = (const struct rtw89_fw_c2h_log_fmt *)buf;
1651
1652 if (len < RTW89_C2H_FW_FORMATTED_LOG_MIN_LEN)
1653 goto plain_log;
1654
1655 if (log_fmt->signature != cpu_to_le16(RTW89_C2H_FW_LOG_SIGNATURE))
1656 goto plain_log;
1657
1658 if (!rtwdev->fw.log.fmts)
1659 return;
1660
1661 para_int = u8_get_bits(v: log_fmt->feature, RTW89_C2H_FW_LOG_FEATURE_PARA_INT);
1662 fmt_idx = rtw89_fw_log_get_fmt_idx(rtwdev, le32_to_cpu(log_fmt->fmt_id));
1663
1664 if (!para_int && log_fmt->argc != 0 && fmt_idx != 0)
1665 rtw89_info(rtwdev, "C2H log: %s%s",
1666 (*rtwdev->fw.log.fmts)[fmt_idx], log_fmt->u.raw);
1667 else if (fmt_idx != 0 && para_int)
1668 rtw89_fw_log_dump_data(rtwdev, log_fmt, fmt_idx, para_int, raw_data: false);
1669 else
1670 rtw89_fw_log_dump_data(rtwdev, log_fmt, fmt_idx, para_int, raw_data: true);
1671 return;
1672
1673plain_log:
1674 rtw89_info(rtwdev, "C2H log: %.*s", len, buf);
1675
1676}
1677
1678#define H2C_CAM_LEN 60
1679int rtw89_fw_h2c_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
1680 struct rtw89_sta *rtwsta, const u8 *scan_mac_addr)
1681{
1682 struct sk_buff *skb;
1683 int ret;
1684
1685 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CAM_LEN);
1686 if (!skb) {
1687 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
1688 return -ENOMEM;
1689 }
1690 skb_put(skb, H2C_CAM_LEN);
1691 rtw89_cam_fill_addr_cam_info(rtwdev, vif: rtwvif, rtwsta, scan_mac_addr, cmd: skb->data);
1692 rtw89_cam_fill_bssid_cam_info(rtwdev, rtwvif, rtwsta, cmd: skb->data);
1693
1694 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
1695 H2C_CAT_MAC,
1696 H2C_CL_MAC_ADDR_CAM_UPDATE,
1697 H2C_FUNC_MAC_ADDR_CAM_UPD, rack: 0, dack: 1,
1698 H2C_CAM_LEN);
1699
1700 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
1701 if (ret) {
1702 rtw89_err(rtwdev, "failed to send h2c\n");
1703 goto fail;
1704 }
1705
1706 return 0;
1707fail:
1708 dev_kfree_skb_any(skb);
1709
1710 return ret;
1711}
1712
1713#define H2C_DCTL_SEC_CAM_LEN 68
1714int rtw89_fw_h2c_dctl_sec_cam_v1(struct rtw89_dev *rtwdev,
1715 struct rtw89_vif *rtwvif,
1716 struct rtw89_sta *rtwsta)
1717{
1718 struct sk_buff *skb;
1719 int ret;
1720
1721 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DCTL_SEC_CAM_LEN);
1722 if (!skb) {
1723 rtw89_err(rtwdev, "failed to alloc skb for dctl sec cam\n");
1724 return -ENOMEM;
1725 }
1726 skb_put(skb, H2C_DCTL_SEC_CAM_LEN);
1727
1728 rtw89_cam_fill_dctl_sec_cam_info_v1(rtwdev, rtwvif, rtwsta, cmd: skb->data);
1729
1730 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
1731 H2C_CAT_MAC,
1732 H2C_CL_MAC_FR_EXCHG,
1733 H2C_FUNC_MAC_DCTLINFO_UD_V1, rack: 0, dack: 0,
1734 H2C_DCTL_SEC_CAM_LEN);
1735
1736 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
1737 if (ret) {
1738 rtw89_err(rtwdev, "failed to send h2c\n");
1739 goto fail;
1740 }
1741
1742 return 0;
1743fail:
1744 dev_kfree_skb_any(skb);
1745
1746 return ret;
1747}
1748EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1);
1749
1750int rtw89_fw_h2c_dctl_sec_cam_v2(struct rtw89_dev *rtwdev,
1751 struct rtw89_vif *rtwvif,
1752 struct rtw89_sta *rtwsta)
1753{
1754 struct rtw89_h2c_dctlinfo_ud_v2 *h2c;
1755 u32 len = sizeof(*h2c);
1756 struct sk_buff *skb;
1757 int ret;
1758
1759 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
1760 if (!skb) {
1761 rtw89_err(rtwdev, "failed to alloc skb for dctl sec cam\n");
1762 return -ENOMEM;
1763 }
1764 skb_put(skb, len);
1765 h2c = (struct rtw89_h2c_dctlinfo_ud_v2 *)skb->data;
1766
1767 rtw89_cam_fill_dctl_sec_cam_info_v2(rtwdev, rtwvif, rtwsta, h2c);
1768
1769 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
1770 H2C_CAT_MAC,
1771 H2C_CL_MAC_FR_EXCHG,
1772 H2C_FUNC_MAC_DCTLINFO_UD_V2, rack: 0, dack: 0,
1773 len);
1774
1775 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
1776 if (ret) {
1777 rtw89_err(rtwdev, "failed to send h2c\n");
1778 goto fail;
1779 }
1780
1781 return 0;
1782fail:
1783 dev_kfree_skb_any(skb);
1784
1785 return ret;
1786}
1787EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2);
1788
1789int rtw89_fw_h2c_default_dmac_tbl_v2(struct rtw89_dev *rtwdev,
1790 struct rtw89_vif *rtwvif,
1791 struct rtw89_sta *rtwsta)
1792{
1793 u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
1794 struct rtw89_h2c_dctlinfo_ud_v2 *h2c;
1795 u32 len = sizeof(*h2c);
1796 struct sk_buff *skb;
1797 int ret;
1798
1799 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
1800 if (!skb) {
1801 rtw89_err(rtwdev, "failed to alloc skb for dctl v2\n");
1802 return -ENOMEM;
1803 }
1804 skb_put(skb, len);
1805 h2c = (struct rtw89_h2c_dctlinfo_ud_v2 *)skb->data;
1806
1807 h2c->c0 = le32_encode_bits(v: mac_id, DCTLINFO_V2_C0_MACID) |
1808 le32_encode_bits(v: 1, DCTLINFO_V2_C0_OP);
1809
1810 h2c->m0 = cpu_to_le32(DCTLINFO_V2_W0_ALL);
1811 h2c->m1 = cpu_to_le32(DCTLINFO_V2_W1_ALL);
1812 h2c->m2 = cpu_to_le32(DCTLINFO_V2_W2_ALL);
1813 h2c->m3 = cpu_to_le32(DCTLINFO_V2_W3_ALL);
1814 h2c->m4 = cpu_to_le32(DCTLINFO_V2_W4_ALL);
1815 h2c->m5 = cpu_to_le32(DCTLINFO_V2_W5_ALL);
1816 h2c->m6 = cpu_to_le32(DCTLINFO_V2_W6_ALL);
1817 h2c->m7 = cpu_to_le32(DCTLINFO_V2_W7_ALL);
1818 h2c->m8 = cpu_to_le32(DCTLINFO_V2_W8_ALL);
1819 h2c->m9 = cpu_to_le32(DCTLINFO_V2_W9_ALL);
1820 h2c->m10 = cpu_to_le32(DCTLINFO_V2_W10_ALL);
1821 h2c->m11 = cpu_to_le32(DCTLINFO_V2_W11_ALL);
1822 h2c->m12 = cpu_to_le32(DCTLINFO_V2_W12_ALL);
1823
1824 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
1825 H2C_CAT_MAC,
1826 H2C_CL_MAC_FR_EXCHG,
1827 H2C_FUNC_MAC_DCTLINFO_UD_V2, rack: 0, dack: 0,
1828 len);
1829
1830 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
1831 if (ret) {
1832 rtw89_err(rtwdev, "failed to send h2c\n");
1833 goto fail;
1834 }
1835
1836 return 0;
1837fail:
1838 dev_kfree_skb_any(skb);
1839
1840 return ret;
1841}
1842EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2);
1843
1844int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
1845 bool valid, struct ieee80211_ampdu_params *params)
1846{
1847 const struct rtw89_chip_info *chip = rtwdev->chip;
1848 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
1849 struct rtw89_h2c_ba_cam *h2c;
1850 u8 macid = rtwsta->mac_id;
1851 u32 len = sizeof(*h2c);
1852 struct sk_buff *skb;
1853 u8 entry_idx;
1854 int ret;
1855
1856 ret = valid ?
1857 rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, tid: params->tid, cam_idx: &entry_idx) :
1858 rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, tid: params->tid, cam_idx: &entry_idx);
1859 if (ret) {
1860 /* it still works even if we don't have static BA CAM, because
1861 * hardware can create dynamic BA CAM automatically.
1862 */
1863 rtw89_debug(rtwdev, mask: RTW89_DBG_TXRX,
1864 fmt: "failed to %s entry tid=%d for h2c ba cam\n",
1865 valid ? "alloc" : "free", params->tid);
1866 return 0;
1867 }
1868
1869 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
1870 if (!skb) {
1871 rtw89_err(rtwdev, "failed to alloc skb for h2c ba cam\n");
1872 return -ENOMEM;
1873 }
1874 skb_put(skb, len);
1875 h2c = (struct rtw89_h2c_ba_cam *)skb->data;
1876
1877 h2c->w0 = le32_encode_bits(v: macid, RTW89_H2C_BA_CAM_W0_MACID);
1878 if (chip->bacam_ver == RTW89_BACAM_V0_EXT)
1879 h2c->w1 |= le32_encode_bits(v: entry_idx, RTW89_H2C_BA_CAM_W1_ENTRY_IDX_V1);
1880 else
1881 h2c->w0 |= le32_encode_bits(v: entry_idx, RTW89_H2C_BA_CAM_W0_ENTRY_IDX);
1882 if (!valid)
1883 goto end;
1884 h2c->w0 |= le32_encode_bits(v: valid, RTW89_H2C_BA_CAM_W0_VALID) |
1885 le32_encode_bits(v: params->tid, RTW89_H2C_BA_CAM_W0_TID);
1886 if (params->buf_size > 64)
1887 h2c->w0 |= le32_encode_bits(v: 4, RTW89_H2C_BA_CAM_W0_BMAP_SIZE);
1888 else
1889 h2c->w0 |= le32_encode_bits(v: 0, RTW89_H2C_BA_CAM_W0_BMAP_SIZE);
1890 /* If init req is set, hw will set the ssn */
1891 h2c->w0 |= le32_encode_bits(v: 1, RTW89_H2C_BA_CAM_W0_INIT_REQ) |
1892 le32_encode_bits(v: params->ssn, RTW89_H2C_BA_CAM_W0_SSN);
1893
1894 if (chip->bacam_ver == RTW89_BACAM_V0_EXT) {
1895 h2c->w1 |= le32_encode_bits(v: 1, RTW89_H2C_BA_CAM_W1_STD_EN) |
1896 le32_encode_bits(v: rtwvif->mac_idx, RTW89_H2C_BA_CAM_W1_BAND);
1897 }
1898
1899end:
1900 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
1901 H2C_CAT_MAC,
1902 H2C_CL_BA_CAM,
1903 H2C_FUNC_MAC_BA_CAM, rack: 0, dack: 1,
1904 len);
1905
1906 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
1907 if (ret) {
1908 rtw89_err(rtwdev, "failed to send h2c\n");
1909 goto fail;
1910 }
1911
1912 return 0;
1913fail:
1914 dev_kfree_skb_any(skb);
1915
1916 return ret;
1917}
1918EXPORT_SYMBOL(rtw89_fw_h2c_ba_cam);
1919
1920static int rtw89_fw_h2c_init_ba_cam_v0_ext(struct rtw89_dev *rtwdev,
1921 u8 entry_idx, u8 uid)
1922{
1923 struct rtw89_h2c_ba_cam *h2c;
1924 u32 len = sizeof(*h2c);
1925 struct sk_buff *skb;
1926 int ret;
1927
1928 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
1929 if (!skb) {
1930 rtw89_err(rtwdev, "failed to alloc skb for dynamic h2c ba cam\n");
1931 return -ENOMEM;
1932 }
1933 skb_put(skb, len);
1934 h2c = (struct rtw89_h2c_ba_cam *)skb->data;
1935
1936 h2c->w0 = le32_encode_bits(v: 1, RTW89_H2C_BA_CAM_W0_VALID);
1937 h2c->w1 = le32_encode_bits(v: entry_idx, RTW89_H2C_BA_CAM_W1_ENTRY_IDX_V1) |
1938 le32_encode_bits(v: uid, RTW89_H2C_BA_CAM_W1_UID) |
1939 le32_encode_bits(v: 0, RTW89_H2C_BA_CAM_W1_BAND) |
1940 le32_encode_bits(v: 0, RTW89_H2C_BA_CAM_W1_STD_EN);
1941
1942 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
1943 H2C_CAT_MAC,
1944 H2C_CL_BA_CAM,
1945 H2C_FUNC_MAC_BA_CAM, rack: 0, dack: 1,
1946 len);
1947
1948 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
1949 if (ret) {
1950 rtw89_err(rtwdev, "failed to send h2c\n");
1951 goto fail;
1952 }
1953
1954 return 0;
1955fail:
1956 dev_kfree_skb_any(skb);
1957
1958 return ret;
1959}
1960
1961void rtw89_fw_h2c_init_dynamic_ba_cam_v0_ext(struct rtw89_dev *rtwdev)
1962{
1963 const struct rtw89_chip_info *chip = rtwdev->chip;
1964 u8 entry_idx = chip->bacam_num;
1965 u8 uid = 0;
1966 int i;
1967
1968 for (i = 0; i < chip->bacam_dynamic_num; i++) {
1969 rtw89_fw_h2c_init_ba_cam_v0_ext(rtwdev, entry_idx, uid);
1970 entry_idx++;
1971 uid++;
1972 }
1973}
1974
1975int rtw89_fw_h2c_ba_cam_v1(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
1976 bool valid, struct ieee80211_ampdu_params *params)
1977{
1978 const struct rtw89_chip_info *chip = rtwdev->chip;
1979 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
1980 struct rtw89_h2c_ba_cam_v1 *h2c;
1981 u8 macid = rtwsta->mac_id;
1982 u32 len = sizeof(*h2c);
1983 struct sk_buff *skb;
1984 u8 entry_idx;
1985 u8 bmap_size;
1986 int ret;
1987
1988 ret = valid ?
1989 rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, tid: params->tid, cam_idx: &entry_idx) :
1990 rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, tid: params->tid, cam_idx: &entry_idx);
1991 if (ret) {
1992 /* it still works even if we don't have static BA CAM, because
1993 * hardware can create dynamic BA CAM automatically.
1994 */
1995 rtw89_debug(rtwdev, mask: RTW89_DBG_TXRX,
1996 fmt: "failed to %s entry tid=%d for h2c ba cam\n",
1997 valid ? "alloc" : "free", params->tid);
1998 return 0;
1999 }
2000
2001 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
2002 if (!skb) {
2003 rtw89_err(rtwdev, "failed to alloc skb for h2c ba cam\n");
2004 return -ENOMEM;
2005 }
2006 skb_put(skb, len);
2007 h2c = (struct rtw89_h2c_ba_cam_v1 *)skb->data;
2008
2009 if (params->buf_size > 512)
2010 bmap_size = 10;
2011 else if (params->buf_size > 256)
2012 bmap_size = 8;
2013 else if (params->buf_size > 64)
2014 bmap_size = 4;
2015 else
2016 bmap_size = 0;
2017
2018 h2c->w0 = le32_encode_bits(v: valid, RTW89_H2C_BA_CAM_V1_W0_VALID) |
2019 le32_encode_bits(v: 1, RTW89_H2C_BA_CAM_V1_W0_INIT_REQ) |
2020 le32_encode_bits(v: macid, RTW89_H2C_BA_CAM_V1_W0_MACID_MASK) |
2021 le32_encode_bits(v: params->tid, RTW89_H2C_BA_CAM_V1_W0_TID_MASK) |
2022 le32_encode_bits(v: bmap_size, RTW89_H2C_BA_CAM_V1_W0_BMAP_SIZE_MASK) |
2023 le32_encode_bits(v: params->ssn, RTW89_H2C_BA_CAM_V1_W0_SSN_MASK);
2024
2025 entry_idx += chip->bacam_dynamic_num; /* std entry right after dynamic ones */
2026 h2c->w1 = le32_encode_bits(v: entry_idx, RTW89_H2C_BA_CAM_V1_W1_ENTRY_IDX_MASK) |
2027 le32_encode_bits(v: 1, RTW89_H2C_BA_CAM_V1_W1_STD_ENTRY_EN) |
2028 le32_encode_bits(v: !!rtwvif->mac_idx, RTW89_H2C_BA_CAM_V1_W1_BAND_SEL);
2029
2030 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2031 H2C_CAT_MAC,
2032 H2C_CL_BA_CAM,
2033 H2C_FUNC_MAC_BA_CAM_V1, rack: 0, dack: 1,
2034 len);
2035
2036 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2037 if (ret) {
2038 rtw89_err(rtwdev, "failed to send h2c\n");
2039 goto fail;
2040 }
2041
2042 return 0;
2043fail:
2044 dev_kfree_skb_any(skb);
2045
2046 return ret;
2047}
2048EXPORT_SYMBOL(rtw89_fw_h2c_ba_cam_v1);
2049
2050int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users,
2051 u8 offset, u8 mac_idx)
2052{
2053 struct rtw89_h2c_ba_cam_init *h2c;
2054 u32 len = sizeof(*h2c);
2055 struct sk_buff *skb;
2056 int ret;
2057
2058 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
2059 if (!skb) {
2060 rtw89_err(rtwdev, "failed to alloc skb for h2c ba cam init\n");
2061 return -ENOMEM;
2062 }
2063 skb_put(skb, len);
2064 h2c = (struct rtw89_h2c_ba_cam_init *)skb->data;
2065
2066 h2c->w0 = le32_encode_bits(v: users, RTW89_H2C_BA_CAM_INIT_USERS_MASK) |
2067 le32_encode_bits(v: offset, RTW89_H2C_BA_CAM_INIT_OFFSET_MASK) |
2068 le32_encode_bits(v: mac_idx, RTW89_H2C_BA_CAM_INIT_BAND_SEL);
2069
2070 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2071 H2C_CAT_MAC,
2072 H2C_CL_BA_CAM,
2073 H2C_FUNC_MAC_BA_CAM_INIT, rack: 0, dack: 1,
2074 len);
2075
2076 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2077 if (ret) {
2078 rtw89_err(rtwdev, "failed to send h2c\n");
2079 goto fail;
2080 }
2081
2082 return 0;
2083fail:
2084 dev_kfree_skb_any(skb);
2085
2086 return ret;
2087}
2088
2089#define H2C_LOG_CFG_LEN 12
2090int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable)
2091{
2092 struct sk_buff *skb;
2093 u32 comp = 0;
2094 int ret;
2095
2096 if (enable)
2097 comp = BIT(RTW89_FW_LOG_COMP_INIT) | BIT(RTW89_FW_LOG_COMP_TASK) |
2098 BIT(RTW89_FW_LOG_COMP_PS) | BIT(RTW89_FW_LOG_COMP_ERROR) |
2099 BIT(RTW89_FW_LOG_COMP_SCAN);
2100
2101 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LOG_CFG_LEN);
2102 if (!skb) {
2103 rtw89_err(rtwdev, "failed to alloc skb for fw log cfg\n");
2104 return -ENOMEM;
2105 }
2106
2107 skb_put(skb, H2C_LOG_CFG_LEN);
2108 SET_LOG_CFG_LEVEL(h2c: skb->data, val: RTW89_FW_LOG_LEVEL_LOUD);
2109 SET_LOG_CFG_PATH(h2c: skb->data, BIT(RTW89_FW_LOG_LEVEL_C2H));
2110 SET_LOG_CFG_COMP(h2c: skb->data, val: comp);
2111 SET_LOG_CFG_COMP_EXT(h2c: skb->data, val: 0);
2112
2113 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2114 H2C_CAT_MAC,
2115 H2C_CL_FW_INFO,
2116 H2C_FUNC_LOG_CFG, rack: 0, dack: 0,
2117 H2C_LOG_CFG_LEN);
2118
2119 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2120 if (ret) {
2121 rtw89_err(rtwdev, "failed to send h2c\n");
2122 goto fail;
2123 }
2124
2125 return 0;
2126fail:
2127 dev_kfree_skb_any(skb);
2128
2129 return ret;
2130}
2131
2132static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
2133 struct rtw89_vif *rtwvif,
2134 enum rtw89_fw_pkt_ofld_type type,
2135 u8 *id)
2136{
2137 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
2138 struct rtw89_pktofld_info *info;
2139 struct sk_buff *skb;
2140 int ret;
2141
2142 info = kzalloc(size: sizeof(*info), GFP_KERNEL);
2143 if (!info)
2144 return -ENOMEM;
2145
2146 switch (type) {
2147 case RTW89_PKT_OFLD_TYPE_PS_POLL:
2148 skb = ieee80211_pspoll_get(hw: rtwdev->hw, vif);
2149 break;
2150 case RTW89_PKT_OFLD_TYPE_PROBE_RSP:
2151 skb = ieee80211_proberesp_get(hw: rtwdev->hw, vif);
2152 break;
2153 case RTW89_PKT_OFLD_TYPE_NULL_DATA:
2154 skb = ieee80211_nullfunc_get(hw: rtwdev->hw, vif, link_id: -1, qos_ok: false);
2155 break;
2156 case RTW89_PKT_OFLD_TYPE_QOS_NULL:
2157 skb = ieee80211_nullfunc_get(hw: rtwdev->hw, vif, link_id: -1, qos_ok: true);
2158 break;
2159 default:
2160 goto err;
2161 }
2162
2163 if (!skb)
2164 goto err;
2165
2166 ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, id: &info->id, skb_ofld: skb);
2167 kfree_skb(skb);
2168
2169 if (ret)
2170 goto err;
2171
2172 list_add_tail(new: &info->list, head: &rtwvif->general_pkt_list);
2173 *id = info->id;
2174 return 0;
2175
2176err:
2177 kfree(objp: info);
2178 return -ENOMEM;
2179}
2180
2181void rtw89_fw_release_general_pkt_list_vif(struct rtw89_dev *rtwdev,
2182 struct rtw89_vif *rtwvif, bool notify_fw)
2183{
2184 struct list_head *pkt_list = &rtwvif->general_pkt_list;
2185 struct rtw89_pktofld_info *info, *tmp;
2186
2187 list_for_each_entry_safe(info, tmp, pkt_list, list) {
2188 if (notify_fw)
2189 rtw89_fw_h2c_del_pkt_offload(rtwdev, id: info->id);
2190 else
2191 rtw89_core_release_bit_map(addr: rtwdev->pkt_offload, bit: info->id);
2192 list_del(entry: &info->list);
2193 kfree(objp: info);
2194 }
2195}
2196
2197void rtw89_fw_release_general_pkt_list(struct rtw89_dev *rtwdev, bool notify_fw)
2198{
2199 struct rtw89_vif *rtwvif;
2200
2201 rtw89_for_each_rtwvif(rtwdev, rtwvif)
2202 rtw89_fw_release_general_pkt_list_vif(rtwdev, rtwvif, notify_fw);
2203}
2204
2205#define H2C_GENERAL_PKT_LEN 6
2206#define H2C_GENERAL_PKT_ID_UND 0xff
2207int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev,
2208 struct rtw89_vif *rtwvif, u8 macid)
2209{
2210 u8 pkt_id_ps_poll = H2C_GENERAL_PKT_ID_UND;
2211 u8 pkt_id_null = H2C_GENERAL_PKT_ID_UND;
2212 u8 pkt_id_qos_null = H2C_GENERAL_PKT_ID_UND;
2213 struct sk_buff *skb;
2214 int ret;
2215
2216 rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
2217 type: RTW89_PKT_OFLD_TYPE_PS_POLL, id: &pkt_id_ps_poll);
2218 rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
2219 type: RTW89_PKT_OFLD_TYPE_NULL_DATA, id: &pkt_id_null);
2220 rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
2221 type: RTW89_PKT_OFLD_TYPE_QOS_NULL, id: &pkt_id_qos_null);
2222
2223 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_GENERAL_PKT_LEN);
2224 if (!skb) {
2225 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
2226 return -ENOMEM;
2227 }
2228 skb_put(skb, H2C_GENERAL_PKT_LEN);
2229 SET_GENERAL_PKT_MACID(h2c: skb->data, val: macid);
2230 SET_GENERAL_PKT_PROBRSP_ID(h2c: skb->data, H2C_GENERAL_PKT_ID_UND);
2231 SET_GENERAL_PKT_PSPOLL_ID(h2c: skb->data, val: pkt_id_ps_poll);
2232 SET_GENERAL_PKT_NULL_ID(h2c: skb->data, val: pkt_id_null);
2233 SET_GENERAL_PKT_QOS_NULL_ID(h2c: skb->data, val: pkt_id_qos_null);
2234 SET_GENERAL_PKT_CTS2SELF_ID(h2c: skb->data, H2C_GENERAL_PKT_ID_UND);
2235
2236 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2237 H2C_CAT_MAC,
2238 H2C_CL_FW_INFO,
2239 H2C_FUNC_MAC_GENERAL_PKT, rack: 0, dack: 1,
2240 H2C_GENERAL_PKT_LEN);
2241
2242 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2243 if (ret) {
2244 rtw89_err(rtwdev, "failed to send h2c\n");
2245 goto fail;
2246 }
2247
2248 return 0;
2249fail:
2250 dev_kfree_skb_any(skb);
2251
2252 return ret;
2253}
2254
2255#define H2C_LPS_PARM_LEN 8
2256int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
2257 struct rtw89_lps_parm *lps_param)
2258{
2259 struct sk_buff *skb;
2260 int ret;
2261
2262 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LPS_PARM_LEN);
2263 if (!skb) {
2264 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
2265 return -ENOMEM;
2266 }
2267 skb_put(skb, H2C_LPS_PARM_LEN);
2268
2269 SET_LPS_PARM_MACID(h2c: skb->data, val: lps_param->macid);
2270 SET_LPS_PARM_PSMODE(h2c: skb->data, val: lps_param->psmode);
2271 SET_LPS_PARM_LASTRPWM(h2c: skb->data, val: lps_param->lastrpwm);
2272 SET_LPS_PARM_RLBM(h2c: skb->data, val: 1);
2273 SET_LPS_PARM_SMARTPS(h2c: skb->data, val: 1);
2274 SET_LPS_PARM_AWAKEINTERVAL(h2c: skb->data, val: 1);
2275 SET_LPS_PARM_VOUAPSD(h2c: skb->data, val: 0);
2276 SET_LPS_PARM_VIUAPSD(h2c: skb->data, val: 0);
2277 SET_LPS_PARM_BEUAPSD(h2c: skb->data, val: 0);
2278 SET_LPS_PARM_BKUAPSD(h2c: skb->data, val: 0);
2279
2280 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2281 H2C_CAT_MAC,
2282 H2C_CL_MAC_PS,
2283 H2C_FUNC_MAC_LPS_PARM, rack: 0, dack: 1,
2284 H2C_LPS_PARM_LEN);
2285
2286 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2287 if (ret) {
2288 rtw89_err(rtwdev, "failed to send h2c\n");
2289 goto fail;
2290 }
2291
2292 return 0;
2293fail:
2294 dev_kfree_skb_any(skb);
2295
2296 return ret;
2297}
2298
2299int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
2300{
2301 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
2302 idx: rtwvif->sub_entity_idx);
2303 const struct rtw89_chip_info *chip = rtwdev->chip;
2304 struct rtw89_h2c_lps_ch_info *h2c;
2305 u32 len = sizeof(*h2c);
2306 struct sk_buff *skb;
2307 int ret;
2308
2309 if (chip->chip_gen != RTW89_CHIP_BE)
2310 return 0;
2311
2312 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
2313 if (!skb) {
2314 rtw89_err(rtwdev, "failed to alloc skb for h2c lps_ch_info\n");
2315 return -ENOMEM;
2316 }
2317 skb_put(skb, len);
2318 h2c = (struct rtw89_h2c_lps_ch_info *)skb->data;
2319
2320 h2c->info[0].central_ch = chan->channel;
2321 h2c->info[0].pri_ch = chan->primary_channel;
2322 h2c->info[0].band = chan->band_type;
2323 h2c->info[0].bw = chan->band_width;
2324 h2c->mlo_dbcc_mode_lps = cpu_to_le32(MLO_2_PLUS_0_1RF);
2325
2326 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2327 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM,
2328 H2C_FUNC_FW_LPS_CH_INFO, rack: 0, dack: 0, len);
2329
2330 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2331 if (ret) {
2332 rtw89_err(rtwdev, "failed to send h2c\n");
2333 goto fail;
2334 }
2335
2336 return 0;
2337fail:
2338 dev_kfree_skb_any(skb);
2339
2340 return ret;
2341}
2342
2343#define H2C_P2P_ACT_LEN 20
2344int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
2345 struct ieee80211_p2p_noa_desc *desc,
2346 u8 act, u8 noa_id)
2347{
2348 struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
2349 bool p2p_type_gc = rtwvif->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
2350 u8 ctwindow_oppps = vif->bss_conf.p2p_noa_attr.oppps_ctwindow;
2351 struct sk_buff *skb;
2352 u8 *cmd;
2353 int ret;
2354
2355 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_P2P_ACT_LEN);
2356 if (!skb) {
2357 rtw89_err(rtwdev, "failed to alloc skb for h2c p2p act\n");
2358 return -ENOMEM;
2359 }
2360 skb_put(skb, H2C_P2P_ACT_LEN);
2361 cmd = skb->data;
2362
2363 RTW89_SET_FWCMD_P2P_MACID(cmd, val: rtwvif->mac_id);
2364 RTW89_SET_FWCMD_P2P_P2PID(cmd, val: 0);
2365 RTW89_SET_FWCMD_P2P_NOAID(cmd, val: noa_id);
2366 RTW89_SET_FWCMD_P2P_ACT(cmd, val: act);
2367 RTW89_SET_FWCMD_P2P_TYPE(cmd, val: p2p_type_gc);
2368 RTW89_SET_FWCMD_P2P_ALL_SLEP(cmd, val: 0);
2369 if (desc) {
2370 RTW89_SET_FWCMD_NOA_START_TIME(cmd, val: desc->start_time);
2371 RTW89_SET_FWCMD_NOA_INTERVAL(cmd, val: desc->interval);
2372 RTW89_SET_FWCMD_NOA_DURATION(cmd, val: desc->duration);
2373 RTW89_SET_FWCMD_NOA_COUNT(cmd, val: desc->count);
2374 RTW89_SET_FWCMD_NOA_CTWINDOW(cmd, val: ctwindow_oppps);
2375 }
2376
2377 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2378 H2C_CAT_MAC, H2C_CL_MAC_PS,
2379 H2C_FUNC_P2P_ACT, rack: 0, dack: 0,
2380 H2C_P2P_ACT_LEN);
2381
2382 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2383 if (ret) {
2384 rtw89_err(rtwdev, "failed to send h2c\n");
2385 goto fail;
2386 }
2387
2388 return 0;
2389fail:
2390 dev_kfree_skb_any(skb);
2391
2392 return ret;
2393}
2394
2395static void __rtw89_fw_h2c_set_tx_path(struct rtw89_dev *rtwdev,
2396 struct sk_buff *skb)
2397{
2398 const struct rtw89_chip_info *chip = rtwdev->chip;
2399 struct rtw89_hal *hal = &rtwdev->hal;
2400 u8 ntx_path;
2401 u8 map_b;
2402
2403 if (chip->rf_path_num == 1) {
2404 ntx_path = RF_A;
2405 map_b = 0;
2406 } else {
2407 ntx_path = hal->antenna_tx ? hal->antenna_tx : RF_B;
2408 map_b = hal->antenna_tx == RF_AB ? 1 : 0;
2409 }
2410
2411 SET_CMC_TBL_NTX_PATH_EN(table: skb->data, val: ntx_path);
2412 SET_CMC_TBL_PATH_MAP_A(table: skb->data, val: 0);
2413 SET_CMC_TBL_PATH_MAP_B(table: skb->data, val: map_b);
2414 SET_CMC_TBL_PATH_MAP_C(table: skb->data, val: 0);
2415 SET_CMC_TBL_PATH_MAP_D(table: skb->data, val: 0);
2416}
2417
2418#define H2C_CMC_TBL_LEN 68
2419int rtw89_fw_h2c_default_cmac_tbl(struct rtw89_dev *rtwdev,
2420 struct rtw89_vif *rtwvif,
2421 struct rtw89_sta *rtwsta)
2422{
2423 const struct rtw89_chip_info *chip = rtwdev->chip;
2424 u8 macid = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
2425 struct sk_buff *skb;
2426 int ret;
2427
2428 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
2429 if (!skb) {
2430 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
2431 return -ENOMEM;
2432 }
2433 skb_put(skb, H2C_CMC_TBL_LEN);
2434 SET_CTRL_INFO_MACID(table: skb->data, val: macid);
2435 SET_CTRL_INFO_OPERATION(table: skb->data, val: 1);
2436 if (chip->h2c_cctl_func_id == H2C_FUNC_MAC_CCTLINFO_UD) {
2437 SET_CMC_TBL_TXPWR_MODE(table: skb->data, val: 0);
2438 __rtw89_fw_h2c_set_tx_path(rtwdev, skb);
2439 SET_CMC_TBL_ANTSEL_A(table: skb->data, val: 0);
2440 SET_CMC_TBL_ANTSEL_B(table: skb->data, val: 0);
2441 SET_CMC_TBL_ANTSEL_C(table: skb->data, val: 0);
2442 SET_CMC_TBL_ANTSEL_D(table: skb->data, val: 0);
2443 }
2444 SET_CMC_TBL_DOPPLER_CTRL(table: skb->data, val: 0);
2445 SET_CMC_TBL_TXPWR_TOLERENCE(table: skb->data, val: 0);
2446 if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
2447 SET_CMC_TBL_DATA_DCM(table: skb->data, val: 0);
2448
2449 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2450 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
2451 func: chip->h2c_cctl_func_id, rack: 0, dack: 1,
2452 H2C_CMC_TBL_LEN);
2453
2454 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2455 if (ret) {
2456 rtw89_err(rtwdev, "failed to send h2c\n");
2457 goto fail;
2458 }
2459
2460 return 0;
2461fail:
2462 dev_kfree_skb_any(skb);
2463
2464 return ret;
2465}
2466EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl);
2467
2468int rtw89_fw_h2c_default_cmac_tbl_g7(struct rtw89_dev *rtwdev,
2469 struct rtw89_vif *rtwvif,
2470 struct rtw89_sta *rtwsta)
2471{
2472 u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
2473 struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
2474 u32 len = sizeof(*h2c);
2475 struct sk_buff *skb;
2476 int ret;
2477
2478 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
2479 if (!skb) {
2480 rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n");
2481 return -ENOMEM;
2482 }
2483 skb_put(skb, len);
2484 h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data;
2485
2486 h2c->c0 = le32_encode_bits(v: mac_id, CCTLINFO_G7_C0_MACID) |
2487 le32_encode_bits(v: 1, CCTLINFO_G7_C0_OP);
2488
2489 h2c->w0 = le32_encode_bits(v: 4, CCTLINFO_G7_W0_DATARATE);
2490 h2c->m0 = cpu_to_le32(CCTLINFO_G7_W0_ALL);
2491
2492 h2c->w1 = le32_encode_bits(v: 4, CCTLINFO_G7_W1_DATA_RTY_LOWEST_RATE) |
2493 le32_encode_bits(v: 0xa, CCTLINFO_G7_W1_RTSRATE) |
2494 le32_encode_bits(v: 4, CCTLINFO_G7_W1_RTS_RTY_LOWEST_RATE);
2495 h2c->m1 = cpu_to_le32(CCTLINFO_G7_W1_ALL);
2496
2497 h2c->m2 = cpu_to_le32(CCTLINFO_G7_W2_ALL);
2498
2499 h2c->m3 = cpu_to_le32(CCTLINFO_G7_W3_ALL);
2500
2501 h2c->w4 = le32_encode_bits(v: 0xFFFF, CCTLINFO_G7_W4_ACT_SUBCH_CBW);
2502 h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_ALL);
2503
2504 h2c->w5 = le32_encode_bits(v: 2, CCTLINFO_G7_W5_NOMINAL_PKT_PADDING0) |
2505 le32_encode_bits(v: 2, CCTLINFO_G7_W5_NOMINAL_PKT_PADDING1) |
2506 le32_encode_bits(v: 2, CCTLINFO_G7_W5_NOMINAL_PKT_PADDING2) |
2507 le32_encode_bits(v: 2, CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3) |
2508 le32_encode_bits(v: 2, CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4);
2509 h2c->m5 = cpu_to_le32(CCTLINFO_G7_W5_ALL);
2510
2511 h2c->w6 = le32_encode_bits(v: 0xb, CCTLINFO_G7_W6_RESP_REF_RATE);
2512 h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ALL);
2513
2514 h2c->w7 = le32_encode_bits(v: 1, CCTLINFO_G7_W7_NC) |
2515 le32_encode_bits(v: 1, CCTLINFO_G7_W7_NR) |
2516 le32_encode_bits(v: 1, CCTLINFO_G7_W7_CB) |
2517 le32_encode_bits(v: 0x1, CCTLINFO_G7_W7_CSI_PARA_EN) |
2518 le32_encode_bits(v: 0xb, CCTLINFO_G7_W7_CSI_FIX_RATE);
2519 h2c->m7 = cpu_to_le32(CCTLINFO_G7_W7_ALL);
2520
2521 h2c->m8 = cpu_to_le32(CCTLINFO_G7_W8_ALL);
2522
2523 h2c->w14 = le32_encode_bits(v: 0, CCTLINFO_G7_W14_VO_CURR_RATE) |
2524 le32_encode_bits(v: 0, CCTLINFO_G7_W14_VI_CURR_RATE) |
2525 le32_encode_bits(v: 0, CCTLINFO_G7_W14_BE_CURR_RATE_L);
2526 h2c->m14 = cpu_to_le32(CCTLINFO_G7_W14_ALL);
2527
2528 h2c->w15 = le32_encode_bits(v: 0, CCTLINFO_G7_W15_BE_CURR_RATE_H) |
2529 le32_encode_bits(v: 0, CCTLINFO_G7_W15_BK_CURR_RATE) |
2530 le32_encode_bits(v: 0, CCTLINFO_G7_W15_MGNT_CURR_RATE);
2531 h2c->m15 = cpu_to_le32(CCTLINFO_G7_W15_ALL);
2532
2533 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2534 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
2535 H2C_FUNC_MAC_CCTLINFO_UD_G7, rack: 0, dack: 1,
2536 len);
2537
2538 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2539 if (ret) {
2540 rtw89_err(rtwdev, "failed to send h2c\n");
2541 goto fail;
2542 }
2543
2544 return 0;
2545fail:
2546 dev_kfree_skb_any(skb);
2547
2548 return ret;
2549}
2550EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7);
2551
2552static void __get_sta_he_pkt_padding(struct rtw89_dev *rtwdev,
2553 struct ieee80211_sta *sta, u8 *pads)
2554{
2555 bool ppe_th;
2556 u8 ppe16, ppe8;
2557 u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
2558 u8 ppe_thres_hdr = sta->deflink.he_cap.ppe_thres[0];
2559 u8 ru_bitmap;
2560 u8 n, idx, sh;
2561 u16 ppe;
2562 int i;
2563
2564 ppe_th = FIELD_GET(IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT,
2565 sta->deflink.he_cap.he_cap_elem.phy_cap_info[6]);
2566 if (!ppe_th) {
2567 u8 pad;
2568
2569 pad = FIELD_GET(IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_MASK,
2570 sta->deflink.he_cap.he_cap_elem.phy_cap_info[9]);
2571
2572 for (i = 0; i < RTW89_PPE_BW_NUM; i++)
2573 pads[i] = pad;
2574
2575 return;
2576 }
2577
2578 ru_bitmap = FIELD_GET(IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK, ppe_thres_hdr);
2579 n = hweight8(ru_bitmap);
2580 n = 7 + (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) * nss;
2581
2582 for (i = 0; i < RTW89_PPE_BW_NUM; i++) {
2583 if (!(ru_bitmap & BIT(i))) {
2584 pads[i] = 1;
2585 continue;
2586 }
2587
2588 idx = n >> 3;
2589 sh = n & 7;
2590 n += IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2;
2591
2592 ppe = le16_to_cpu(*((__le16 *)&sta->deflink.he_cap.ppe_thres[idx]));
2593 ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
2594 sh += IEEE80211_PPE_THRES_INFO_PPET_SIZE;
2595 ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
2596
2597 if (ppe16 != 7 && ppe8 == 7)
2598 pads[i] = 2;
2599 else if (ppe8 != 7)
2600 pads[i] = 1;
2601 else
2602 pads[i] = 0;
2603 }
2604}
2605
2606int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
2607 struct ieee80211_vif *vif,
2608 struct ieee80211_sta *sta)
2609{
2610 const struct rtw89_chip_info *chip = rtwdev->chip;
2611 struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
2612 struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
2613 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
2614 idx: rtwvif->sub_entity_idx);
2615 struct sk_buff *skb;
2616 u8 pads[RTW89_PPE_BW_NUM];
2617 u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
2618 u16 lowest_rate;
2619 int ret;
2620
2621 memset(pads, 0, sizeof(pads));
2622 if (sta && sta->deflink.he_cap.has_he)
2623 __get_sta_he_pkt_padding(rtwdev, sta, pads);
2624
2625 if (vif->p2p)
2626 lowest_rate = RTW89_HW_RATE_OFDM6;
2627 else if (chan->band_type == RTW89_BAND_2G)
2628 lowest_rate = RTW89_HW_RATE_CCK1;
2629 else
2630 lowest_rate = RTW89_HW_RATE_OFDM6;
2631
2632 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
2633 if (!skb) {
2634 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
2635 return -ENOMEM;
2636 }
2637 skb_put(skb, H2C_CMC_TBL_LEN);
2638 SET_CTRL_INFO_MACID(table: skb->data, val: mac_id);
2639 SET_CTRL_INFO_OPERATION(table: skb->data, val: 1);
2640 SET_CMC_TBL_DISRTSFB(table: skb->data, val: 1);
2641 SET_CMC_TBL_DISDATAFB(table: skb->data, val: 1);
2642 SET_CMC_TBL_RTS_RTY_LOWEST_RATE(table: skb->data, val: lowest_rate);
2643 SET_CMC_TBL_RTS_TXCNT_LMT_SEL(table: skb->data, val: 0);
2644 SET_CMC_TBL_DATA_TXCNT_LMT_SEL(table: skb->data, val: 0);
2645 if (vif->type == NL80211_IFTYPE_STATION)
2646 SET_CMC_TBL_ULDL(table: skb->data, val: 1);
2647 else
2648 SET_CMC_TBL_ULDL(table: skb->data, val: 0);
2649 SET_CMC_TBL_MULTI_PORT_ID(table: skb->data, val: rtwvif->port);
2650 if (chip->h2c_cctl_func_id == H2C_FUNC_MAC_CCTLINFO_UD_V1) {
2651 SET_CMC_TBL_NOMINAL_PKT_PADDING_V1(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_20]);
2652 SET_CMC_TBL_NOMINAL_PKT_PADDING40_V1(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_40]);
2653 SET_CMC_TBL_NOMINAL_PKT_PADDING80_V1(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_80]);
2654 SET_CMC_TBL_NOMINAL_PKT_PADDING160_V1(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_160]);
2655 } else if (chip->h2c_cctl_func_id == H2C_FUNC_MAC_CCTLINFO_UD) {
2656 SET_CMC_TBL_NOMINAL_PKT_PADDING(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_20]);
2657 SET_CMC_TBL_NOMINAL_PKT_PADDING40(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_40]);
2658 SET_CMC_TBL_NOMINAL_PKT_PADDING80(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_80]);
2659 SET_CMC_TBL_NOMINAL_PKT_PADDING160(table: skb->data, val: pads[RTW89_CHANNEL_WIDTH_160]);
2660 }
2661 if (sta)
2662 SET_CMC_TBL_BSR_QUEUE_SIZE_FORMAT(table: skb->data,
2663 val: sta->deflink.he_cap.has_he);
2664 if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE)
2665 SET_CMC_TBL_DATA_DCM(table: skb->data, val: 0);
2666
2667 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2668 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
2669 func: chip->h2c_cctl_func_id, rack: 0, dack: 1,
2670 H2C_CMC_TBL_LEN);
2671
2672 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2673 if (ret) {
2674 rtw89_err(rtwdev, "failed to send h2c\n");
2675 goto fail;
2676 }
2677
2678 return 0;
2679fail:
2680 dev_kfree_skb_any(skb);
2681
2682 return ret;
2683}
2684EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl);
2685
2686static void __get_sta_eht_pkt_padding(struct rtw89_dev *rtwdev,
2687 struct ieee80211_sta *sta, u8 *pads)
2688{
2689 u8 nss = min(sta->deflink.rx_nss, rtwdev->hal.tx_nss) - 1;
2690 u16 ppe_thres_hdr;
2691 u8 ppe16, ppe8;
2692 u8 n, idx, sh;
2693 u8 ru_bitmap;
2694 bool ppe_th;
2695 u16 ppe;
2696 int i;
2697
2698 ppe_th = !!u8_get_bits(v: sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5],
2699 IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT);
2700 if (!ppe_th) {
2701 u8 pad;
2702
2703 pad = u8_get_bits(v: sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[5],
2704 IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK);
2705
2706 for (i = 0; i < RTW89_PPE_BW_NUM; i++)
2707 pads[i] = pad;
2708
2709 return;
2710 }
2711
2712 ppe_thres_hdr = get_unaligned_le16(p: sta->deflink.eht_cap.eht_ppe_thres);
2713 ru_bitmap = u16_get_bits(v: ppe_thres_hdr,
2714 IEEE80211_EHT_PPE_THRES_RU_INDEX_BITMASK_MASK);
2715 n = hweight8(ru_bitmap);
2716 n = IEEE80211_EHT_PPE_THRES_INFO_HEADER_SIZE +
2717 (n * IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2) * nss;
2718
2719 for (i = 0; i < RTW89_PPE_BW_NUM; i++) {
2720 if (!(ru_bitmap & BIT(i))) {
2721 pads[i] = 1;
2722 continue;
2723 }
2724
2725 idx = n >> 3;
2726 sh = n & 7;
2727 n += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE * 2;
2728
2729 ppe = get_unaligned_le16(p: sta->deflink.eht_cap.eht_ppe_thres + idx);
2730 ppe16 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
2731 sh += IEEE80211_EHT_PPE_THRES_INFO_PPET_SIZE;
2732 ppe8 = (ppe >> sh) & IEEE80211_PPE_THRES_NSS_MASK;
2733
2734 if (ppe16 != 7 && ppe8 == 7)
2735 pads[i] = 2;
2736 else if (ppe8 != 7)
2737 pads[i] = 1;
2738 else
2739 pads[i] = 0;
2740 }
2741}
2742
2743int rtw89_fw_h2c_assoc_cmac_tbl_g7(struct rtw89_dev *rtwdev,
2744 struct ieee80211_vif *vif,
2745 struct ieee80211_sta *sta)
2746{
2747 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx: RTW89_SUB_ENTITY_0);
2748 struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
2749 struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
2750 u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
2751 struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
2752 u8 pads[RTW89_PPE_BW_NUM];
2753 u32 len = sizeof(*h2c);
2754 struct sk_buff *skb;
2755 u16 lowest_rate;
2756 int ret;
2757
2758 memset(pads, 0, sizeof(pads));
2759 if (sta) {
2760 if (sta->deflink.eht_cap.has_eht)
2761 __get_sta_eht_pkt_padding(rtwdev, sta, pads);
2762 else if (sta->deflink.he_cap.has_he)
2763 __get_sta_he_pkt_padding(rtwdev, sta, pads);
2764 }
2765
2766 if (vif->p2p)
2767 lowest_rate = RTW89_HW_RATE_OFDM6;
2768 else if (chan->band_type == RTW89_BAND_2G)
2769 lowest_rate = RTW89_HW_RATE_CCK1;
2770 else
2771 lowest_rate = RTW89_HW_RATE_OFDM6;
2772
2773 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
2774 if (!skb) {
2775 rtw89_err(rtwdev, "failed to alloc skb for cmac g7\n");
2776 return -ENOMEM;
2777 }
2778 skb_put(skb, len);
2779 h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data;
2780
2781 h2c->c0 = le32_encode_bits(v: mac_id, CCTLINFO_G7_C0_MACID) |
2782 le32_encode_bits(v: 1, CCTLINFO_G7_C0_OP);
2783
2784 h2c->w0 = le32_encode_bits(v: 1, CCTLINFO_G7_W0_DISRTSFB) |
2785 le32_encode_bits(v: 1, CCTLINFO_G7_W0_DISDATAFB);
2786 h2c->m0 = cpu_to_le32(CCTLINFO_G7_W0_DISRTSFB |
2787 CCTLINFO_G7_W0_DISDATAFB);
2788
2789 h2c->w1 = le32_encode_bits(v: lowest_rate, CCTLINFO_G7_W1_RTS_RTY_LOWEST_RATE);
2790 h2c->m1 = cpu_to_le32(CCTLINFO_G7_W1_RTS_RTY_LOWEST_RATE);
2791
2792 h2c->w2 = le32_encode_bits(v: 0, CCTLINFO_G7_W2_DATA_TXCNT_LMT_SEL);
2793 h2c->m2 = cpu_to_le32(CCTLINFO_G7_W2_DATA_TXCNT_LMT_SEL);
2794
2795 h2c->w3 = le32_encode_bits(v: 0, CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL);
2796 h2c->m3 = cpu_to_le32(CCTLINFO_G7_W3_RTS_TXCNT_LMT_SEL);
2797
2798 h2c->w4 = le32_encode_bits(v: rtwvif->port, CCTLINFO_G7_W4_MULTI_PORT_ID);
2799 h2c->m4 = cpu_to_le32(CCTLINFO_G7_W4_MULTI_PORT_ID);
2800
2801 if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) {
2802 h2c->w4 |= le32_encode_bits(v: 0, CCTLINFO_G7_W4_DATA_DCM);
2803 h2c->m4 |= cpu_to_le32(CCTLINFO_G7_W4_DATA_DCM);
2804 }
2805
2806 if (vif->bss_conf.eht_support) {
2807 u16 punct = vif->bss_conf.chanreq.oper.punctured;
2808
2809 h2c->w4 |= le32_encode_bits(v: ~punct,
2810 CCTLINFO_G7_W4_ACT_SUBCH_CBW);
2811 h2c->m4 |= cpu_to_le32(CCTLINFO_G7_W4_ACT_SUBCH_CBW);
2812 }
2813
2814 h2c->w5 = le32_encode_bits(v: pads[RTW89_CHANNEL_WIDTH_20],
2815 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING0) |
2816 le32_encode_bits(v: pads[RTW89_CHANNEL_WIDTH_40],
2817 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING1) |
2818 le32_encode_bits(v: pads[RTW89_CHANNEL_WIDTH_80],
2819 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING2) |
2820 le32_encode_bits(v: pads[RTW89_CHANNEL_WIDTH_160],
2821 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3) |
2822 le32_encode_bits(v: pads[RTW89_CHANNEL_WIDTH_320],
2823 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4);
2824 h2c->m5 = cpu_to_le32(CCTLINFO_G7_W5_NOMINAL_PKT_PADDING0 |
2825 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING1 |
2826 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING2 |
2827 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING3 |
2828 CCTLINFO_G7_W5_NOMINAL_PKT_PADDING4);
2829
2830 h2c->w6 = le32_encode_bits(v: vif->type == NL80211_IFTYPE_STATION ? 1 : 0,
2831 CCTLINFO_G7_W6_ULDL);
2832 h2c->m6 = cpu_to_le32(CCTLINFO_G7_W6_ULDL);
2833
2834 if (sta) {
2835 h2c->w8 = le32_encode_bits(v: sta->deflink.he_cap.has_he,
2836 CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT);
2837 h2c->m8 = cpu_to_le32(CCTLINFO_G7_W8_BSR_QUEUE_SIZE_FORMAT);
2838 }
2839
2840 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2841 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
2842 H2C_FUNC_MAC_CCTLINFO_UD_G7, rack: 0, dack: 1,
2843 len);
2844
2845 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2846 if (ret) {
2847 rtw89_err(rtwdev, "failed to send h2c\n");
2848 goto fail;
2849 }
2850
2851 return 0;
2852fail:
2853 dev_kfree_skb_any(skb);
2854
2855 return ret;
2856}
2857EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7);
2858
2859int rtw89_fw_h2c_ampdu_cmac_tbl_g7(struct rtw89_dev *rtwdev,
2860 struct ieee80211_vif *vif,
2861 struct ieee80211_sta *sta)
2862{
2863 struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
2864 struct rtw89_h2c_cctlinfo_ud_g7 *h2c;
2865 u32 len = sizeof(*h2c);
2866 struct sk_buff *skb;
2867 u16 agg_num = 0;
2868 u8 ba_bmap = 0;
2869 int ret;
2870 u8 tid;
2871
2872 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
2873 if (!skb) {
2874 rtw89_err(rtwdev, "failed to alloc skb for ampdu cmac g7\n");
2875 return -ENOMEM;
2876 }
2877 skb_put(skb, len);
2878 h2c = (struct rtw89_h2c_cctlinfo_ud_g7 *)skb->data;
2879
2880 for_each_set_bit(tid, rtwsta->ampdu_map, IEEE80211_NUM_TIDS) {
2881 if (agg_num == 0)
2882 agg_num = rtwsta->ampdu_params[tid].agg_num;
2883 else
2884 agg_num = min(agg_num, rtwsta->ampdu_params[tid].agg_num);
2885 }
2886
2887 if (agg_num <= 0x20)
2888 ba_bmap = 3;
2889 else if (agg_num > 0x20 && agg_num <= 0x40)
2890 ba_bmap = 0;
2891 else if (agg_num > 0x40 && agg_num <= 0x80)
2892 ba_bmap = 1;
2893 else if (agg_num > 0x80 && agg_num <= 0x100)
2894 ba_bmap = 2;
2895 else if (agg_num > 0x100 && agg_num <= 0x200)
2896 ba_bmap = 4;
2897 else if (agg_num > 0x200 && agg_num <= 0x400)
2898 ba_bmap = 5;
2899
2900 h2c->c0 = le32_encode_bits(v: rtwsta->mac_id, CCTLINFO_G7_C0_MACID) |
2901 le32_encode_bits(v: 1, CCTLINFO_G7_C0_OP);
2902
2903 h2c->w3 = le32_encode_bits(v: ba_bmap, CCTLINFO_G7_W3_BA_BMAP);
2904 h2c->m3 = cpu_to_le32(CCTLINFO_G7_W3_BA_BMAP);
2905
2906 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2907 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
2908 H2C_FUNC_MAC_CCTLINFO_UD_G7, rack: 0, dack: 0,
2909 len);
2910
2911 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2912 if (ret) {
2913 rtw89_err(rtwdev, "failed to send h2c\n");
2914 goto fail;
2915 }
2916
2917 return 0;
2918fail:
2919 dev_kfree_skb_any(skb);
2920
2921 return ret;
2922}
2923EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7);
2924
2925int rtw89_fw_h2c_txtime_cmac_tbl(struct rtw89_dev *rtwdev,
2926 struct rtw89_sta *rtwsta)
2927{
2928 const struct rtw89_chip_info *chip = rtwdev->chip;
2929 struct sk_buff *skb;
2930 int ret;
2931
2932 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
2933 if (!skb) {
2934 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
2935 return -ENOMEM;
2936 }
2937 skb_put(skb, H2C_CMC_TBL_LEN);
2938 SET_CTRL_INFO_MACID(table: skb->data, val: rtwsta->mac_id);
2939 SET_CTRL_INFO_OPERATION(table: skb->data, val: 1);
2940 if (rtwsta->cctl_tx_time) {
2941 SET_CMC_TBL_AMPDU_TIME_SEL(table: skb->data, val: 1);
2942 SET_CMC_TBL_AMPDU_MAX_TIME(table: skb->data, val: rtwsta->ampdu_max_time);
2943 }
2944 if (rtwsta->cctl_tx_retry_limit) {
2945 SET_CMC_TBL_DATA_TXCNT_LMT_SEL(table: skb->data, val: 1);
2946 SET_CMC_TBL_DATA_TX_CNT_LMT(table: skb->data, val: rtwsta->data_tx_cnt_lmt);
2947 }
2948
2949 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2950 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
2951 func: chip->h2c_cctl_func_id, rack: 0, dack: 1,
2952 H2C_CMC_TBL_LEN);
2953
2954 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2955 if (ret) {
2956 rtw89_err(rtwdev, "failed to send h2c\n");
2957 goto fail;
2958 }
2959
2960 return 0;
2961fail:
2962 dev_kfree_skb_any(skb);
2963
2964 return ret;
2965}
2966
2967int rtw89_fw_h2c_txpath_cmac_tbl(struct rtw89_dev *rtwdev,
2968 struct rtw89_sta *rtwsta)
2969{
2970 const struct rtw89_chip_info *chip = rtwdev->chip;
2971 struct sk_buff *skb;
2972 int ret;
2973
2974 if (chip->h2c_cctl_func_id != H2C_FUNC_MAC_CCTLINFO_UD)
2975 return 0;
2976
2977 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_CMC_TBL_LEN);
2978 if (!skb) {
2979 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
2980 return -ENOMEM;
2981 }
2982 skb_put(skb, H2C_CMC_TBL_LEN);
2983 SET_CTRL_INFO_MACID(table: skb->data, val: rtwsta->mac_id);
2984 SET_CTRL_INFO_OPERATION(table: skb->data, val: 1);
2985
2986 __rtw89_fw_h2c_set_tx_path(rtwdev, skb);
2987
2988 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
2989 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
2990 H2C_FUNC_MAC_CCTLINFO_UD, rack: 0, dack: 1,
2991 H2C_CMC_TBL_LEN);
2992
2993 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
2994 if (ret) {
2995 rtw89_err(rtwdev, "failed to send h2c\n");
2996 goto fail;
2997 }
2998
2999 return 0;
3000fail:
3001 dev_kfree_skb_any(skb);
3002
3003 return ret;
3004}
3005
3006int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
3007 struct rtw89_vif *rtwvif)
3008{
3009 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
3010 idx: rtwvif->sub_entity_idx);
3011 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
3012 struct rtw89_h2c_bcn_upd *h2c;
3013 struct sk_buff *skb_beacon;
3014 struct ieee80211_hdr *hdr;
3015 u32 len = sizeof(*h2c);
3016 struct sk_buff *skb;
3017 int bcn_total_len;
3018 u16 beacon_rate;
3019 u16 tim_offset;
3020 void *noa_data;
3021 u8 noa_len;
3022 int ret;
3023
3024 if (vif->p2p)
3025 beacon_rate = RTW89_HW_RATE_OFDM6;
3026 else if (chan->band_type == RTW89_BAND_2G)
3027 beacon_rate = RTW89_HW_RATE_CCK1;
3028 else
3029 beacon_rate = RTW89_HW_RATE_OFDM6;
3030
3031 skb_beacon = ieee80211_beacon_get_tim(hw: rtwdev->hw, vif, tim_offset: &tim_offset,
3032 NULL, link_id: 0);
3033 if (!skb_beacon) {
3034 rtw89_err(rtwdev, "failed to get beacon skb\n");
3035 return -ENOMEM;
3036 }
3037
3038 noa_len = rtw89_p2p_noa_fetch(rtwvif, data: &noa_data);
3039 if (noa_len &&
3040 (noa_len <= skb_tailroom(skb: skb_beacon) ||
3041 pskb_expand_head(skb: skb_beacon, nhead: 0, ntail: noa_len, GFP_KERNEL) == 0)) {
3042 skb_put_data(skb: skb_beacon, data: noa_data, len: noa_len);
3043 }
3044
3045 hdr = (struct ieee80211_hdr *)skb_beacon;
3046 tim_offset -= ieee80211_hdrlen(fc: hdr->frame_control);
3047
3048 bcn_total_len = len + skb_beacon->len;
3049 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len: bcn_total_len);
3050 if (!skb) {
3051 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
3052 dev_kfree_skb_any(skb: skb_beacon);
3053 return -ENOMEM;
3054 }
3055 skb_put(skb, len);
3056 h2c = (struct rtw89_h2c_bcn_upd *)skb->data;
3057
3058 h2c->w0 = le32_encode_bits(v: rtwvif->port, RTW89_H2C_BCN_UPD_W0_PORT) |
3059 le32_encode_bits(v: 0, RTW89_H2C_BCN_UPD_W0_MBSSID) |
3060 le32_encode_bits(v: rtwvif->mac_idx, RTW89_H2C_BCN_UPD_W0_BAND) |
3061 le32_encode_bits(v: tim_offset | BIT(7), RTW89_H2C_BCN_UPD_W0_GRP_IE_OFST);
3062 h2c->w1 = le32_encode_bits(v: rtwvif->mac_id, RTW89_H2C_BCN_UPD_W1_MACID) |
3063 le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_W1_SSN_SEL) |
3064 le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_W1_SSN_MODE) |
3065 le32_encode_bits(v: beacon_rate, RTW89_H2C_BCN_UPD_W1_RATE);
3066
3067 skb_put_data(skb, data: skb_beacon->data, len: skb_beacon->len);
3068 dev_kfree_skb_any(skb: skb_beacon);
3069
3070 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3071 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
3072 H2C_FUNC_MAC_BCN_UPD, rack: 0, dack: 1,
3073 len: bcn_total_len);
3074
3075 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3076 if (ret) {
3077 rtw89_err(rtwdev, "failed to send h2c\n");
3078 dev_kfree_skb_any(skb);
3079 return ret;
3080 }
3081
3082 return 0;
3083}
3084EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon);
3085
3086int rtw89_fw_h2c_update_beacon_be(struct rtw89_dev *rtwdev,
3087 struct rtw89_vif *rtwvif)
3088{
3089 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, idx: RTW89_SUB_ENTITY_0);
3090 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
3091 struct rtw89_h2c_bcn_upd_be *h2c;
3092 struct sk_buff *skb_beacon;
3093 struct ieee80211_hdr *hdr;
3094 u32 len = sizeof(*h2c);
3095 struct sk_buff *skb;
3096 int bcn_total_len;
3097 u16 beacon_rate;
3098 u16 tim_offset;
3099 void *noa_data;
3100 u8 noa_len;
3101 int ret;
3102
3103 if (vif->p2p)
3104 beacon_rate = RTW89_HW_RATE_OFDM6;
3105 else if (chan->band_type == RTW89_BAND_2G)
3106 beacon_rate = RTW89_HW_RATE_CCK1;
3107 else
3108 beacon_rate = RTW89_HW_RATE_OFDM6;
3109
3110 skb_beacon = ieee80211_beacon_get_tim(hw: rtwdev->hw, vif, tim_offset: &tim_offset,
3111 NULL, link_id: 0);
3112 if (!skb_beacon) {
3113 rtw89_err(rtwdev, "failed to get beacon skb\n");
3114 return -ENOMEM;
3115 }
3116
3117 noa_len = rtw89_p2p_noa_fetch(rtwvif, data: &noa_data);
3118 if (noa_len &&
3119 (noa_len <= skb_tailroom(skb: skb_beacon) ||
3120 pskb_expand_head(skb: skb_beacon, nhead: 0, ntail: noa_len, GFP_KERNEL) == 0)) {
3121 skb_put_data(skb: skb_beacon, data: noa_data, len: noa_len);
3122 }
3123
3124 hdr = (struct ieee80211_hdr *)skb_beacon;
3125 tim_offset -= ieee80211_hdrlen(fc: hdr->frame_control);
3126
3127 bcn_total_len = len + skb_beacon->len;
3128 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len: bcn_total_len);
3129 if (!skb) {
3130 rtw89_err(rtwdev, "failed to alloc skb for fw dl\n");
3131 dev_kfree_skb_any(skb: skb_beacon);
3132 return -ENOMEM;
3133 }
3134 skb_put(skb, len);
3135 h2c = (struct rtw89_h2c_bcn_upd_be *)skb->data;
3136
3137 h2c->w0 = le32_encode_bits(v: rtwvif->port, RTW89_H2C_BCN_UPD_BE_W0_PORT) |
3138 le32_encode_bits(v: 0, RTW89_H2C_BCN_UPD_BE_W0_MBSSID) |
3139 le32_encode_bits(v: rtwvif->mac_idx, RTW89_H2C_BCN_UPD_BE_W0_BAND) |
3140 le32_encode_bits(v: tim_offset | BIT(7), RTW89_H2C_BCN_UPD_BE_W0_GRP_IE_OFST);
3141 h2c->w1 = le32_encode_bits(v: rtwvif->mac_id, RTW89_H2C_BCN_UPD_BE_W1_MACID) |
3142 le32_encode_bits(RTW89_MGMT_HW_SSN_SEL, RTW89_H2C_BCN_UPD_BE_W1_SSN_SEL) |
3143 le32_encode_bits(RTW89_MGMT_HW_SEQ_MODE, RTW89_H2C_BCN_UPD_BE_W1_SSN_MODE) |
3144 le32_encode_bits(v: beacon_rate, RTW89_H2C_BCN_UPD_BE_W1_RATE);
3145
3146 skb_put_data(skb, data: skb_beacon->data, len: skb_beacon->len);
3147 dev_kfree_skb_any(skb: skb_beacon);
3148
3149 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3150 H2C_CAT_MAC, H2C_CL_MAC_FR_EXCHG,
3151 H2C_FUNC_MAC_BCN_UPD_BE, rack: 0, dack: 1,
3152 len: bcn_total_len);
3153
3154 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3155 if (ret) {
3156 rtw89_err(rtwdev, "failed to send h2c\n");
3157 goto fail;
3158 }
3159
3160 return 0;
3161
3162fail:
3163 dev_kfree_skb_any(skb);
3164
3165 return ret;
3166}
3167EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be);
3168
3169#define H2C_ROLE_MAINTAIN_LEN 4
3170int rtw89_fw_h2c_role_maintain(struct rtw89_dev *rtwdev,
3171 struct rtw89_vif *rtwvif,
3172 struct rtw89_sta *rtwsta,
3173 enum rtw89_upd_mode upd_mode)
3174{
3175 struct sk_buff *skb;
3176 u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
3177 u8 self_role;
3178 int ret;
3179
3180 if (rtwvif->net_type == RTW89_NET_TYPE_AP_MODE) {
3181 if (rtwsta)
3182 self_role = RTW89_SELF_ROLE_AP_CLIENT;
3183 else
3184 self_role = rtwvif->self_role;
3185 } else {
3186 self_role = rtwvif->self_role;
3187 }
3188
3189 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_ROLE_MAINTAIN_LEN);
3190 if (!skb) {
3191 rtw89_err(rtwdev, "failed to alloc skb for h2c join\n");
3192 return -ENOMEM;
3193 }
3194 skb_put(skb, H2C_ROLE_MAINTAIN_LEN);
3195 SET_FWROLE_MAINTAIN_MACID(h2c: skb->data, val: mac_id);
3196 SET_FWROLE_MAINTAIN_SELF_ROLE(h2c: skb->data, val: self_role);
3197 SET_FWROLE_MAINTAIN_UPD_MODE(h2c: skb->data, val: upd_mode);
3198 SET_FWROLE_MAINTAIN_WIFI_ROLE(h2c: skb->data, val: rtwvif->wifi_role);
3199
3200 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3201 H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT,
3202 H2C_FUNC_MAC_FWROLE_MAINTAIN, rack: 0, dack: 1,
3203 H2C_ROLE_MAINTAIN_LEN);
3204
3205 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3206 if (ret) {
3207 rtw89_err(rtwdev, "failed to send h2c\n");
3208 goto fail;
3209 }
3210
3211 return 0;
3212fail:
3213 dev_kfree_skb_any(skb);
3214
3215 return ret;
3216}
3217
3218static enum rtw89_fw_sta_type
3219rtw89_fw_get_sta_type(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
3220 struct rtw89_sta *rtwsta)
3221{
3222 struct ieee80211_sta *sta = rtwsta_to_sta_safe(rtwsta);
3223 struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
3224
3225 if (!sta)
3226 goto by_vif;
3227
3228 if (sta->deflink.eht_cap.has_eht)
3229 return RTW89_FW_BE_STA;
3230 else if (sta->deflink.he_cap.has_he)
3231 return RTW89_FW_AX_STA;
3232 else
3233 return RTW89_FW_N_AC_STA;
3234
3235by_vif:
3236 if (vif->bss_conf.eht_support)
3237 return RTW89_FW_BE_STA;
3238 else if (vif->bss_conf.he_support)
3239 return RTW89_FW_AX_STA;
3240 else
3241 return RTW89_FW_N_AC_STA;
3242}
3243
3244int rtw89_fw_h2c_join_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
3245 struct rtw89_sta *rtwsta, bool dis_conn)
3246{
3247 struct sk_buff *skb;
3248 u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
3249 u8 self_role = rtwvif->self_role;
3250 enum rtw89_fw_sta_type sta_type;
3251 u8 net_type = rtwvif->net_type;
3252 struct rtw89_h2c_join_v1 *h2c_v1;
3253 struct rtw89_h2c_join *h2c;
3254 u32 len = sizeof(*h2c);
3255 bool format_v1 = false;
3256 int ret;
3257
3258 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) {
3259 len = sizeof(*h2c_v1);
3260 format_v1 = true;
3261 }
3262
3263 if (net_type == RTW89_NET_TYPE_AP_MODE && rtwsta) {
3264 self_role = RTW89_SELF_ROLE_AP_CLIENT;
3265 net_type = dis_conn ? RTW89_NET_TYPE_NO_LINK : net_type;
3266 }
3267
3268 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3269 if (!skb) {
3270 rtw89_err(rtwdev, "failed to alloc skb for h2c join\n");
3271 return -ENOMEM;
3272 }
3273 skb_put(skb, len);
3274 h2c = (struct rtw89_h2c_join *)skb->data;
3275
3276 h2c->w0 = le32_encode_bits(v: mac_id, RTW89_H2C_JOININFO_W0_MACID) |
3277 le32_encode_bits(v: dis_conn, RTW89_H2C_JOININFO_W0_OP) |
3278 le32_encode_bits(v: rtwvif->mac_idx, RTW89_H2C_JOININFO_W0_BAND) |
3279 le32_encode_bits(v: rtwvif->wmm, RTW89_H2C_JOININFO_W0_WMM) |
3280 le32_encode_bits(v: rtwvif->trigger, RTW89_H2C_JOININFO_W0_TGR) |
3281 le32_encode_bits(v: 0, RTW89_H2C_JOININFO_W0_ISHESTA) |
3282 le32_encode_bits(v: 0, RTW89_H2C_JOININFO_W0_DLBW) |
3283 le32_encode_bits(v: 0, RTW89_H2C_JOININFO_W0_TF_MAC_PAD) |
3284 le32_encode_bits(v: 0, RTW89_H2C_JOININFO_W0_DL_T_PE) |
3285 le32_encode_bits(v: rtwvif->port, RTW89_H2C_JOININFO_W0_PORT_ID) |
3286 le32_encode_bits(v: net_type, RTW89_H2C_JOININFO_W0_NET_TYPE) |
3287 le32_encode_bits(v: rtwvif->wifi_role, RTW89_H2C_JOININFO_W0_WIFI_ROLE) |
3288 le32_encode_bits(v: self_role, RTW89_H2C_JOININFO_W0_SELF_ROLE);
3289
3290 if (!format_v1)
3291 goto done;
3292
3293 h2c_v1 = (struct rtw89_h2c_join_v1 *)skb->data;
3294
3295 sta_type = rtw89_fw_get_sta_type(rtwdev, rtwvif, rtwsta);
3296
3297 h2c_v1->w1 = le32_encode_bits(v: sta_type, RTW89_H2C_JOININFO_W1_STA_TYPE);
3298 h2c_v1->w2 = 0;
3299
3300done:
3301 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3302 H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT,
3303 H2C_FUNC_MAC_JOININFO, rack: 0, dack: 1,
3304 len);
3305
3306 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3307 if (ret) {
3308 rtw89_err(rtwdev, "failed to send h2c\n");
3309 goto fail;
3310 }
3311
3312 return 0;
3313fail:
3314 dev_kfree_skb_any(skb);
3315
3316 return ret;
3317}
3318
3319int rtw89_fw_h2c_notify_dbcc(struct rtw89_dev *rtwdev, bool en)
3320{
3321 struct rtw89_h2c_notify_dbcc *h2c;
3322 u32 len = sizeof(*h2c);
3323 struct sk_buff *skb;
3324 int ret;
3325
3326 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3327 if (!skb) {
3328 rtw89_err(rtwdev, "failed to alloc skb for h2c notify dbcc\n");
3329 return -ENOMEM;
3330 }
3331 skb_put(skb, len);
3332 h2c = (struct rtw89_h2c_notify_dbcc *)skb->data;
3333
3334 h2c->w0 = le32_encode_bits(v: en, RTW89_H2C_NOTIFY_DBCC_EN);
3335
3336 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3337 H2C_CAT_MAC, H2C_CL_MAC_MEDIA_RPT,
3338 H2C_FUNC_NOTIFY_DBCC, rack: 0, dack: 1,
3339 len);
3340
3341 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3342 if (ret) {
3343 rtw89_err(rtwdev, "failed to send h2c\n");
3344 goto fail;
3345 }
3346
3347 return 0;
3348fail:
3349 dev_kfree_skb_any(skb);
3350
3351 return ret;
3352}
3353
3354int rtw89_fw_h2c_macid_pause(struct rtw89_dev *rtwdev, u8 sh, u8 grp,
3355 bool pause)
3356{
3357 struct rtw89_fw_macid_pause_sleep_grp *h2c_new;
3358 struct rtw89_fw_macid_pause_grp *h2c;
3359 __le32 set = cpu_to_le32(BIT(sh));
3360 u8 h2c_macid_pause_id;
3361 struct sk_buff *skb;
3362 u32 len;
3363 int ret;
3364
3365 if (RTW89_CHK_FW_FEATURE(MACID_PAUSE_SLEEP, &rtwdev->fw)) {
3366 h2c_macid_pause_id = H2C_FUNC_MAC_MACID_PAUSE_SLEEP;
3367 len = sizeof(*h2c_new);
3368 } else {
3369 h2c_macid_pause_id = H2C_FUNC_MAC_MACID_PAUSE;
3370 len = sizeof(*h2c);
3371 }
3372
3373 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3374 if (!skb) {
3375 rtw89_err(rtwdev, "failed to alloc skb for h2c macid pause\n");
3376 return -ENOMEM;
3377 }
3378 skb_put(skb, len);
3379
3380 if (h2c_macid_pause_id == H2C_FUNC_MAC_MACID_PAUSE_SLEEP) {
3381 h2c_new = (struct rtw89_fw_macid_pause_sleep_grp *)skb->data;
3382
3383 h2c_new->n[0].pause_mask_grp[grp] = set;
3384 h2c_new->n[0].sleep_mask_grp[grp] = set;
3385 if (pause) {
3386 h2c_new->n[0].pause_grp[grp] = set;
3387 h2c_new->n[0].sleep_grp[grp] = set;
3388 }
3389 } else {
3390 h2c = (struct rtw89_fw_macid_pause_grp *)skb->data;
3391
3392 h2c->mask_grp[grp] = set;
3393 if (pause)
3394 h2c->pause_grp[grp] = set;
3395 }
3396
3397 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3398 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
3399 func: h2c_macid_pause_id, rack: 1, dack: 0,
3400 len);
3401
3402 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3403 if (ret) {
3404 rtw89_err(rtwdev, "failed to send h2c\n");
3405 goto fail;
3406 }
3407
3408 return 0;
3409fail:
3410 dev_kfree_skb_any(skb);
3411
3412 return ret;
3413}
3414
3415#define H2C_EDCA_LEN 12
3416int rtw89_fw_h2c_set_edca(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
3417 u8 ac, u32 val)
3418{
3419 struct sk_buff *skb;
3420 int ret;
3421
3422 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_EDCA_LEN);
3423 if (!skb) {
3424 rtw89_err(rtwdev, "failed to alloc skb for h2c edca\n");
3425 return -ENOMEM;
3426 }
3427 skb_put(skb, H2C_EDCA_LEN);
3428 RTW89_SET_EDCA_SEL(cmd: skb->data, val: 0);
3429 RTW89_SET_EDCA_BAND(cmd: skb->data, val: rtwvif->mac_idx);
3430 RTW89_SET_EDCA_WMM(cmd: skb->data, val: 0);
3431 RTW89_SET_EDCA_AC(cmd: skb->data, val: ac);
3432 RTW89_SET_EDCA_PARAM(cmd: skb->data, val);
3433
3434 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3435 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
3436 func: H2C_FUNC_USR_EDCA, rack: 0, dack: 1,
3437 H2C_EDCA_LEN);
3438
3439 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3440 if (ret) {
3441 rtw89_err(rtwdev, "failed to send h2c\n");
3442 goto fail;
3443 }
3444
3445 return 0;
3446fail:
3447 dev_kfree_skb_any(skb);
3448
3449 return ret;
3450}
3451
3452#define H2C_TSF32_TOGL_LEN 4
3453int rtw89_fw_h2c_tsf32_toggle(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
3454 bool en)
3455{
3456 struct sk_buff *skb;
3457 u16 early_us = en ? 2000 : 0;
3458 u8 *cmd;
3459 int ret;
3460
3461 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_TSF32_TOGL_LEN);
3462 if (!skb) {
3463 rtw89_err(rtwdev, "failed to alloc skb for h2c p2p act\n");
3464 return -ENOMEM;
3465 }
3466 skb_put(skb, H2C_TSF32_TOGL_LEN);
3467 cmd = skb->data;
3468
3469 RTW89_SET_FWCMD_TSF32_TOGL_BAND(cmd, val: rtwvif->mac_idx);
3470 RTW89_SET_FWCMD_TSF32_TOGL_EN(cmd, val: en);
3471 RTW89_SET_FWCMD_TSF32_TOGL_PORT(cmd, val: rtwvif->port);
3472 RTW89_SET_FWCMD_TSF32_TOGL_EARLY(cmd, val: early_us);
3473
3474 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3475 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
3476 func: H2C_FUNC_TSF32_TOGL, rack: 0, dack: 0,
3477 H2C_TSF32_TOGL_LEN);
3478
3479 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3480 if (ret) {
3481 rtw89_err(rtwdev, "failed to send h2c\n");
3482 goto fail;
3483 }
3484
3485 return 0;
3486fail:
3487 dev_kfree_skb_any(skb);
3488
3489 return ret;
3490}
3491
3492#define H2C_OFLD_CFG_LEN 8
3493int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev)
3494{
3495 static const u8 cfg[] = {0x09, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00};
3496 struct sk_buff *skb;
3497 int ret;
3498
3499 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_OFLD_CFG_LEN);
3500 if (!skb) {
3501 rtw89_err(rtwdev, "failed to alloc skb for h2c ofld\n");
3502 return -ENOMEM;
3503 }
3504 skb_put_data(skb, data: cfg, H2C_OFLD_CFG_LEN);
3505
3506 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3507 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
3508 func: H2C_FUNC_OFLD_CFG, rack: 0, dack: 1,
3509 H2C_OFLD_CFG_LEN);
3510
3511 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3512 if (ret) {
3513 rtw89_err(rtwdev, "failed to send h2c\n");
3514 goto fail;
3515 }
3516
3517 return 0;
3518fail:
3519 dev_kfree_skb_any(skb);
3520
3521 return ret;
3522}
3523
3524int rtw89_fw_h2c_set_bcn_fltr_cfg(struct rtw89_dev *rtwdev,
3525 struct ieee80211_vif *vif,
3526 bool connect)
3527{
3528 struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
3529 struct ieee80211_bss_conf *bss_conf = vif ? &vif->bss_conf : NULL;
3530 s32 thold = RTW89_DEFAULT_CQM_THOLD;
3531 u32 hyst = RTW89_DEFAULT_CQM_HYST;
3532 struct rtw89_h2c_bcnfltr *h2c;
3533 u32 len = sizeof(*h2c);
3534 struct sk_buff *skb;
3535 int ret;
3536
3537 if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
3538 return -EINVAL;
3539
3540 if (!rtwvif || !bss_conf || rtwvif->net_type != RTW89_NET_TYPE_INFRA)
3541 return -EINVAL;
3542
3543 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3544 if (!skb) {
3545 rtw89_err(rtwdev, "failed to alloc skb for h2c bcn filter\n");
3546 return -ENOMEM;
3547 }
3548
3549 skb_put(skb, len);
3550 h2c = (struct rtw89_h2c_bcnfltr *)skb->data;
3551
3552 if (bss_conf->cqm_rssi_hyst)
3553 hyst = bss_conf->cqm_rssi_hyst;
3554 if (bss_conf->cqm_rssi_thold)
3555 thold = bss_conf->cqm_rssi_thold;
3556
3557 h2c->w0 = le32_encode_bits(v: connect, RTW89_H2C_BCNFLTR_W0_MON_RSSI) |
3558 le32_encode_bits(v: connect, RTW89_H2C_BCNFLTR_W0_MON_BCN) |
3559 le32_encode_bits(v: connect, RTW89_H2C_BCNFLTR_W0_MON_EN) |
3560 le32_encode_bits(v: RTW89_BCN_FLTR_OFFLOAD_MODE_DEFAULT,
3561 RTW89_H2C_BCNFLTR_W0_MODE) |
3562 le32_encode_bits(RTW89_BCN_LOSS_CNT, RTW89_H2C_BCNFLTR_W0_BCN_LOSS_CNT) |
3563 le32_encode_bits(v: hyst, RTW89_H2C_BCNFLTR_W0_RSSI_HYST) |
3564 le32_encode_bits(v: thold + MAX_RSSI,
3565 RTW89_H2C_BCNFLTR_W0_RSSI_THRESHOLD) |
3566 le32_encode_bits(v: rtwvif->mac_id, RTW89_H2C_BCNFLTR_W0_MAC_ID);
3567
3568 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3569 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
3570 func: H2C_FUNC_CFG_BCNFLTR, rack: 0, dack: 1, len);
3571
3572 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3573 if (ret) {
3574 rtw89_err(rtwdev, "failed to send h2c\n");
3575 goto fail;
3576 }
3577
3578 return 0;
3579fail:
3580 dev_kfree_skb_any(skb);
3581
3582 return ret;
3583}
3584
3585int rtw89_fw_h2c_rssi_offload(struct rtw89_dev *rtwdev,
3586 struct rtw89_rx_phy_ppdu *phy_ppdu)
3587{
3588 struct rtw89_h2c_ofld_rssi *h2c;
3589 u32 len = sizeof(*h2c);
3590 struct sk_buff *skb;
3591 s8 rssi;
3592 int ret;
3593
3594 if (!RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
3595 return -EINVAL;
3596
3597 if (!phy_ppdu)
3598 return -EINVAL;
3599
3600 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3601 if (!skb) {
3602 rtw89_err(rtwdev, "failed to alloc skb for h2c rssi\n");
3603 return -ENOMEM;
3604 }
3605
3606 rssi = phy_ppdu->rssi_avg >> RSSI_FACTOR;
3607 skb_put(skb, len);
3608 h2c = (struct rtw89_h2c_ofld_rssi *)skb->data;
3609
3610 h2c->w0 = le32_encode_bits(v: phy_ppdu->mac_id, RTW89_H2C_OFLD_RSSI_W0_MACID) |
3611 le32_encode_bits(v: 1, RTW89_H2C_OFLD_RSSI_W0_NUM);
3612 h2c->w1 = le32_encode_bits(v: rssi, RTW89_H2C_OFLD_RSSI_W1_VAL);
3613
3614 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3615 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
3616 func: H2C_FUNC_OFLD_RSSI, rack: 0, dack: 1, len);
3617
3618 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3619 if (ret) {
3620 rtw89_err(rtwdev, "failed to send h2c\n");
3621 goto fail;
3622 }
3623
3624 return 0;
3625fail:
3626 dev_kfree_skb_any(skb);
3627
3628 return ret;
3629}
3630
3631int rtw89_fw_h2c_tp_offload(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
3632{
3633 struct rtw89_traffic_stats *stats = &rtwvif->stats;
3634 struct rtw89_h2c_ofld *h2c;
3635 u32 len = sizeof(*h2c);
3636 struct sk_buff *skb;
3637 int ret;
3638
3639 if (rtwvif->net_type != RTW89_NET_TYPE_INFRA)
3640 return -EINVAL;
3641
3642 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3643 if (!skb) {
3644 rtw89_err(rtwdev, "failed to alloc skb for h2c tp\n");
3645 return -ENOMEM;
3646 }
3647
3648 skb_put(skb, len);
3649 h2c = (struct rtw89_h2c_ofld *)skb->data;
3650
3651 h2c->w0 = le32_encode_bits(v: rtwvif->mac_id, RTW89_H2C_OFLD_W0_MAC_ID) |
3652 le32_encode_bits(v: stats->tx_throughput, RTW89_H2C_OFLD_W0_TX_TP) |
3653 le32_encode_bits(v: stats->rx_throughput, RTW89_H2C_OFLD_W0_RX_TP);
3654
3655 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3656 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
3657 func: H2C_FUNC_OFLD_TP, rack: 0, dack: 1, len);
3658
3659 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3660 if (ret) {
3661 rtw89_err(rtwdev, "failed to send h2c\n");
3662 goto fail;
3663 }
3664
3665 return 0;
3666fail:
3667 dev_kfree_skb_any(skb);
3668
3669 return ret;
3670}
3671
3672int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi)
3673{
3674 const struct rtw89_chip_info *chip = rtwdev->chip;
3675 struct rtw89_h2c_ra_v1 *h2c_v1;
3676 struct rtw89_h2c_ra *h2c;
3677 u32 len = sizeof(*h2c);
3678 bool format_v1 = false;
3679 struct sk_buff *skb;
3680 int ret;
3681
3682 if (chip->chip_gen == RTW89_CHIP_BE) {
3683 len = sizeof(*h2c_v1);
3684 format_v1 = true;
3685 }
3686
3687 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3688 if (!skb) {
3689 rtw89_err(rtwdev, "failed to alloc skb for h2c join\n");
3690 return -ENOMEM;
3691 }
3692 skb_put(skb, len);
3693 h2c = (struct rtw89_h2c_ra *)skb->data;
3694 rtw89_debug(rtwdev, mask: RTW89_DBG_RA,
3695 fmt: "ra cmd msk: %llx ", ra->ra_mask);
3696
3697 h2c->w0 = le32_encode_bits(v: ra->mode_ctrl, RTW89_H2C_RA_W0_MODE) |
3698 le32_encode_bits(v: ra->bw_cap, RTW89_H2C_RA_W0_BW_CAP) |
3699 le32_encode_bits(v: ra->macid, RTW89_H2C_RA_W0_MACID) |
3700 le32_encode_bits(v: ra->dcm_cap, RTW89_H2C_RA_W0_DCM) |
3701 le32_encode_bits(v: ra->er_cap, RTW89_H2C_RA_W0_ER) |
3702 le32_encode_bits(v: ra->init_rate_lv, RTW89_H2C_RA_W0_INIT_RATE_LV) |
3703 le32_encode_bits(v: ra->upd_all, RTW89_H2C_RA_W0_UPD_ALL) |
3704 le32_encode_bits(v: ra->en_sgi, RTW89_H2C_RA_W0_SGI) |
3705 le32_encode_bits(v: ra->ldpc_cap, RTW89_H2C_RA_W0_LDPC) |
3706 le32_encode_bits(v: ra->stbc_cap, RTW89_H2C_RA_W0_STBC) |
3707 le32_encode_bits(v: ra->ss_num, RTW89_H2C_RA_W0_SS_NUM) |
3708 le32_encode_bits(v: ra->giltf, RTW89_H2C_RA_W0_GILTF) |
3709 le32_encode_bits(v: ra->upd_bw_nss_mask, RTW89_H2C_RA_W0_UPD_BW_NSS_MASK) |
3710 le32_encode_bits(v: ra->upd_mask, RTW89_H2C_RA_W0_UPD_MASK);
3711 h2c->w1 = le32_encode_bits(v: ra->ra_mask, RTW89_H2C_RA_W1_RAMASK_LO32);
3712 h2c->w2 = le32_encode_bits(v: ra->ra_mask >> 32, RTW89_H2C_RA_W2_RAMASK_HI32);
3713 h2c->w3 = le32_encode_bits(v: ra->fix_giltf_en, RTW89_H2C_RA_W3_FIX_GILTF_EN) |
3714 le32_encode_bits(v: ra->fix_giltf, RTW89_H2C_RA_W3_FIX_GILTF);
3715
3716 if (!format_v1)
3717 goto csi;
3718
3719 h2c_v1 = (struct rtw89_h2c_ra_v1 *)h2c;
3720 h2c_v1->w4 = le32_encode_bits(v: ra->mode_ctrl, RTW89_H2C_RA_V1_W4_MODE_EHT) |
3721 le32_encode_bits(v: ra->bw_cap, RTW89_H2C_RA_V1_W4_BW_EHT);
3722
3723csi:
3724 if (!csi)
3725 goto done;
3726
3727 h2c->w2 |= le32_encode_bits(v: 1, RTW89_H2C_RA_W2_BFEE_CSI_CTL);
3728 h2c->w3 |= le32_encode_bits(v: ra->band_num, RTW89_H2C_RA_W3_BAND_NUM) |
3729 le32_encode_bits(v: ra->cr_tbl_sel, RTW89_H2C_RA_W3_CR_TBL_SEL) |
3730 le32_encode_bits(v: ra->fixed_csi_rate_en, RTW89_H2C_RA_W3_FIXED_CSI_RATE_EN) |
3731 le32_encode_bits(v: ra->ra_csi_rate_en, RTW89_H2C_RA_W3_RA_CSI_RATE_EN) |
3732 le32_encode_bits(v: ra->csi_mcs_ss_idx, RTW89_H2C_RA_W3_FIXED_CSI_MCS_SS_IDX) |
3733 le32_encode_bits(v: ra->csi_mode, RTW89_H2C_RA_W3_FIXED_CSI_MODE) |
3734 le32_encode_bits(v: ra->csi_gi_ltf, RTW89_H2C_RA_W3_FIXED_CSI_GI_LTF) |
3735 le32_encode_bits(v: ra->csi_bw, RTW89_H2C_RA_W3_FIXED_CSI_BW);
3736
3737done:
3738 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3739 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RA,
3740 H2C_FUNC_OUTSRC_RA_MACIDCFG, rack: 0, dack: 0,
3741 len);
3742
3743 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3744 if (ret) {
3745 rtw89_err(rtwdev, "failed to send h2c\n");
3746 goto fail;
3747 }
3748
3749 return 0;
3750fail:
3751 dev_kfree_skb_any(skb);
3752
3753 return ret;
3754}
3755
3756int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev, u8 type)
3757{
3758 struct rtw89_btc *btc = &rtwdev->btc;
3759 struct rtw89_btc_dm *dm = &btc->dm;
3760 struct rtw89_btc_init_info *init_info = &dm->init_info.init;
3761 struct rtw89_btc_module *module = &init_info->module;
3762 struct rtw89_btc_ant_info *ant = &module->ant;
3763 struct rtw89_h2c_cxinit *h2c;
3764 u32 len = sizeof(*h2c);
3765 struct sk_buff *skb;
3766 int ret;
3767
3768 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3769 if (!skb) {
3770 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_init\n");
3771 return -ENOMEM;
3772 }
3773 skb_put(skb, len);
3774 h2c = (struct rtw89_h2c_cxinit *)skb->data;
3775
3776 h2c->hdr.type = type;
3777 h2c->hdr.len = len - H2C_LEN_CXDRVHDR;
3778
3779 h2c->ant_type = ant->type;
3780 h2c->ant_num = ant->num;
3781 h2c->ant_iso = ant->isolation;
3782 h2c->ant_info =
3783 u8_encode_bits(v: ant->single_pos, RTW89_H2C_CXINIT_ANT_INFO_POS) |
3784 u8_encode_bits(v: ant->diversity, RTW89_H2C_CXINIT_ANT_INFO_DIVERSITY) |
3785 u8_encode_bits(v: ant->btg_pos, RTW89_H2C_CXINIT_ANT_INFO_BTG_POS) |
3786 u8_encode_bits(v: ant->stream_cnt, RTW89_H2C_CXINIT_ANT_INFO_STREAM_CNT);
3787
3788 h2c->mod_rfe = module->rfe_type;
3789 h2c->mod_cv = module->cv;
3790 h2c->mod_info =
3791 u8_encode_bits(v: module->bt_solo, RTW89_H2C_CXINIT_MOD_INFO_BT_SOLO) |
3792 u8_encode_bits(v: module->bt_pos, RTW89_H2C_CXINIT_MOD_INFO_BT_POS) |
3793 u8_encode_bits(v: module->switch_type, RTW89_H2C_CXINIT_MOD_INFO_SW_TYPE) |
3794 u8_encode_bits(v: module->wa_type, RTW89_H2C_CXINIT_MOD_INFO_WA_TYPE);
3795 h2c->mod_adie_kt = module->kt_ver_adie;
3796 h2c->wl_gch = init_info->wl_guard_ch;
3797
3798 h2c->info =
3799 u8_encode_bits(v: init_info->wl_only, RTW89_H2C_CXINIT_INFO_WL_ONLY) |
3800 u8_encode_bits(v: init_info->wl_init_ok, RTW89_H2C_CXINIT_INFO_WL_INITOK) |
3801 u8_encode_bits(v: init_info->dbcc_en, RTW89_H2C_CXINIT_INFO_DBCC_EN) |
3802 u8_encode_bits(v: init_info->cx_other, RTW89_H2C_CXINIT_INFO_CX_OTHER) |
3803 u8_encode_bits(v: init_info->bt_only, RTW89_H2C_CXINIT_INFO_BT_ONLY);
3804
3805 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3806 H2C_CAT_OUTSRC, class: BTFC_SET,
3807 func: SET_DRV_INFO, rack: 0, dack: 0,
3808 len);
3809
3810 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3811 if (ret) {
3812 rtw89_err(rtwdev, "failed to send h2c\n");
3813 goto fail;
3814 }
3815
3816 return 0;
3817fail:
3818 dev_kfree_skb_any(skb);
3819
3820 return ret;
3821}
3822
3823int rtw89_fw_h2c_cxdrv_init_v7(struct rtw89_dev *rtwdev, u8 type)
3824{
3825 struct rtw89_btc *btc = &rtwdev->btc;
3826 struct rtw89_btc_dm *dm = &btc->dm;
3827 struct rtw89_btc_init_info_v7 *init_info = &dm->init_info.init_v7;
3828 struct rtw89_h2c_cxinit_v7 *h2c;
3829 u32 len = sizeof(*h2c);
3830 struct sk_buff *skb;
3831 int ret;
3832
3833 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3834 if (!skb) {
3835 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_init_v7\n");
3836 return -ENOMEM;
3837 }
3838 skb_put(skb, len);
3839 h2c = (struct rtw89_h2c_cxinit_v7 *)skb->data;
3840
3841 h2c->hdr.type = type;
3842 h2c->hdr.ver = btc->ver->fcxinit;
3843 h2c->hdr.len = len - H2C_LEN_CXDRVHDR_V7;
3844 h2c->init = *init_info;
3845
3846 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3847 H2C_CAT_OUTSRC, class: BTFC_SET,
3848 func: SET_DRV_INFO, rack: 0, dack: 0,
3849 len);
3850
3851 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3852 if (ret) {
3853 rtw89_err(rtwdev, "failed to send h2c\n");
3854 goto fail;
3855 }
3856
3857 return 0;
3858fail:
3859 dev_kfree_skb_any(skb);
3860
3861 return ret;
3862}
3863
3864#define PORT_DATA_OFFSET 4
3865#define H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN 12
3866#define H2C_LEN_CXDRVINFO_ROLE_SIZE(max_role_num) \
3867 (4 + 12 * (max_role_num) + H2C_LEN_CXDRVHDR)
3868
3869int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev, u8 type)
3870{
3871 struct rtw89_btc *btc = &rtwdev->btc;
3872 const struct rtw89_btc_ver *ver = btc->ver;
3873 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3874 struct rtw89_btc_wl_role_info *role_info = &wl->role_info;
3875 struct rtw89_btc_wl_role_info_bpos *bpos = &role_info->role_map.role;
3876 struct rtw89_btc_wl_active_role *active = role_info->active_role;
3877 struct sk_buff *skb;
3878 u32 len;
3879 u8 offset = 0;
3880 u8 *cmd;
3881 int ret;
3882 int i;
3883
3884 len = H2C_LEN_CXDRVINFO_ROLE_SIZE(ver->max_role_num);
3885
3886 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3887 if (!skb) {
3888 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_role\n");
3889 return -ENOMEM;
3890 }
3891 skb_put(skb, len);
3892 cmd = skb->data;
3893
3894 RTW89_SET_FWCMD_CXHDR_TYPE(cmd, val: type);
3895 RTW89_SET_FWCMD_CXHDR_LEN(cmd, val: len - H2C_LEN_CXDRVHDR);
3896
3897 RTW89_SET_FWCMD_CXROLE_CONNECT_CNT(cmd, val: role_info->connect_cnt);
3898 RTW89_SET_FWCMD_CXROLE_LINK_MODE(cmd, val: role_info->link_mode);
3899
3900 RTW89_SET_FWCMD_CXROLE_ROLE_NONE(cmd, val: bpos->none);
3901 RTW89_SET_FWCMD_CXROLE_ROLE_STA(cmd, val: bpos->station);
3902 RTW89_SET_FWCMD_CXROLE_ROLE_AP(cmd, val: bpos->ap);
3903 RTW89_SET_FWCMD_CXROLE_ROLE_VAP(cmd, val: bpos->vap);
3904 RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC(cmd, val: bpos->adhoc);
3905 RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC_MASTER(cmd, val: bpos->adhoc_master);
3906 RTW89_SET_FWCMD_CXROLE_ROLE_MESH(cmd, val: bpos->mesh);
3907 RTW89_SET_FWCMD_CXROLE_ROLE_MONITOR(cmd, val: bpos->moniter);
3908 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_DEV(cmd, val: bpos->p2p_device);
3909 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GC(cmd, val: bpos->p2p_gc);
3910 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GO(cmd, val: bpos->p2p_go);
3911 RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, val: bpos->nan);
3912
3913 for (i = 0; i < RTW89_PORT_NUM; i++, active++) {
3914 RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, val: active->connected, n: i, offset);
3915 RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, val: active->pid, n: i, offset);
3916 RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, val: active->phy, n: i, offset);
3917 RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, val: active->noa, n: i, offset);
3918 RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, val: active->band, n: i, offset);
3919 RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, val: active->client_ps, n: i, offset);
3920 RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, val: active->bw, n: i, offset);
3921 RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, val: active->role, n: i, offset);
3922 RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, val: active->ch, n: i, offset);
3923 RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, val: active->tx_lvl, n: i, offset);
3924 RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, val: active->rx_lvl, n: i, offset);
3925 RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, val: active->tx_rate, n: i, offset);
3926 RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, val: active->rx_rate, n: i, offset);
3927 }
3928
3929 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
3930 H2C_CAT_OUTSRC, class: BTFC_SET,
3931 func: SET_DRV_INFO, rack: 0, dack: 0,
3932 len);
3933
3934 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
3935 if (ret) {
3936 rtw89_err(rtwdev, "failed to send h2c\n");
3937 goto fail;
3938 }
3939
3940 return 0;
3941fail:
3942 dev_kfree_skb_any(skb);
3943
3944 return ret;
3945}
3946
3947#define H2C_LEN_CXDRVINFO_ROLE_SIZE_V1(max_role_num) \
3948 (4 + 16 * (max_role_num) + H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN + H2C_LEN_CXDRVHDR)
3949
3950int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev, u8 type)
3951{
3952 struct rtw89_btc *btc = &rtwdev->btc;
3953 const struct rtw89_btc_ver *ver = btc->ver;
3954 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
3955 struct rtw89_btc_wl_role_info_v1 *role_info = &wl->role_info_v1;
3956 struct rtw89_btc_wl_role_info_bpos *bpos = &role_info->role_map.role;
3957 struct rtw89_btc_wl_active_role_v1 *active = role_info->active_role_v1;
3958 struct sk_buff *skb;
3959 u32 len;
3960 u8 *cmd, offset;
3961 int ret;
3962 int i;
3963
3964 len = H2C_LEN_CXDRVINFO_ROLE_SIZE_V1(ver->max_role_num);
3965
3966 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
3967 if (!skb) {
3968 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_role\n");
3969 return -ENOMEM;
3970 }
3971 skb_put(skb, len);
3972 cmd = skb->data;
3973
3974 RTW89_SET_FWCMD_CXHDR_TYPE(cmd, val: type);
3975 RTW89_SET_FWCMD_CXHDR_LEN(cmd, val: len - H2C_LEN_CXDRVHDR);
3976
3977 RTW89_SET_FWCMD_CXROLE_CONNECT_CNT(cmd, val: role_info->connect_cnt);
3978 RTW89_SET_FWCMD_CXROLE_LINK_MODE(cmd, val: role_info->link_mode);
3979
3980 RTW89_SET_FWCMD_CXROLE_ROLE_NONE(cmd, val: bpos->none);
3981 RTW89_SET_FWCMD_CXROLE_ROLE_STA(cmd, val: bpos->station);
3982 RTW89_SET_FWCMD_CXROLE_ROLE_AP(cmd, val: bpos->ap);
3983 RTW89_SET_FWCMD_CXROLE_ROLE_VAP(cmd, val: bpos->vap);
3984 RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC(cmd, val: bpos->adhoc);
3985 RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC_MASTER(cmd, val: bpos->adhoc_master);
3986 RTW89_SET_FWCMD_CXROLE_ROLE_MESH(cmd, val: bpos->mesh);
3987 RTW89_SET_FWCMD_CXROLE_ROLE_MONITOR(cmd, val: bpos->moniter);
3988 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_DEV(cmd, val: bpos->p2p_device);
3989 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GC(cmd, val: bpos->p2p_gc);
3990 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GO(cmd, val: bpos->p2p_go);
3991 RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, val: bpos->nan);
3992
3993 offset = PORT_DATA_OFFSET;
3994 for (i = 0; i < RTW89_PORT_NUM; i++, active++) {
3995 RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, val: active->connected, n: i, offset);
3996 RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, val: active->pid, n: i, offset);
3997 RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, val: active->phy, n: i, offset);
3998 RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, val: active->noa, n: i, offset);
3999 RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, val: active->band, n: i, offset);
4000 RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, val: active->client_ps, n: i, offset);
4001 RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, val: active->bw, n: i, offset);
4002 RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, val: active->role, n: i, offset);
4003 RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, val: active->ch, n: i, offset);
4004 RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, val: active->tx_lvl, n: i, offset);
4005 RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, val: active->rx_lvl, n: i, offset);
4006 RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, val: active->tx_rate, n: i, offset);
4007 RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, val: active->rx_rate, n: i, offset);
4008 RTW89_SET_FWCMD_CXROLE_ACT_NOA_DUR(cmd, val: active->noa_duration, n: i, offset);
4009 }
4010
4011 offset = len - H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN;
4012 RTW89_SET_FWCMD_CXROLE_MROLE_TYPE(cmd, val: role_info->mrole_type, offset);
4013 RTW89_SET_FWCMD_CXROLE_MROLE_NOA(cmd, val: role_info->mrole_noa_duration, offset);
4014 RTW89_SET_FWCMD_CXROLE_DBCC_EN(cmd, val: role_info->dbcc_en, offset);
4015 RTW89_SET_FWCMD_CXROLE_DBCC_CHG(cmd, val: role_info->dbcc_chg, offset);
4016 RTW89_SET_FWCMD_CXROLE_DBCC_2G_PHY(cmd, val: role_info->dbcc_2g_phy, offset);
4017 RTW89_SET_FWCMD_CXROLE_LINK_MODE_CHG(cmd, val: role_info->link_mode_chg, offset);
4018
4019 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4020 H2C_CAT_OUTSRC, class: BTFC_SET,
4021 func: SET_DRV_INFO, rack: 0, dack: 0,
4022 len);
4023
4024 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4025 if (ret) {
4026 rtw89_err(rtwdev, "failed to send h2c\n");
4027 goto fail;
4028 }
4029
4030 return 0;
4031fail:
4032 dev_kfree_skb_any(skb);
4033
4034 return ret;
4035}
4036
4037#define H2C_LEN_CXDRVINFO_ROLE_SIZE_V2(max_role_num) \
4038 (4 + 8 * (max_role_num) + H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN + H2C_LEN_CXDRVHDR)
4039
4040int rtw89_fw_h2c_cxdrv_role_v2(struct rtw89_dev *rtwdev, u8 type)
4041{
4042 struct rtw89_btc *btc = &rtwdev->btc;
4043 const struct rtw89_btc_ver *ver = btc->ver;
4044 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4045 struct rtw89_btc_wl_role_info_v2 *role_info = &wl->role_info_v2;
4046 struct rtw89_btc_wl_role_info_bpos *bpos = &role_info->role_map.role;
4047 struct rtw89_btc_wl_active_role_v2 *active = role_info->active_role_v2;
4048 struct sk_buff *skb;
4049 u32 len;
4050 u8 *cmd, offset;
4051 int ret;
4052 int i;
4053
4054 len = H2C_LEN_CXDRVINFO_ROLE_SIZE_V2(ver->max_role_num);
4055
4056 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4057 if (!skb) {
4058 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_role\n");
4059 return -ENOMEM;
4060 }
4061 skb_put(skb, len);
4062 cmd = skb->data;
4063
4064 RTW89_SET_FWCMD_CXHDR_TYPE(cmd, val: type);
4065 RTW89_SET_FWCMD_CXHDR_LEN(cmd, val: len - H2C_LEN_CXDRVHDR);
4066
4067 RTW89_SET_FWCMD_CXROLE_CONNECT_CNT(cmd, val: role_info->connect_cnt);
4068 RTW89_SET_FWCMD_CXROLE_LINK_MODE(cmd, val: role_info->link_mode);
4069
4070 RTW89_SET_FWCMD_CXROLE_ROLE_NONE(cmd, val: bpos->none);
4071 RTW89_SET_FWCMD_CXROLE_ROLE_STA(cmd, val: bpos->station);
4072 RTW89_SET_FWCMD_CXROLE_ROLE_AP(cmd, val: bpos->ap);
4073 RTW89_SET_FWCMD_CXROLE_ROLE_VAP(cmd, val: bpos->vap);
4074 RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC(cmd, val: bpos->adhoc);
4075 RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC_MASTER(cmd, val: bpos->adhoc_master);
4076 RTW89_SET_FWCMD_CXROLE_ROLE_MESH(cmd, val: bpos->mesh);
4077 RTW89_SET_FWCMD_CXROLE_ROLE_MONITOR(cmd, val: bpos->moniter);
4078 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_DEV(cmd, val: bpos->p2p_device);
4079 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GC(cmd, val: bpos->p2p_gc);
4080 RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GO(cmd, val: bpos->p2p_go);
4081 RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, val: bpos->nan);
4082
4083 offset = PORT_DATA_OFFSET;
4084 for (i = 0; i < RTW89_PORT_NUM; i++, active++) {
4085 RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED_V2(cmd, val: active->connected, n: i, offset);
4086 RTW89_SET_FWCMD_CXROLE_ACT_PID_V2(cmd, val: active->pid, n: i, offset);
4087 RTW89_SET_FWCMD_CXROLE_ACT_PHY_V2(cmd, val: active->phy, n: i, offset);
4088 RTW89_SET_FWCMD_CXROLE_ACT_NOA_V2(cmd, val: active->noa, n: i, offset);
4089 RTW89_SET_FWCMD_CXROLE_ACT_BAND_V2(cmd, val: active->band, n: i, offset);
4090 RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS_V2(cmd, val: active->client_ps, n: i, offset);
4091 RTW89_SET_FWCMD_CXROLE_ACT_BW_V2(cmd, val: active->bw, n: i, offset);
4092 RTW89_SET_FWCMD_CXROLE_ACT_ROLE_V2(cmd, val: active->role, n: i, offset);
4093 RTW89_SET_FWCMD_CXROLE_ACT_CH_V2(cmd, val: active->ch, n: i, offset);
4094 RTW89_SET_FWCMD_CXROLE_ACT_NOA_DUR_V2(cmd, val: active->noa_duration, n: i, offset);
4095 }
4096
4097 offset = len - H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN;
4098 RTW89_SET_FWCMD_CXROLE_MROLE_TYPE(cmd, val: role_info->mrole_type, offset);
4099 RTW89_SET_FWCMD_CXROLE_MROLE_NOA(cmd, val: role_info->mrole_noa_duration, offset);
4100 RTW89_SET_FWCMD_CXROLE_DBCC_EN(cmd, val: role_info->dbcc_en, offset);
4101 RTW89_SET_FWCMD_CXROLE_DBCC_CHG(cmd, val: role_info->dbcc_chg, offset);
4102 RTW89_SET_FWCMD_CXROLE_DBCC_2G_PHY(cmd, val: role_info->dbcc_2g_phy, offset);
4103 RTW89_SET_FWCMD_CXROLE_LINK_MODE_CHG(cmd, val: role_info->link_mode_chg, offset);
4104
4105 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4106 H2C_CAT_OUTSRC, class: BTFC_SET,
4107 func: SET_DRV_INFO, rack: 0, dack: 0,
4108 len);
4109
4110 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4111 if (ret) {
4112 rtw89_err(rtwdev, "failed to send h2c\n");
4113 goto fail;
4114 }
4115
4116 return 0;
4117fail:
4118 dev_kfree_skb_any(skb);
4119
4120 return ret;
4121}
4122
4123#define H2C_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR)
4124int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev, u8 type)
4125{
4126 struct rtw89_btc *btc = &rtwdev->btc;
4127 const struct rtw89_btc_ver *ver = btc->ver;
4128 struct rtw89_btc_ctrl *ctrl = &btc->ctrl.ctrl;
4129 struct sk_buff *skb;
4130 u8 *cmd;
4131 int ret;
4132
4133 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_CTRL);
4134 if (!skb) {
4135 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n");
4136 return -ENOMEM;
4137 }
4138 skb_put(skb, H2C_LEN_CXDRVINFO_CTRL);
4139 cmd = skb->data;
4140
4141 RTW89_SET_FWCMD_CXHDR_TYPE(cmd, val: type);
4142 RTW89_SET_FWCMD_CXHDR_LEN(cmd, H2C_LEN_CXDRVINFO_CTRL - H2C_LEN_CXDRVHDR);
4143
4144 RTW89_SET_FWCMD_CXCTRL_MANUAL(cmd, val: ctrl->manual);
4145 RTW89_SET_FWCMD_CXCTRL_IGNORE_BT(cmd, val: ctrl->igno_bt);
4146 RTW89_SET_FWCMD_CXCTRL_ALWAYS_FREERUN(cmd, val: ctrl->always_freerun);
4147 if (ver->fcxctrl == 0)
4148 RTW89_SET_FWCMD_CXCTRL_TRACE_STEP(cmd, val: ctrl->trace_step);
4149
4150 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4151 H2C_CAT_OUTSRC, class: BTFC_SET,
4152 func: SET_DRV_INFO, rack: 0, dack: 0,
4153 H2C_LEN_CXDRVINFO_CTRL);
4154
4155 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4156 if (ret) {
4157 rtw89_err(rtwdev, "failed to send h2c\n");
4158 goto fail;
4159 }
4160
4161 return 0;
4162fail:
4163 dev_kfree_skb_any(skb);
4164
4165 return ret;
4166}
4167
4168int rtw89_fw_h2c_cxdrv_ctrl_v7(struct rtw89_dev *rtwdev, u8 type)
4169{
4170 struct rtw89_btc *btc = &rtwdev->btc;
4171 struct rtw89_btc_ctrl_v7 *ctrl = &btc->ctrl.ctrl_v7;
4172 struct rtw89_h2c_cxctrl_v7 *h2c;
4173 u32 len = sizeof(*h2c);
4174 struct sk_buff *skb;
4175 int ret;
4176
4177 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4178 if (!skb) {
4179 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n");
4180 return -ENOMEM;
4181 }
4182 skb_put(skb, len);
4183 h2c = (struct rtw89_h2c_cxctrl_v7 *)skb->data;
4184
4185 h2c->hdr.type = type;
4186 h2c->hdr.ver = btc->ver->fcxctrl;
4187 h2c->hdr.len = sizeof(*h2c) - H2C_LEN_CXDRVHDR_V7;
4188 h2c->ctrl = *ctrl;
4189
4190 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4191 H2C_CAT_OUTSRC, class: BTFC_SET,
4192 func: SET_DRV_INFO, rack: 0, dack: 0, len);
4193
4194 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4195 if (ret) {
4196 rtw89_err(rtwdev, "failed to send h2c\n");
4197 goto fail;
4198 }
4199
4200 return 0;
4201fail:
4202 dev_kfree_skb_any(skb);
4203
4204 return ret;
4205}
4206
4207#define H2C_LEN_CXDRVINFO_TRX (28 + H2C_LEN_CXDRVHDR)
4208int rtw89_fw_h2c_cxdrv_trx(struct rtw89_dev *rtwdev, u8 type)
4209{
4210 struct rtw89_btc *btc = &rtwdev->btc;
4211 struct rtw89_btc_trx_info *trx = &btc->dm.trx_info;
4212 struct sk_buff *skb;
4213 u8 *cmd;
4214 int ret;
4215
4216 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_TRX);
4217 if (!skb) {
4218 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_trx\n");
4219 return -ENOMEM;
4220 }
4221 skb_put(skb, H2C_LEN_CXDRVINFO_TRX);
4222 cmd = skb->data;
4223
4224 RTW89_SET_FWCMD_CXHDR_TYPE(cmd, val: type);
4225 RTW89_SET_FWCMD_CXHDR_LEN(cmd, H2C_LEN_CXDRVINFO_TRX - H2C_LEN_CXDRVHDR);
4226
4227 RTW89_SET_FWCMD_CXTRX_TXLV(cmd, val: trx->tx_lvl);
4228 RTW89_SET_FWCMD_CXTRX_RXLV(cmd, val: trx->rx_lvl);
4229 RTW89_SET_FWCMD_CXTRX_WLRSSI(cmd, val: trx->wl_rssi);
4230 RTW89_SET_FWCMD_CXTRX_BTRSSI(cmd, val: trx->bt_rssi);
4231 RTW89_SET_FWCMD_CXTRX_TXPWR(cmd, val: trx->tx_power);
4232 RTW89_SET_FWCMD_CXTRX_RXGAIN(cmd, val: trx->rx_gain);
4233 RTW89_SET_FWCMD_CXTRX_BTTXPWR(cmd, val: trx->bt_tx_power);
4234 RTW89_SET_FWCMD_CXTRX_BTRXGAIN(cmd, val: trx->bt_rx_gain);
4235 RTW89_SET_FWCMD_CXTRX_CN(cmd, val: trx->cn);
4236 RTW89_SET_FWCMD_CXTRX_NHM(cmd, val: trx->nhm);
4237 RTW89_SET_FWCMD_CXTRX_BTPROFILE(cmd, val: trx->bt_profile);
4238 RTW89_SET_FWCMD_CXTRX_RSVD2(cmd, val: trx->rsvd2);
4239 RTW89_SET_FWCMD_CXTRX_TXRATE(cmd, val: trx->tx_rate);
4240 RTW89_SET_FWCMD_CXTRX_RXRATE(cmd, val: trx->rx_rate);
4241 RTW89_SET_FWCMD_CXTRX_TXTP(cmd, val: trx->tx_tp);
4242 RTW89_SET_FWCMD_CXTRX_RXTP(cmd, val: trx->rx_tp);
4243 RTW89_SET_FWCMD_CXTRX_RXERRRA(cmd, val: trx->rx_err_ratio);
4244
4245 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4246 H2C_CAT_OUTSRC, class: BTFC_SET,
4247 func: SET_DRV_INFO, rack: 0, dack: 0,
4248 H2C_LEN_CXDRVINFO_TRX);
4249
4250 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4251 if (ret) {
4252 rtw89_err(rtwdev, "failed to send h2c\n");
4253 goto fail;
4254 }
4255
4256 return 0;
4257fail:
4258 dev_kfree_skb_any(skb);
4259
4260 return ret;
4261}
4262
4263#define H2C_LEN_CXDRVINFO_RFK (4 + H2C_LEN_CXDRVHDR)
4264int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev, u8 type)
4265{
4266 struct rtw89_btc *btc = &rtwdev->btc;
4267 struct rtw89_btc_wl_info *wl = &btc->cx.wl;
4268 struct rtw89_btc_wl_rfk_info *rfk_info = &wl->rfk_info;
4269 struct sk_buff *skb;
4270 u8 *cmd;
4271 int ret;
4272
4273 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_RFK);
4274 if (!skb) {
4275 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n");
4276 return -ENOMEM;
4277 }
4278 skb_put(skb, H2C_LEN_CXDRVINFO_RFK);
4279 cmd = skb->data;
4280
4281 RTW89_SET_FWCMD_CXHDR_TYPE(cmd, val: type);
4282 RTW89_SET_FWCMD_CXHDR_LEN(cmd, H2C_LEN_CXDRVINFO_RFK - H2C_LEN_CXDRVHDR);
4283
4284 RTW89_SET_FWCMD_CXRFK_STATE(cmd, val: rfk_info->state);
4285 RTW89_SET_FWCMD_CXRFK_PATH_MAP(cmd, val: rfk_info->path_map);
4286 RTW89_SET_FWCMD_CXRFK_PHY_MAP(cmd, val: rfk_info->phy_map);
4287 RTW89_SET_FWCMD_CXRFK_BAND(cmd, val: rfk_info->band);
4288 RTW89_SET_FWCMD_CXRFK_TYPE(cmd, val: rfk_info->type);
4289
4290 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4291 H2C_CAT_OUTSRC, class: BTFC_SET,
4292 func: SET_DRV_INFO, rack: 0, dack: 0,
4293 H2C_LEN_CXDRVINFO_RFK);
4294
4295 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4296 if (ret) {
4297 rtw89_err(rtwdev, "failed to send h2c\n");
4298 goto fail;
4299 }
4300
4301 return 0;
4302fail:
4303 dev_kfree_skb_any(skb);
4304
4305 return ret;
4306}
4307
4308#define H2C_LEN_PKT_OFLD 4
4309int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id)
4310{
4311 struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
4312 struct sk_buff *skb;
4313 unsigned int cond;
4314 u8 *cmd;
4315 int ret;
4316
4317 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_PKT_OFLD);
4318 if (!skb) {
4319 rtw89_err(rtwdev, "failed to alloc skb for h2c pkt offload\n");
4320 return -ENOMEM;
4321 }
4322 skb_put(skb, H2C_LEN_PKT_OFLD);
4323 cmd = skb->data;
4324
4325 RTW89_SET_FWCMD_PACKET_OFLD_PKT_IDX(cmd, val: id);
4326 RTW89_SET_FWCMD_PACKET_OFLD_PKT_OP(cmd, val: RTW89_PKT_OFLD_OP_DEL);
4327
4328 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4329 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
4330 func: H2C_FUNC_PACKET_OFLD, rack: 1, dack: 1,
4331 H2C_LEN_PKT_OFLD);
4332
4333 cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(id, RTW89_PKT_OFLD_OP_DEL);
4334
4335 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
4336 if (ret < 0) {
4337 rtw89_debug(rtwdev, mask: RTW89_DBG_FW,
4338 fmt: "failed to del pkt ofld: id %d, ret %d\n",
4339 id, ret);
4340 return ret;
4341 }
4342
4343 rtw89_core_release_bit_map(addr: rtwdev->pkt_offload, bit: id);
4344 return 0;
4345}
4346
4347int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id,
4348 struct sk_buff *skb_ofld)
4349{
4350 struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
4351 struct sk_buff *skb;
4352 unsigned int cond;
4353 u8 *cmd;
4354 u8 alloc_id;
4355 int ret;
4356
4357 alloc_id = rtw89_core_acquire_bit_map(addr: rtwdev->pkt_offload,
4358 RTW89_MAX_PKT_OFLD_NUM);
4359 if (alloc_id == RTW89_MAX_PKT_OFLD_NUM)
4360 return -ENOSPC;
4361
4362 *id = alloc_id;
4363
4364 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_PKT_OFLD + skb_ofld->len);
4365 if (!skb) {
4366 rtw89_err(rtwdev, "failed to alloc skb for h2c pkt offload\n");
4367 rtw89_core_release_bit_map(addr: rtwdev->pkt_offload, bit: alloc_id);
4368 return -ENOMEM;
4369 }
4370 skb_put(skb, H2C_LEN_PKT_OFLD);
4371 cmd = skb->data;
4372
4373 RTW89_SET_FWCMD_PACKET_OFLD_PKT_IDX(cmd, val: alloc_id);
4374 RTW89_SET_FWCMD_PACKET_OFLD_PKT_OP(cmd, val: RTW89_PKT_OFLD_OP_ADD);
4375 RTW89_SET_FWCMD_PACKET_OFLD_PKT_LENGTH(cmd, val: skb_ofld->len);
4376 skb_put_data(skb, data: skb_ofld->data, len: skb_ofld->len);
4377
4378 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4379 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
4380 func: H2C_FUNC_PACKET_OFLD, rack: 1, dack: 1,
4381 H2C_LEN_PKT_OFLD + skb_ofld->len);
4382
4383 cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(alloc_id, RTW89_PKT_OFLD_OP_ADD);
4384
4385 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
4386 if (ret < 0) {
4387 rtw89_debug(rtwdev, mask: RTW89_DBG_FW,
4388 fmt: "failed to add pkt ofld: id %d, ret %d\n",
4389 alloc_id, ret);
4390 rtw89_core_release_bit_map(addr: rtwdev->pkt_offload, bit: alloc_id);
4391 return ret;
4392 }
4393
4394 return 0;
4395}
4396
4397int rtw89_fw_h2c_scan_list_offload(struct rtw89_dev *rtwdev, int ch_num,
4398 struct list_head *chan_list)
4399{
4400 struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
4401 struct rtw89_h2c_chinfo_elem *elem;
4402 struct rtw89_mac_chinfo *ch_info;
4403 struct rtw89_h2c_chinfo *h2c;
4404 struct sk_buff *skb;
4405 unsigned int cond;
4406 int skb_len;
4407 int ret;
4408
4409 static_assert(sizeof(*elem) == RTW89_MAC_CHINFO_SIZE);
4410
4411 skb_len = struct_size(h2c, elem, ch_num);
4412 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len: skb_len);
4413 if (!skb) {
4414 rtw89_err(rtwdev, "failed to alloc skb for h2c scan list\n");
4415 return -ENOMEM;
4416 }
4417 skb_put(skb, len: sizeof(*h2c));
4418 h2c = (struct rtw89_h2c_chinfo *)skb->data;
4419
4420 h2c->ch_num = ch_num;
4421 h2c->elem_size = sizeof(*elem) / 4; /* in unit of 4 bytes */
4422
4423 list_for_each_entry(ch_info, chan_list, list) {
4424 elem = (struct rtw89_h2c_chinfo_elem *)skb_put(skb, len: sizeof(*elem));
4425
4426 elem->w0 = le32_encode_bits(v: ch_info->period, RTW89_H2C_CHINFO_W0_PERIOD) |
4427 le32_encode_bits(v: ch_info->dwell_time, RTW89_H2C_CHINFO_W0_DWELL) |
4428 le32_encode_bits(v: ch_info->central_ch, RTW89_H2C_CHINFO_W0_CENTER_CH) |
4429 le32_encode_bits(v: ch_info->pri_ch, RTW89_H2C_CHINFO_W0_PRI_CH);
4430
4431 elem->w1 = le32_encode_bits(v: ch_info->bw, RTW89_H2C_CHINFO_W1_BW) |
4432 le32_encode_bits(v: ch_info->notify_action, RTW89_H2C_CHINFO_W1_ACTION) |
4433 le32_encode_bits(v: ch_info->num_pkt, RTW89_H2C_CHINFO_W1_NUM_PKT) |
4434 le32_encode_bits(v: ch_info->tx_pkt, RTW89_H2C_CHINFO_W1_TX) |
4435 le32_encode_bits(v: ch_info->pause_data, RTW89_H2C_CHINFO_W1_PAUSE_DATA) |
4436 le32_encode_bits(v: ch_info->ch_band, RTW89_H2C_CHINFO_W1_BAND) |
4437 le32_encode_bits(v: ch_info->probe_id, RTW89_H2C_CHINFO_W1_PKT_ID) |
4438 le32_encode_bits(v: ch_info->dfs_ch, RTW89_H2C_CHINFO_W1_DFS) |
4439 le32_encode_bits(v: ch_info->tx_null, RTW89_H2C_CHINFO_W1_TX_NULL) |
4440 le32_encode_bits(v: ch_info->rand_seq_num, RTW89_H2C_CHINFO_W1_RANDOM);
4441
4442 elem->w2 = le32_encode_bits(v: ch_info->pkt_id[0], RTW89_H2C_CHINFO_W2_PKT0) |
4443 le32_encode_bits(v: ch_info->pkt_id[1], RTW89_H2C_CHINFO_W2_PKT1) |
4444 le32_encode_bits(v: ch_info->pkt_id[2], RTW89_H2C_CHINFO_W2_PKT2) |
4445 le32_encode_bits(v: ch_info->pkt_id[3], RTW89_H2C_CHINFO_W2_PKT3);
4446
4447 elem->w3 = le32_encode_bits(v: ch_info->pkt_id[4], RTW89_H2C_CHINFO_W3_PKT4) |
4448 le32_encode_bits(v: ch_info->pkt_id[5], RTW89_H2C_CHINFO_W3_PKT5) |
4449 le32_encode_bits(v: ch_info->pkt_id[6], RTW89_H2C_CHINFO_W3_PKT6) |
4450 le32_encode_bits(v: ch_info->pkt_id[7], RTW89_H2C_CHINFO_W3_PKT7);
4451 }
4452
4453 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4454 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
4455 func: H2C_FUNC_ADD_SCANOFLD_CH, rack: 1, dack: 1, len: skb_len);
4456
4457 cond = RTW89_SCANOFLD_WAIT_COND_ADD_CH;
4458
4459 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
4460 if (ret) {
4461 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "failed to add scan ofld ch\n");
4462 return ret;
4463 }
4464
4465 return 0;
4466}
4467
4468int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
4469 struct list_head *chan_list)
4470{
4471 struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
4472 struct rtw89_h2c_chinfo_elem_be *elem;
4473 struct rtw89_mac_chinfo_be *ch_info;
4474 struct rtw89_h2c_chinfo *h2c;
4475 struct sk_buff *skb;
4476 unsigned int cond;
4477 int skb_len;
4478 int ret;
4479
4480 static_assert(sizeof(*elem) == RTW89_MAC_CHINFO_SIZE);
4481
4482 skb_len = struct_size(h2c, elem, ch_num);
4483 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len: skb_len);
4484 if (!skb) {
4485 rtw89_err(rtwdev, "failed to alloc skb for h2c scan list\n");
4486 return -ENOMEM;
4487 }
4488
4489 skb_put(skb, len: sizeof(*h2c));
4490 h2c = (struct rtw89_h2c_chinfo *)skb->data;
4491
4492 h2c->ch_num = ch_num;
4493 h2c->elem_size = sizeof(*elem) / 4; /* in unit of 4 bytes */
4494 h2c->arg = u8_encode_bits(v: RTW89_PHY_0, RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK);
4495
4496 list_for_each_entry(ch_info, chan_list, list) {
4497 elem = (struct rtw89_h2c_chinfo_elem_be *)skb_put(skb, len: sizeof(*elem));
4498
4499 elem->w0 = le32_encode_bits(v: ch_info->period, RTW89_H2C_CHINFO_BE_W0_PERIOD) |
4500 le32_encode_bits(v: ch_info->dwell_time, RTW89_H2C_CHINFO_BE_W0_DWELL) |
4501 le32_encode_bits(v: ch_info->central_ch,
4502 RTW89_H2C_CHINFO_BE_W0_CENTER_CH) |
4503 le32_encode_bits(v: ch_info->pri_ch, RTW89_H2C_CHINFO_BE_W0_PRI_CH);
4504
4505 elem->w1 = le32_encode_bits(v: ch_info->bw, RTW89_H2C_CHINFO_BE_W1_BW) |
4506 le32_encode_bits(v: ch_info->ch_band, RTW89_H2C_CHINFO_BE_W1_CH_BAND) |
4507 le32_encode_bits(v: ch_info->dfs_ch, RTW89_H2C_CHINFO_BE_W1_DFS) |
4508 le32_encode_bits(v: ch_info->pause_data,
4509 RTW89_H2C_CHINFO_BE_W1_PAUSE_DATA) |
4510 le32_encode_bits(v: ch_info->tx_null, RTW89_H2C_CHINFO_BE_W1_TX_NULL) |
4511 le32_encode_bits(v: ch_info->rand_seq_num,
4512 RTW89_H2C_CHINFO_BE_W1_RANDOM) |
4513 le32_encode_bits(v: ch_info->notify_action,
4514 RTW89_H2C_CHINFO_BE_W1_NOTIFY) |
4515 le32_encode_bits(v: ch_info->probe_id != 0xff ? 1 : 0,
4516 RTW89_H2C_CHINFO_BE_W1_PROBE) |
4517 le32_encode_bits(v: ch_info->leave_crit,
4518 RTW89_H2C_CHINFO_BE_W1_EARLY_LEAVE_CRIT) |
4519 le32_encode_bits(v: ch_info->chkpt_timer,
4520 RTW89_H2C_CHINFO_BE_W1_CHKPT_TIMER);
4521
4522 elem->w2 = le32_encode_bits(v: ch_info->leave_time,
4523 RTW89_H2C_CHINFO_BE_W2_EARLY_LEAVE_TIME) |
4524 le32_encode_bits(v: ch_info->leave_th,
4525 RTW89_H2C_CHINFO_BE_W2_EARLY_LEAVE_TH) |
4526 le32_encode_bits(v: ch_info->tx_pkt_ctrl,
4527 RTW89_H2C_CHINFO_BE_W2_TX_PKT_CTRL);
4528
4529 elem->w3 = le32_encode_bits(v: ch_info->pkt_id[0], RTW89_H2C_CHINFO_BE_W3_PKT0) |
4530 le32_encode_bits(v: ch_info->pkt_id[1], RTW89_H2C_CHINFO_BE_W3_PKT1) |
4531 le32_encode_bits(v: ch_info->pkt_id[2], RTW89_H2C_CHINFO_BE_W3_PKT2) |
4532 le32_encode_bits(v: ch_info->pkt_id[3], RTW89_H2C_CHINFO_BE_W3_PKT3);
4533
4534 elem->w4 = le32_encode_bits(v: ch_info->pkt_id[4], RTW89_H2C_CHINFO_BE_W4_PKT4) |
4535 le32_encode_bits(v: ch_info->pkt_id[5], RTW89_H2C_CHINFO_BE_W4_PKT5) |
4536 le32_encode_bits(v: ch_info->pkt_id[6], RTW89_H2C_CHINFO_BE_W4_PKT6) |
4537 le32_encode_bits(v: ch_info->pkt_id[7], RTW89_H2C_CHINFO_BE_W4_PKT7);
4538
4539 elem->w5 = le32_encode_bits(v: ch_info->sw_def, RTW89_H2C_CHINFO_BE_W5_SW_DEF) |
4540 le32_encode_bits(v: ch_info->fw_probe0_ssids,
4541 RTW89_H2C_CHINFO_BE_W5_FW_PROBE0_SSIDS);
4542
4543 elem->w6 = le32_encode_bits(v: ch_info->fw_probe0_shortssids,
4544 RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_SHORTSSIDS) |
4545 le32_encode_bits(v: ch_info->fw_probe0_bssids,
4546 RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_BSSIDS);
4547 }
4548
4549 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4550 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
4551 func: H2C_FUNC_ADD_SCANOFLD_CH, rack: 1, dack: 1, len: skb_len);
4552
4553 cond = RTW89_SCANOFLD_WAIT_COND_ADD_CH;
4554
4555 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
4556 if (ret) {
4557 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "failed to add scan ofld ch\n");
4558 return ret;
4559 }
4560
4561 return 0;
4562}
4563
4564int rtw89_fw_h2c_scan_offload(struct rtw89_dev *rtwdev,
4565 struct rtw89_scan_option *option,
4566 struct rtw89_vif *rtwvif)
4567{
4568 struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
4569 struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
4570 struct rtw89_h2c_scanofld *h2c;
4571 u32 len = sizeof(*h2c);
4572 struct sk_buff *skb;
4573 unsigned int cond;
4574 int ret;
4575
4576 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4577 if (!skb) {
4578 rtw89_err(rtwdev, "failed to alloc skb for h2c scan offload\n");
4579 return -ENOMEM;
4580 }
4581 skb_put(skb, len);
4582 h2c = (struct rtw89_h2c_scanofld *)skb->data;
4583
4584 h2c->w0 = le32_encode_bits(v: rtwvif->mac_id, RTW89_H2C_SCANOFLD_W0_MACID) |
4585 le32_encode_bits(v: rtwvif->port, RTW89_H2C_SCANOFLD_W0_PORT_ID) |
4586 le32_encode_bits(v: RTW89_PHY_0, RTW89_H2C_SCANOFLD_W0_BAND) |
4587 le32_encode_bits(v: option->enable, RTW89_H2C_SCANOFLD_W0_OPERATION);
4588
4589 h2c->w1 = le32_encode_bits(v: true, RTW89_H2C_SCANOFLD_W1_NOTIFY_END) |
4590 le32_encode_bits(v: option->target_ch_mode,
4591 RTW89_H2C_SCANOFLD_W1_TARGET_CH_MODE) |
4592 le32_encode_bits(v: RTW89_SCAN_IMMEDIATE,
4593 RTW89_H2C_SCANOFLD_W1_START_MODE) |
4594 le32_encode_bits(v: RTW89_SCAN_ONCE, RTW89_H2C_SCANOFLD_W1_SCAN_TYPE);
4595
4596 if (option->target_ch_mode) {
4597 h2c->w1 |= le32_encode_bits(v: op->band_width,
4598 RTW89_H2C_SCANOFLD_W1_TARGET_CH_BW) |
4599 le32_encode_bits(v: op->primary_channel,
4600 RTW89_H2C_SCANOFLD_W1_TARGET_PRI_CH) |
4601 le32_encode_bits(v: op->channel,
4602 RTW89_H2C_SCANOFLD_W1_TARGET_CENTRAL_CH);
4603 h2c->w0 |= le32_encode_bits(v: op->band_type,
4604 RTW89_H2C_SCANOFLD_W0_TARGET_CH_BAND);
4605 }
4606
4607 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4608 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
4609 func: H2C_FUNC_SCANOFLD, rack: 1, dack: 1,
4610 len);
4611
4612 if (option->enable)
4613 cond = RTW89_SCANOFLD_WAIT_COND_START;
4614 else
4615 cond = RTW89_SCANOFLD_WAIT_COND_STOP;
4616
4617 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
4618 if (ret) {
4619 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "failed to scan ofld\n");
4620 return ret;
4621 }
4622
4623 return 0;
4624}
4625
4626static void rtw89_scan_get_6g_disabled_chan(struct rtw89_dev *rtwdev,
4627 struct rtw89_scan_option *option)
4628{
4629 struct ieee80211_supported_band *sband;
4630 struct ieee80211_channel *chan;
4631 u8 i, idx;
4632
4633 sband = rtwdev->hw->wiphy->bands[NL80211_BAND_6GHZ];
4634
4635 for (i = 0; i < sband->n_channels; i++) {
4636 chan = &sband->channels[i];
4637 if (chan->flags & IEEE80211_CHAN_DISABLED) {
4638 idx = (chan->hw_value - 1) / 4;
4639 option->prohib_chan |= BIT(idx);
4640 }
4641 }
4642}
4643
4644int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
4645 struct rtw89_scan_option *option,
4646 struct rtw89_vif *rtwvif)
4647{
4648 struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
4649 struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
4650 struct rtw89_h2c_scanofld_be_macc_role *macc_role;
4651 struct rtw89_chan *op = &scan_info->op_chan;
4652 struct rtw89_h2c_scanofld_be_opch *opch;
4653 struct rtw89_h2c_scanofld_be *h2c;
4654 struct sk_buff *skb;
4655 u8 macc_role_size = sizeof(*macc_role) * option->num_macc_role;
4656 u8 opch_size = sizeof(*opch) * option->num_opch;
4657 u8 probe_id[NUM_NL80211_BANDS];
4658 unsigned int cond;
4659 void *ptr;
4660 int ret;
4661 u32 len;
4662 u8 i;
4663
4664 rtw89_scan_get_6g_disabled_chan(rtwdev, option);
4665
4666 len = sizeof(*h2c) + macc_role_size + opch_size;
4667 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4668 if (!skb) {
4669 rtw89_err(rtwdev, "failed to alloc skb for h2c scan offload\n");
4670 return -ENOMEM;
4671 }
4672
4673 skb_put(skb, len);
4674 h2c = (struct rtw89_h2c_scanofld_be *)skb->data;
4675 ptr = skb->data;
4676
4677 h2c->w0 = le32_encode_bits(v: option->operation, RTW89_H2C_SCANOFLD_BE_W0_OP) |
4678 le32_encode_bits(v: option->scan_mode,
4679 RTW89_H2C_SCANOFLD_BE_W0_SCAN_MODE) |
4680 le32_encode_bits(v: option->repeat, RTW89_H2C_SCANOFLD_BE_W0_REPEAT) |
4681 le32_encode_bits(v: true, RTW89_H2C_SCANOFLD_BE_W0_NOTIFY_END) |
4682 le32_encode_bits(v: true, RTW89_H2C_SCANOFLD_BE_W0_LEARN_CH) |
4683 le32_encode_bits(v: rtwvif->mac_id, RTW89_H2C_SCANOFLD_BE_W0_MACID) |
4684 le32_encode_bits(v: rtwvif->port, RTW89_H2C_SCANOFLD_BE_W0_PORT) |
4685 le32_encode_bits(v: option->band, RTW89_H2C_SCANOFLD_BE_W0_BAND);
4686
4687 h2c->w1 = le32_encode_bits(v: option->num_macc_role, RTW89_H2C_SCANOFLD_BE_W1_NUM_MACC_ROLE) |
4688 le32_encode_bits(v: option->num_opch, RTW89_H2C_SCANOFLD_BE_W1_NUM_OP) |
4689 le32_encode_bits(v: option->norm_pd, RTW89_H2C_SCANOFLD_BE_W1_NORM_PD);
4690
4691 h2c->w2 = le32_encode_bits(v: option->slow_pd, RTW89_H2C_SCANOFLD_BE_W2_SLOW_PD) |
4692 le32_encode_bits(v: option->norm_cy, RTW89_H2C_SCANOFLD_BE_W2_NORM_CY) |
4693 le32_encode_bits(v: option->opch_end, RTW89_H2C_SCANOFLD_BE_W2_OPCH_END);
4694
4695 h2c->w3 = le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_W3_NUM_SSID) |
4696 le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_W3_NUM_SHORT_SSID) |
4697 le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_W3_NUM_BSSID) |
4698 le32_encode_bits(v: probe_id[NL80211_BAND_2GHZ], RTW89_H2C_SCANOFLD_BE_W3_PROBEID);
4699
4700 h2c->w4 = le32_encode_bits(v: probe_id[NL80211_BAND_5GHZ],
4701 RTW89_H2C_SCANOFLD_BE_W4_PROBE_5G) |
4702 le32_encode_bits(v: probe_id[NL80211_BAND_6GHZ],
4703 RTW89_H2C_SCANOFLD_BE_W4_PROBE_6G) |
4704 le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_W4_DELAY_START);
4705
4706 h2c->w5 = le32_encode_bits(v: option->mlo_mode, RTW89_H2C_SCANOFLD_BE_W5_MLO_MODE);
4707
4708 h2c->w6 = le32_encode_bits(v: option->prohib_chan,
4709 RTW89_H2C_SCANOFLD_BE_W6_CHAN_PROHIB_LOW);
4710 h2c->w7 = le32_encode_bits(v: option->prohib_chan >> 32,
4711 RTW89_H2C_SCANOFLD_BE_W7_CHAN_PROHIB_HIGH);
4712 ptr += sizeof(*h2c);
4713
4714 for (i = 0; i < option->num_macc_role; i++) {
4715 macc_role = (struct rtw89_h2c_scanofld_be_macc_role *)&h2c->role[i];
4716 macc_role->w0 =
4717 le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_BAND) |
4718 le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_PORT) |
4719 le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_MACID) |
4720 le32_encode_bits(v: 0, RTW89_H2C_SCANOFLD_BE_MACC_ROLE_W0_OPCH_END);
4721 ptr += sizeof(*macc_role);
4722 }
4723
4724 for (i = 0; i < option->num_opch; i++) {
4725 opch = ptr;
4726 opch->w0 = le32_encode_bits(v: rtwvif->mac_id,
4727 RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID) |
4728 le32_encode_bits(v: option->band,
4729 RTW89_H2C_SCANOFLD_BE_OPCH_W0_BAND) |
4730 le32_encode_bits(v: rtwvif->port,
4731 RTW89_H2C_SCANOFLD_BE_OPCH_W0_PORT) |
4732 le32_encode_bits(v: RTW89_SCAN_OPMODE_INTV,
4733 RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY) |
4734 le32_encode_bits(v: true,
4735 RTW89_H2C_SCANOFLD_BE_OPCH_W0_TXNULL) |
4736 le32_encode_bits(RTW89_OFF_CHAN_TIME / 10,
4737 RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY_VAL);
4738
4739 opch->w1 = le32_encode_bits(RTW89_CHANNEL_TIME,
4740 RTW89_H2C_SCANOFLD_BE_OPCH_W1_DURATION) |
4741 le32_encode_bits(v: op->band_type,
4742 RTW89_H2C_SCANOFLD_BE_OPCH_W1_CH_BAND) |
4743 le32_encode_bits(v: op->band_width,
4744 RTW89_H2C_SCANOFLD_BE_OPCH_W1_BW) |
4745 le32_encode_bits(v: 0x3,
4746 RTW89_H2C_SCANOFLD_BE_OPCH_W1_NOTIFY) |
4747 le32_encode_bits(v: op->primary_channel,
4748 RTW89_H2C_SCANOFLD_BE_OPCH_W1_PRI_CH) |
4749 le32_encode_bits(v: op->channel,
4750 RTW89_H2C_SCANOFLD_BE_OPCH_W1_CENTRAL_CH);
4751
4752 opch->w2 = le32_encode_bits(v: 0,
4753 RTW89_H2C_SCANOFLD_BE_OPCH_W2_PKTS_CTRL) |
4754 le32_encode_bits(v: 0,
4755 RTW89_H2C_SCANOFLD_BE_OPCH_W2_SW_DEF) |
4756 le32_encode_bits(v: 2,
4757 RTW89_H2C_SCANOFLD_BE_OPCH_W2_SS);
4758
4759 opch->w3 = le32_encode_bits(RTW89_SCANOFLD_PKT_NONE,
4760 RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT0) |
4761 le32_encode_bits(RTW89_SCANOFLD_PKT_NONE,
4762 RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT1) |
4763 le32_encode_bits(RTW89_SCANOFLD_PKT_NONE,
4764 RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT2) |
4765 le32_encode_bits(RTW89_SCANOFLD_PKT_NONE,
4766 RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT3);
4767 ptr += sizeof(*opch);
4768 }
4769
4770 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4771 H2C_CAT_MAC, H2C_CL_MAC_FW_OFLD,
4772 func: H2C_FUNC_SCANOFLD_BE, rack: 1, dack: 1,
4773 len);
4774
4775 if (option->enable)
4776 cond = RTW89_SCANOFLD_BE_WAIT_COND_START;
4777 else
4778 cond = RTW89_SCANOFLD_BE_WAIT_COND_STOP;
4779
4780 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
4781 if (ret) {
4782 rtw89_debug(rtwdev, mask: RTW89_DBG_FW, fmt: "failed to scan be ofld\n");
4783 return ret;
4784 }
4785
4786 return 0;
4787}
4788
4789int rtw89_fw_h2c_rf_reg(struct rtw89_dev *rtwdev,
4790 struct rtw89_fw_h2c_rf_reg_info *info,
4791 u16 len, u8 page)
4792{
4793 struct sk_buff *skb;
4794 u8 class = info->rf_path == RF_PATH_A ?
4795 H2C_CL_OUTSRC_RF_REG_A : H2C_CL_OUTSRC_RF_REG_B;
4796 int ret;
4797
4798 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4799 if (!skb) {
4800 rtw89_err(rtwdev, "failed to alloc skb for h2c rf reg\n");
4801 return -ENOMEM;
4802 }
4803 skb_put_data(skb, data: info->rtw89_phy_config_rf_h2c[page], len);
4804
4805 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4806 H2C_CAT_OUTSRC, class, func: page, rack: 0, dack: 0,
4807 len);
4808
4809 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4810 if (ret) {
4811 rtw89_err(rtwdev, "failed to send h2c\n");
4812 goto fail;
4813 }
4814
4815 return 0;
4816fail:
4817 dev_kfree_skb_any(skb);
4818
4819 return ret;
4820}
4821
4822int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
4823{
4824 struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
4825 struct rtw89_fw_h2c_rf_get_mccch *mccch;
4826 struct sk_buff *skb;
4827 int ret;
4828 u8 idx;
4829
4830 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len: sizeof(*mccch));
4831 if (!skb) {
4832 rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_ctrl\n");
4833 return -ENOMEM;
4834 }
4835 skb_put(skb, len: sizeof(*mccch));
4836 mccch = (struct rtw89_fw_h2c_rf_get_mccch *)skb->data;
4837
4838 idx = rfk_mcc->table_idx;
4839 mccch->ch_0 = cpu_to_le32(rfk_mcc->ch[0]);
4840 mccch->ch_1 = cpu_to_le32(rfk_mcc->ch[1]);
4841 mccch->band_0 = cpu_to_le32(rfk_mcc->band[0]);
4842 mccch->band_1 = cpu_to_le32(rfk_mcc->band[1]);
4843 mccch->current_channel = cpu_to_le32(rfk_mcc->ch[idx]);
4844 mccch->current_band_type = cpu_to_le32(rfk_mcc->band[idx]);
4845
4846 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4847 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY,
4848 H2C_FUNC_OUTSRC_RF_GET_MCCCH, rack: 0, dack: 0,
4849 len: sizeof(*mccch));
4850
4851 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4852 if (ret) {
4853 rtw89_err(rtwdev, "failed to send h2c\n");
4854 goto fail;
4855 }
4856
4857 return 0;
4858fail:
4859 dev_kfree_skb_any(skb);
4860
4861 return ret;
4862}
4863EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc);
4864
4865int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
4866 enum rtw89_phy_idx phy_idx)
4867{
4868 struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
4869 struct rtw89_fw_h2c_rfk_pre_info *h2c;
4870 u8 tbl_sel = rfk_mcc->table_idx;
4871 u32 len = sizeof(*h2c);
4872 struct sk_buff *skb;
4873 u8 tbl, path;
4874 u32 val32;
4875 int ret;
4876
4877 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4878 if (!skb) {
4879 rtw89_err(rtwdev, "failed to alloc skb for h2c rfk_pre_ntfy\n");
4880 return -ENOMEM;
4881 }
4882 skb_put(skb, len);
4883 h2c = (struct rtw89_fw_h2c_rfk_pre_info *)skb->data;
4884
4885 h2c->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
4886
4887 BUILD_BUG_ON(NUM_OF_RTW89_FW_RFK_TBL > RTW89_RFK_CHS_NR);
4888
4889 for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) {
4890 for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
4891 h2c->dbcc.ch[path][tbl] = cpu_to_le32(rfk_mcc->ch[tbl]);
4892 h2c->dbcc.band[path][tbl] = cpu_to_le32(rfk_mcc->band[tbl]);
4893 }
4894 }
4895
4896 for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
4897 h2c->tbl.cur_ch[path] = cpu_to_le32(rfk_mcc->ch[tbl_sel]);
4898 h2c->tbl.cur_band[path] = cpu_to_le32(rfk_mcc->band[tbl_sel]);
4899 }
4900
4901 h2c->phy_idx = cpu_to_le32(phy_idx);
4902 h2c->cur_band = cpu_to_le32(rfk_mcc->band[tbl_sel]);
4903 h2c->cur_bw = cpu_to_le32(rfk_mcc->bw[tbl_sel]);
4904 h2c->cur_center_ch = cpu_to_le32(rfk_mcc->ch[tbl_sel]);
4905
4906 val32 = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL, B_COEF_SEL_IQC_V1);
4907 h2c->ktbl_sel0 = cpu_to_le32(val32);
4908 val32 = rtw89_phy_read32_mask(rtwdev, R_COEF_SEL_C1, B_COEF_SEL_IQC_V1);
4909 h2c->ktbl_sel1 = cpu_to_le32(val32);
4910 val32 = rtw89_read_rf(rtwdev, rf_path: RF_PATH_A, RR_CFGCH, RFREG_MASK);
4911 h2c->rfmod0 = cpu_to_le32(val32);
4912 val32 = rtw89_read_rf(rtwdev, rf_path: RF_PATH_B, RR_CFGCH, RFREG_MASK);
4913 h2c->rfmod1 = cpu_to_le32(val32);
4914
4915 if (rtw89_is_mlo_1_1(rtwdev))
4916 h2c->mlo_1_1 = cpu_to_le32(1);
4917
4918 h2c->rfe_type = cpu_to_le32(rtwdev->efuse.rfe_type);
4919
4920 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4921 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
4922 func: H2C_FUNC_RFK_PRE_NOTIFY, rack: 0, dack: 0,
4923 len);
4924
4925 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4926 if (ret) {
4927 rtw89_err(rtwdev, "failed to send h2c\n");
4928 goto fail;
4929 }
4930
4931 return 0;
4932fail:
4933 dev_kfree_skb_any(skb);
4934
4935 return ret;
4936}
4937
4938int rtw89_fw_h2c_rf_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx,
4939 enum rtw89_tssi_mode tssi_mode)
4940{
4941 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
4942 idx: RTW89_SUB_ENTITY_0);
4943 struct rtw89_hal *hal = &rtwdev->hal;
4944 struct rtw89_h2c_rf_tssi *h2c;
4945 u32 len = sizeof(*h2c);
4946 struct sk_buff *skb;
4947 int ret;
4948
4949 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4950 if (!skb) {
4951 rtw89_err(rtwdev, "failed to alloc skb for h2c RF TSSI\n");
4952 return -ENOMEM;
4953 }
4954 skb_put(skb, len);
4955 h2c = (struct rtw89_h2c_rf_tssi *)skb->data;
4956
4957 h2c->len = cpu_to_le16(len);
4958 h2c->phy = phy_idx;
4959 h2c->ch = chan->channel;
4960 h2c->bw = chan->band_width;
4961 h2c->band = chan->band_type;
4962 h2c->hwtx_en = true;
4963 h2c->cv = hal->cv;
4964 h2c->tssi_mode = tssi_mode;
4965
4966 rtw89_phy_rfk_tssi_fill_fwcmd_efuse_to_de(rtwdev, phy: phy_idx, chan, h2c);
4967 rtw89_phy_rfk_tssi_fill_fwcmd_tmeter_tbl(rtwdev, phy: phy_idx, chan, h2c);
4968
4969 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
4970 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
4971 func: H2C_FUNC_RFK_TSSI_OFFLOAD, rack: 0, dack: 0, len);
4972
4973 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
4974 if (ret) {
4975 rtw89_err(rtwdev, "failed to send h2c\n");
4976 goto fail;
4977 }
4978
4979 return 0;
4980fail:
4981 dev_kfree_skb_any(skb);
4982
4983 return ret;
4984}
4985
4986int rtw89_fw_h2c_rf_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
4987{
4988 struct rtw89_h2c_rf_iqk *h2c;
4989 u32 len = sizeof(*h2c);
4990 struct sk_buff *skb;
4991 int ret;
4992
4993 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
4994 if (!skb) {
4995 rtw89_err(rtwdev, "failed to alloc skb for h2c RF IQK\n");
4996 return -ENOMEM;
4997 }
4998 skb_put(skb, len);
4999 h2c = (struct rtw89_h2c_rf_iqk *)skb->data;
5000
5001 h2c->phy_idx = cpu_to_le32(phy_idx);
5002 h2c->dbcc = cpu_to_le32(rtwdev->dbcc_en);
5003
5004 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
5005 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
5006 func: H2C_FUNC_RFK_IQK_OFFLOAD, rack: 0, dack: 0, len);
5007
5008 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
5009 if (ret) {
5010 rtw89_err(rtwdev, "failed to send h2c\n");
5011 goto fail;
5012 }
5013
5014 return 0;
5015fail:
5016 dev_kfree_skb_any(skb);
5017
5018 return ret;
5019}
5020
5021int rtw89_fw_h2c_rf_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
5022{
5023 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
5024 idx: RTW89_SUB_ENTITY_0);
5025 struct rtw89_h2c_rf_dpk *h2c;
5026 u32 len = sizeof(*h2c);
5027 struct sk_buff *skb;
5028 int ret;
5029
5030 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
5031 if (!skb) {
5032 rtw89_err(rtwdev, "failed to alloc skb for h2c RF DPK\n");
5033 return -ENOMEM;
5034 }
5035 skb_put(skb, len);
5036 h2c = (struct rtw89_h2c_rf_dpk *)skb->data;
5037
5038 h2c->len = len;
5039 h2c->phy = phy_idx;
5040 h2c->dpk_enable = true;
5041 h2c->kpath = RF_AB;
5042 h2c->cur_band = chan->band_type;
5043 h2c->cur_bw = chan->band_width;
5044 h2c->cur_ch = chan->channel;
5045 h2c->dpk_dbg_en = rtw89_debug_is_enabled(rtwdev, mask: RTW89_DBG_RFK);
5046
5047 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
5048 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
5049 func: H2C_FUNC_RFK_DPK_OFFLOAD, rack: 0, dack: 0, len);
5050
5051 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
5052 if (ret) {
5053 rtw89_err(rtwdev, "failed to send h2c\n");
5054 goto fail;
5055 }
5056
5057 return 0;
5058fail:
5059 dev_kfree_skb_any(skb);
5060
5061 return ret;
5062}
5063
5064int rtw89_fw_h2c_rf_txgapk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
5065{
5066 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
5067 idx: RTW89_SUB_ENTITY_0);
5068 struct rtw89_hal *hal = &rtwdev->hal;
5069 struct rtw89_h2c_rf_txgapk *h2c;
5070 u32 len = sizeof(*h2c);
5071 struct sk_buff *skb;
5072 int ret;
5073
5074 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
5075 if (!skb) {
5076 rtw89_err(rtwdev, "failed to alloc skb for h2c RF TXGAPK\n");
5077 return -ENOMEM;
5078 }
5079 skb_put(skb, len);
5080 h2c = (struct rtw89_h2c_rf_txgapk *)skb->data;
5081
5082 h2c->len = len;
5083 h2c->ktype = 2;
5084 h2c->phy = phy_idx;
5085 h2c->kpath = RF_AB;
5086 h2c->band = chan->band_type;
5087 h2c->bw = chan->band_width;
5088 h2c->ch = chan->channel;
5089 h2c->cv = hal->cv;
5090
5091 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
5092 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
5093 func: H2C_FUNC_RFK_TXGAPK_OFFLOAD, rack: 0, dack: 0, len);
5094
5095 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
5096 if (ret) {
5097 rtw89_err(rtwdev, "failed to send h2c\n");
5098 goto fail;
5099 }
5100
5101 return 0;
5102fail:
5103 dev_kfree_skb_any(skb);
5104
5105 return ret;
5106}
5107
5108int rtw89_fw_h2c_rf_dack(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
5109{
5110 struct rtw89_h2c_rf_dack *h2c;
5111 u32 len = sizeof(*h2c);
5112 struct sk_buff *skb;
5113 int ret;
5114
5115 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
5116 if (!skb) {
5117 rtw89_err(rtwdev, "failed to alloc skb for h2c RF DACK\n");
5118 return -ENOMEM;
5119 }
5120 skb_put(skb, len);
5121 h2c = (struct rtw89_h2c_rf_dack *)skb->data;
5122
5123 h2c->len = cpu_to_le32(len);
5124 h2c->phy = cpu_to_le32(phy_idx);
5125 h2c->type = cpu_to_le32(0);
5126
5127 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
5128 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
5129 func: H2C_FUNC_RFK_DACK_OFFLOAD, rack: 0, dack: 0, len);
5130
5131 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
5132 if (ret) {
5133 rtw89_err(rtwdev, "failed to send h2c\n");
5134 goto fail;
5135 }
5136
5137 return 0;
5138fail:
5139 dev_kfree_skb_any(skb);
5140
5141 return ret;
5142}
5143
5144int rtw89_fw_h2c_rf_rxdck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
5145{
5146 const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
5147 idx: RTW89_SUB_ENTITY_0);
5148 struct rtw89_h2c_rf_rxdck *h2c;
5149 u32 len = sizeof(*h2c);
5150 struct sk_buff *skb;
5151 int ret;
5152
5153 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
5154 if (!skb) {
5155 rtw89_err(rtwdev, "failed to alloc skb for h2c RF RXDCK\n");
5156 return -ENOMEM;
5157 }
5158 skb_put(skb, len);
5159 h2c = (struct rtw89_h2c_rf_rxdck *)skb->data;
5160
5161 h2c->len = len;
5162 h2c->phy = phy_idx;
5163 h2c->is_afe = false;
5164 h2c->kpath = RF_AB;
5165 h2c->cur_band = chan->band_type;
5166 h2c->cur_bw = chan->band_width;
5167 h2c->cur_ch = chan->channel;
5168 h2c->rxdck_dbg_en = rtw89_debug_is_enabled(rtwdev, mask: RTW89_DBG_RFK);
5169
5170 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
5171 H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
5172 func: H2C_FUNC_RFK_RXDCK_OFFLOAD, rack: 0, dack: 0, len);
5173
5174 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
5175 if (ret) {
5176 rtw89_err(rtwdev, "failed to send h2c\n");
5177 goto fail;
5178 }
5179
5180 return 0;
5181fail:
5182 dev_kfree_skb_any(skb);
5183
5184 return ret;
5185}
5186
5187int rtw89_fw_h2c_raw_with_hdr(struct rtw89_dev *rtwdev,
5188 u8 h2c_class, u8 h2c_func, u8 *buf, u16 len,
5189 bool rack, bool dack)
5190{
5191 struct sk_buff *skb;
5192 int ret;
5193
5194 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
5195 if (!skb) {
5196 rtw89_err(rtwdev, "failed to alloc skb for raw with hdr\n");
5197 return -ENOMEM;
5198 }
5199 skb_put_data(skb, data: buf, len);
5200
5201 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
5202 H2C_CAT_OUTSRC, class: h2c_class, func: h2c_func, rack, dack,
5203 len);
5204
5205 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
5206 if (ret) {
5207 rtw89_err(rtwdev, "failed to send h2c\n");
5208 goto fail;
5209 }
5210
5211 return 0;
5212fail:
5213 dev_kfree_skb_any(skb);
5214
5215 return ret;
5216}
5217
5218int rtw89_fw_h2c_raw(struct rtw89_dev *rtwdev, const u8 *buf, u16 len)
5219{
5220 struct sk_buff *skb;
5221 int ret;
5222
5223 skb = rtw89_fw_h2c_alloc_skb_no_hdr(rtwdev, len);
5224 if (!skb) {
5225 rtw89_err(rtwdev, "failed to alloc skb for h2c raw\n");
5226 return -ENOMEM;
5227 }
5228 skb_put_data(skb, data: buf, len);
5229
5230 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
5231 if (ret) {
5232 rtw89_err(rtwdev, "failed to send h2c\n");
5233 goto fail;
5234 }
5235
5236 return 0;
5237fail:
5238 dev_kfree_skb_any(skb);
5239
5240 return ret;
5241}
5242
5243void rtw89_fw_send_all_early_h2c(struct rtw89_dev *rtwdev)
5244{
5245 struct rtw89_early_h2c *early_h2c;
5246
5247 lockdep_assert_held(&rtwdev->mutex);
5248
5249 list_for_each_entry(early_h2c, &rtwdev->early_h2c_list, list) {
5250 rtw89_fw_h2c_raw(rtwdev, buf: early_h2c->h2c, len: early_h2c->h2c_len);
5251 }
5252}
5253
5254void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev)
5255{
5256 struct rtw89_early_h2c *early_h2c, *tmp;
5257
5258 mutex_lock(&rtwdev->mutex);
5259 list_for_each_entry_safe(early_h2c, tmp, &rtwdev->early_h2c_list, list) {
5260 list_del(entry: &early_h2c->list);
5261 kfree(objp: early_h2c->h2c);
5262 kfree(objp: early_h2c);
5263 }
5264 mutex_unlock(lock: &rtwdev->mutex);
5265}
5266
5267static void rtw89_fw_c2h_parse_attr(struct sk_buff *c2h)
5268{
5269 const struct rtw89_c2h_hdr *hdr = (const struct rtw89_c2h_hdr *)c2h->data;
5270 struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb: c2h);
5271
5272 attr->category = le32_get_bits(v: hdr->w0, RTW89_C2H_HDR_W0_CATEGORY);
5273 attr->class = le32_get_bits(v: hdr->w0, RTW89_C2H_HDR_W0_CLASS);
5274 attr->func = le32_get_bits(v: hdr->w0, RTW89_C2H_HDR_W0_FUNC);
5275 attr->len = le32_get_bits(v: hdr->w1, RTW89_C2H_HDR_W1_LEN);
5276}
5277
5278static bool rtw89_fw_c2h_chk_atomic(struct rtw89_dev *rtwdev,
5279 struct sk_buff *c2h)
5280{
5281 struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb: c2h);
5282 u8 category = attr->category;
5283 u8 class = attr->class;
5284 u8 func = attr->func;
5285
5286 switch (category) {
5287 default:
5288 return false;
5289 case RTW89_C2H_CAT_MAC:
5290 return rtw89_mac_c2h_chk_atomic(rtwdev, c2h, class, func);
5291 case RTW89_C2H_CAT_OUTSRC:
5292 return rtw89_phy_c2h_chk_atomic(rtwdev, class, func);
5293 }
5294}
5295
5296void rtw89_fw_c2h_irqsafe(struct rtw89_dev *rtwdev, struct sk_buff *c2h)
5297{
5298 rtw89_fw_c2h_parse_attr(c2h);
5299 if (!rtw89_fw_c2h_chk_atomic(rtwdev, c2h))
5300 goto enqueue;
5301
5302 rtw89_fw_c2h_cmd_handle(rtwdev, skb: c2h);
5303 dev_kfree_skb_any(skb: c2h);
5304 return;
5305
5306enqueue:
5307 skb_queue_tail(list: &rtwdev->c2h_queue, newsk: c2h);
5308 ieee80211_queue_work(hw: rtwdev->hw, work: &rtwdev->c2h_work);
5309}
5310
5311static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev,
5312 struct sk_buff *skb)
5313{
5314 struct rtw89_fw_c2h_attr *attr = RTW89_SKB_C2H_CB(skb);
5315 u8 category = attr->category;
5316 u8 class = attr->class;
5317 u8 func = attr->func;
5318 u16 len = attr->len;
5319 bool dump = true;
5320
5321 if (!test_bit(RTW89_FLAG_RUNNING, rtwdev->flags))
5322 return;
5323
5324 switch (category) {
5325 case RTW89_C2H_CAT_TEST:
5326 break;
5327 case RTW89_C2H_CAT_MAC:
5328 rtw89_mac_c2h_handle(rtwdev, skb, len, class, func);
5329 if (class == RTW89_MAC_C2H_CLASS_INFO &&
5330 func == RTW89_MAC_C2H_FUNC_C2H_LOG)
5331 dump = false;
5332 break;
5333 case RTW89_C2H_CAT_OUTSRC:
5334 if (class >= RTW89_PHY_C2H_CLASS_BTC_MIN &&
5335 class <= RTW89_PHY_C2H_CLASS_BTC_MAX)
5336 rtw89_btc_c2h_handle(rtwdev, skb, len, class, func);
5337 else
5338 rtw89_phy_c2h_handle(rtwdev, skb, len, class, func);
5339 break;
5340 }
5341
5342 if (dump)
5343 rtw89_hex_dump(rtwdev, mask: RTW89_DBG_FW, prefix_str: "C2H: ", buf: skb->data, len: skb->len);
5344}
5345
5346void rtw89_fw_c2h_work(struct work_struct *work)
5347{
5348 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
5349 c2h_work);
5350 struct sk_buff *skb, *tmp;
5351
5352 skb_queue_walk_safe(&rtwdev->c2h_queue, skb, tmp) {
5353 skb_unlink(skb, list: &rtwdev->c2h_queue);
5354 mutex_lock(&rtwdev->mutex);
5355 rtw89_fw_c2h_cmd_handle(rtwdev, skb);
5356 mutex_unlock(lock: &rtwdev->mutex);
5357 dev_kfree_skb_any(skb);
5358 }
5359}
5360
5361static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev,
5362 struct rtw89_mac_h2c_info *info)
5363{
5364 const struct rtw89_chip_info *chip = rtwdev->chip;
5365 struct rtw89_fw_info *fw_info = &rtwdev->fw;
5366 const u32 *h2c_reg = chip->h2c_regs;
5367 u8 i, val, len;
5368 int ret;
5369
5370 ret = read_poll_timeout(rtw89_read8, val, val == 0, 1000, 5000, false,
5371 rtwdev, chip->h2c_ctrl_reg);
5372 if (ret) {
5373 rtw89_warn(rtwdev, "FW does not process h2c registers\n");
5374 return ret;
5375 }
5376
5377 len = DIV_ROUND_UP(info->content_len + RTW89_H2CREG_HDR_LEN,
5378 sizeof(info->u.h2creg[0]));
5379
5380 u32p_replace_bits(p: &info->u.hdr.w0, val: info->id, RTW89_H2CREG_HDR_FUNC_MASK);
5381 u32p_replace_bits(p: &info->u.hdr.w0, val: len, RTW89_H2CREG_HDR_LEN_MASK);
5382
5383 for (i = 0; i < RTW89_H2CREG_MAX; i++)
5384 rtw89_write32(rtwdev, addr: h2c_reg[i], data: info->u.h2creg[i]);
5385
5386 fw_info->h2c_counter++;
5387 rtw89_write8_mask(rtwdev, addr: chip->h2c_counter_reg.addr,
5388 mask: chip->h2c_counter_reg.mask, data: fw_info->h2c_counter);
5389 rtw89_write8(rtwdev, addr: chip->h2c_ctrl_reg, B_AX_H2CREG_TRIGGER);
5390
5391 return 0;
5392}
5393
5394static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev,
5395 struct rtw89_mac_c2h_info *info)
5396{
5397 const struct rtw89_chip_info *chip = rtwdev->chip;
5398 struct rtw89_fw_info *fw_info = &rtwdev->fw;
5399 const u32 *c2h_reg = chip->c2h_regs;
5400 u32 ret;
5401 u8 i, val;
5402
5403 info->id = RTW89_FWCMD_C2HREG_FUNC_NULL;
5404
5405 ret = read_poll_timeout_atomic(rtw89_read8, val, val, 1,
5406 RTW89_C2H_TIMEOUT, false, rtwdev,
5407 chip->c2h_ctrl_reg);
5408 if (ret) {
5409 rtw89_warn(rtwdev, "c2h reg timeout\n");
5410 return ret;
5411 }
5412
5413 for (i = 0; i < RTW89_C2HREG_MAX; i++)
5414 info->u.c2hreg[i] = rtw89_read32(rtwdev, addr: c2h_reg[i]);
5415
5416 rtw89_write8(rtwdev, addr: chip->c2h_ctrl_reg, data: 0);
5417
5418 info->id = u32_get_bits(v: info->u.hdr.w0, RTW89_C2HREG_HDR_FUNC_MASK);
5419 info->content_len =
5420 (u32_get_bits(v: info->u.hdr.w0, RTW89_C2HREG_HDR_LEN_MASK) << 2) -
5421 RTW89_C2HREG_HDR_LEN;
5422
5423 fw_info->c2h_counter++;
5424 rtw89_write8_mask(rtwdev, addr: chip->c2h_counter_reg.addr,
5425 mask: chip->c2h_counter_reg.mask, data: fw_info->c2h_counter);
5426
5427 return 0;
5428}
5429
5430int rtw89_fw_msg_reg(struct rtw89_dev *rtwdev,
5431 struct rtw89_mac_h2c_info *h2c_info,
5432 struct rtw89_mac_c2h_info *c2h_info)
5433{
5434 u32 ret;
5435
5436 if (h2c_info && h2c_info->id != RTW89_FWCMD_H2CREG_FUNC_GET_FEATURE)
5437 lockdep_assert_held(&rtwdev->mutex);
5438
5439 if (!h2c_info && !c2h_info)
5440 return -EINVAL;
5441
5442 if (!h2c_info)
5443 goto recv_c2h;
5444
5445 ret = rtw89_fw_write_h2c_reg(rtwdev, info: h2c_info);
5446 if (ret)
5447 return ret;
5448
5449recv_c2h:
5450 if (!c2h_info)
5451 return 0;
5452
5453 ret = rtw89_fw_read_c2h_reg(rtwdev, info: c2h_info);
5454 if (ret)
5455 return ret;
5456
5457 return 0;
5458}
5459
5460void rtw89_fw_st_dbg_dump(struct rtw89_dev *rtwdev)
5461{
5462 if (!test_bit(RTW89_FLAG_POWERON, rtwdev->flags)) {
5463 rtw89_err(rtwdev, "[ERR]pwr is off\n");
5464 return;
5465 }
5466
5467 rtw89_info(rtwdev, "FW status = 0x%x\n", rtw89_read32(rtwdev, R_AX_UDM0));
5468 rtw89_info(rtwdev, "FW BADADDR = 0x%x\n", rtw89_read32(rtwdev, R_AX_UDM1));
5469 rtw89_info(rtwdev, "FW EPC/RA = 0x%x\n", rtw89_read32(rtwdev, R_AX_UDM2));
5470 rtw89_info(rtwdev, "FW MISC = 0x%x\n", rtw89_read32(rtwdev, R_AX_UDM3));
5471 rtw89_info(rtwdev, "R_AX_HALT_C2H = 0x%x\n",
5472 rtw89_read32(rtwdev, R_AX_HALT_C2H));
5473 rtw89_info(rtwdev, "R_AX_SER_DBG_INFO = 0x%x\n",
5474 rtw89_read32(rtwdev, R_AX_SER_DBG_INFO));
5475
5476 rtw89_fw_prog_cnt_dump(rtwdev);
5477}
5478
5479static void rtw89_release_pkt_list(struct rtw89_dev *rtwdev)
5480{
5481 struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
5482 struct rtw89_pktofld_info *info, *tmp;
5483 u8 idx;
5484
5485 for (idx = NL80211_BAND_2GHZ; idx < NUM_NL80211_BANDS; idx++) {
5486 if (!(rtwdev->chip->support_bands & BIT(idx)))
5487 continue;
5488
5489 list_for_each_entry_safe(info, tmp, &pkt_list[idx], list) {
5490 if (test_bit(info->id, rtwdev->pkt_offload))
5491 rtw89_fw_h2c_del_pkt_offload(rtwdev, id: info->id);
5492 list_del(entry: &info->list);
5493 kfree(objp: info);
5494 }
5495 }
5496}
5497
5498static bool rtw89_is_6ghz_wildcard_probe_req(struct rtw89_dev *rtwdev,
5499 struct rtw89_vif *rtwvif,
5500 struct rtw89_pktofld_info *info,
5501 enum nl80211_band band, u8 ssid_idx)
5502{
5503 struct cfg80211_scan_request *req = rtwvif->scan_req;
5504
5505 if (band != NL80211_BAND_6GHZ)
5506 return false;
5507
5508 if (req->ssids[ssid_idx].ssid_len) {
5509 memcpy(info->ssid, req->ssids[ssid_idx].ssid,
5510 req->ssids[ssid_idx].ssid_len);
5511 info->ssid_len = req->ssids[ssid_idx].ssid_len;
5512 return false;
5513 } else {
5514 return true;
5515 }
5516}
5517
5518static int rtw89_append_probe_req_ie(struct rtw89_dev *rtwdev,
5519 struct rtw89_vif *rtwvif,
5520 struct sk_buff *skb, u8 ssid_idx)
5521{
5522 struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
5523 struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
5524 struct rtw89_pktofld_info *info;
5525 struct sk_buff *new;
5526 int ret = 0;
5527 u8 band;
5528
5529 for (band = NL80211_BAND_2GHZ; band < NUM_NL80211_BANDS; band++) {
5530 if (!(rtwdev->chip->support_bands & BIT(band)))
5531 continue;
5532
5533 new = skb_copy(skb, GFP_KERNEL);
5534 if (!new) {
5535 ret = -ENOMEM;
5536 goto out;
5537 }
5538 skb_put_data(skb: new, data: ies->ies[band], len: ies->len[band]);
5539 skb_put_data(skb: new, data: ies->common_ies, len: ies->common_ie_len);
5540
5541 info = kzalloc(size: sizeof(*info), GFP_KERNEL);
5542 if (!info) {
5543 ret = -ENOMEM;
5544 kfree_skb(skb: new);
5545 goto out;
5546 }
5547
5548 if (rtw89_is_6ghz_wildcard_probe_req(rtwdev, rtwvif, info, band,
5549 ssid_idx)) {
5550 kfree_skb(skb: new);
5551 kfree(objp: info);
5552 goto out;
5553 }
5554
5555 ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, id: &info->id, skb_ofld: new);
5556 if (ret) {
5557 kfree_skb(skb: new);
5558 kfree(objp: info);
5559 goto out;
5560 }
5561
5562 list_add_tail(new: &info->list, head: &scan_info->pkt_list[band]);
5563 kfree_skb(skb: new);
5564 }
5565out:
5566 return ret;
5567}
5568
5569static int rtw89_hw_scan_update_probe_req(struct rtw89_dev *rtwdev,
5570 struct rtw89_vif *rtwvif)
5571{
5572 struct cfg80211_scan_request *req = rtwvif->scan_req;
5573 struct sk_buff *skb;
5574 u8 num = req->n_ssids, i;
5575 int ret;
5576
5577 for (i = 0; i < num; i++) {
5578 skb = ieee80211_probereq_get(hw: rtwdev->hw, src_addr: rtwvif->mac_addr,
5579 ssid: req->ssids[i].ssid,
5580 ssid_len: req->ssids[i].ssid_len,
5581 tailroom: req->ie_len);
5582 if (!skb)
5583 return -ENOMEM;
5584
5585 ret = rtw89_append_probe_req_ie(rtwdev, rtwvif, skb, ssid_idx: i);
5586 kfree_skb(skb);
5587
5588 if (ret)
5589 return ret;
5590 }
5591
5592 return 0;
5593}
5594
5595static int rtw89_update_6ghz_rnr_chan(struct rtw89_dev *rtwdev,
5596 struct cfg80211_scan_request *req,
5597 struct rtw89_mac_chinfo *ch_info)
5598{
5599 struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
5600 struct list_head *pkt_list = rtwdev->scan_info.pkt_list;
5601 struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
5602 struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
5603 struct cfg80211_scan_6ghz_params *params;
5604 struct rtw89_pktofld_info *info, *tmp;
5605 struct ieee80211_hdr *hdr;
5606 struct sk_buff *skb;
5607 bool found;
5608 int ret = 0;
5609 u8 i;
5610
5611 if (!req->n_6ghz_params)
5612 return 0;
5613
5614 for (i = 0; i < req->n_6ghz_params; i++) {
5615 params = &req->scan_6ghz_params[i];
5616
5617 if (req->channels[params->channel_idx]->hw_value !=
5618 ch_info->pri_ch)
5619 continue;
5620
5621 found = false;
5622 list_for_each_entry(tmp, &pkt_list[NL80211_BAND_6GHZ], list) {
5623 if (ether_addr_equal(addr1: tmp->bssid, addr2: params->bssid)) {
5624 found = true;
5625 break;
5626 }
5627 }
5628 if (found)
5629 continue;
5630
5631 skb = ieee80211_probereq_get(hw: rtwdev->hw, src_addr: rtwvif->mac_addr,
5632 NULL, ssid_len: 0, tailroom: req->ie_len);
5633 skb_put_data(skb, data: ies->ies[NL80211_BAND_6GHZ], len: ies->len[NL80211_BAND_6GHZ]);
5634 skb_put_data(skb, data: ies->common_ies, len: ies->common_ie_len);
5635 hdr = (struct ieee80211_hdr *)skb->data;
5636 ether_addr_copy(dst: hdr->addr3, src: params->bssid);
5637
5638 info = kzalloc(size: sizeof(*info), GFP_KERNEL);
5639 if (!info) {
5640 ret = -ENOMEM;
5641 kfree_skb(skb);
5642 goto out;
5643 }
5644
5645 ret = rtw89_fw_h2c_add_pkt_offload(rtwdev, id: &info->id, skb_ofld: skb);
5646 if (ret) {
5647 kfree_skb(skb);
5648 kfree(objp: info);
5649 goto out;
5650 }
5651
5652 ether_addr_copy(dst: info->bssid, src: params->bssid);
5653 info->channel_6ghz = req->channels[params->channel_idx]->hw_value;
5654 list_add_tail(new: &info->list, head: &rtwdev->scan_info.pkt_list[NL80211_BAND_6GHZ]);
5655
5656 ch_info->tx_pkt = true;
5657 ch_info->period = RTW89_CHANNEL_TIME_6G + RTW89_DWELL_TIME_6G;
5658
5659 kfree_skb(skb);
5660 }
5661
5662out:
5663 return ret;
5664}
5665
5666static void rtw89_hw_scan_add_chan(struct rtw89_dev *rtwdev, int chan_type,
5667 int ssid_num,
5668 struct rtw89_mac_chinfo *ch_info)
5669{
5670 struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
5671 struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
5672 struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
5673 struct cfg80211_scan_request *req = rtwvif->scan_req;
5674 struct rtw89_chan *op = &rtwdev->scan_info.op_chan;
5675 struct rtw89_pktofld_info *info;
5676 u8 band, probe_count = 0;
5677 int ret;
5678
5679 ch_info->notify_action = RTW89_SCANOFLD_DEBUG_MASK;
5680 ch_info->dfs_ch = chan_type == RTW89_CHAN_DFS;
5681 ch_info->bw = RTW89_SCAN_WIDTH;
5682 ch_info->tx_pkt = true;
5683 ch_info->cfg_tx_pwr = false;
5684 ch_info->tx_pwr_idx = 0;
5685 ch_info->tx_null = false;
5686 ch_info->pause_data = false;
5687 ch_info->probe_id = RTW89_SCANOFLD_PKT_NONE;
5688
5689 if (ch_info->ch_band == RTW89_BAND_6G) {
5690 if ((ssid_num == 1 && req->ssids[0].ssid_len == 0) ||
5691 !ch_info->is_psc) {
5692 ch_info->tx_pkt = false;
5693 if (!req->duration_mandatory)
5694 ch_info->period -= RTW89_DWELL_TIME_6G;
5695 }
5696 }
5697
5698 ret = rtw89_update_6ghz_rnr_chan(rtwdev, req, ch_info);
5699 if (ret)
5700 rtw89_warn(rtwdev, "RNR fails: %d\n", ret);
5701
5702 if (ssid_num) {
5703 band = rtw89_hw_to_nl80211_band(hw_band: ch_info->ch_band);
5704
5705 list_for_each_entry(info, &scan_info->pkt_list[band], list) {
5706 if (info->channel_6ghz &&
5707 ch_info->pri_ch != info->channel_6ghz)
5708 continue;
5709 else if (info->channel_6ghz && probe_count != 0)
5710 ch_info->period += RTW89_CHANNEL_TIME_6G;
5711 ch_info->pkt_id[probe_count++] = info->id;
5712 if (probe_count >= RTW89_SCANOFLD_MAX_SSID)
5713 break;
5714 }
5715 ch_info->num_pkt = probe_count;
5716 }
5717
5718 switch (chan_type) {
5719 case RTW89_CHAN_OPERATE:
5720 ch_info->central_ch = op->channel;
5721 ch_info->pri_ch = op->primary_channel;
5722 ch_info->ch_band = op->band_type;
5723 ch_info->bw = op->band_width;
5724 ch_info->tx_null = true;
5725 ch_info->num_pkt = 0;
5726 break;
5727 case RTW89_CHAN_DFS:
5728 if (ch_info->ch_band != RTW89_BAND_6G)
5729 ch_info->period = max_t(u8, ch_info->period,
5730 RTW89_DFS_CHAN_TIME);
5731 ch_info->dwell_time = RTW89_DWELL_TIME;
5732 break;
5733 case RTW89_CHAN_ACTIVE:
5734 break;
5735 default:
5736 rtw89_err(rtwdev, "Channel type out of bound\n");
5737 }
5738}
5739
5740static void rtw89_hw_scan_add_chan_be(struct rtw89_dev *rtwdev, int chan_type,
5741 int ssid_num,
5742 struct rtw89_mac_chinfo_be *ch_info)
5743{
5744 struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
5745 struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
5746 struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
5747 struct cfg80211_scan_request *req = rtwvif->scan_req;
5748 struct rtw89_pktofld_info *info;
5749 u8 band, probe_count = 0, i;
5750
5751 ch_info->notify_action = RTW89_SCANOFLD_DEBUG_MASK;
5752 ch_info->dfs_ch = chan_type == RTW89_CHAN_DFS;
5753 ch_info->bw = RTW89_SCAN_WIDTH;
5754 ch_info->tx_null = false;
5755 ch_info->pause_data = false;
5756 ch_info->probe_id = RTW89_SCANOFLD_PKT_NONE;
5757
5758 if (ssid_num) {
5759 band = rtw89_hw_to_nl80211_band(hw_band: ch_info->ch_band);
5760
5761 list_for_each_entry(info, &scan_info->pkt_list[band], list) {
5762 if (info->channel_6ghz &&
5763 ch_info->pri_ch != info->channel_6ghz)
5764 continue;
5765 ch_info->pkt_id[probe_count++] = info->id;
5766 if (probe_count >= RTW89_SCANOFLD_MAX_SSID)
5767 break;
5768 }
5769 }
5770
5771 if (ch_info->ch_band == RTW89_BAND_6G) {
5772 if ((ssid_num == 1 && req->ssids[0].ssid_len == 0) ||
5773 !ch_info->is_psc) {
5774 ch_info->probe_id = RTW89_SCANOFLD_PKT_NONE;
5775 if (!req->duration_mandatory)
5776 ch_info->period -= RTW89_DWELL_TIME_6G;
5777 }
5778 }
5779
5780 for (i = probe_count; i < RTW89_SCANOFLD_MAX_SSID; i++)
5781 ch_info->pkt_id[i] = RTW89_SCANOFLD_PKT_NONE;
5782
5783 switch (chan_type) {
5784 case RTW89_CHAN_DFS:
5785 if (ch_info->ch_band != RTW89_BAND_6G)
5786 ch_info->period =
5787 max_t(u8, ch_info->period, RTW89_DFS_CHAN_TIME);
5788 ch_info->dwell_time = RTW89_DWELL_TIME;
5789 break;
5790 case RTW89_CHAN_ACTIVE:
5791 break;
5792 default:
5793 rtw89_warn(rtwdev, "Channel type out of bound\n");
5794 break;
5795 }
5796}
5797
5798int rtw89_hw_scan_add_chan_list(struct rtw89_dev *rtwdev,
5799 struct rtw89_vif *rtwvif, bool connected)
5800{
5801 struct cfg80211_scan_request *req = rtwvif->scan_req;
5802 struct rtw89_mac_chinfo *ch_info, *tmp;
5803 struct ieee80211_channel *channel;
5804 struct list_head chan_list;
5805 bool random_seq = req->flags & NL80211_SCAN_FLAG_RANDOM_SN;
5806 int list_len, off_chan_time = 0;
5807 enum rtw89_chan_type type;
5808 int ret = 0;
5809 u32 idx;
5810
5811 INIT_LIST_HEAD(list: &chan_list);
5812 for (idx = rtwdev->scan_info.last_chan_idx, list_len = 0;
5813 idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT;
5814 idx++, list_len++) {
5815 channel = req->channels[idx];
5816 ch_info = kzalloc(size: sizeof(*ch_info), GFP_KERNEL);
5817 if (!ch_info) {
5818 ret = -ENOMEM;
5819 goto out;
5820 }
5821
5822 if (req->duration)
5823 ch_info->period = req->duration;
5824 else if (channel->band == NL80211_BAND_6GHZ)
5825 ch_info->period = RTW89_CHANNEL_TIME_6G +
5826 RTW89_DWELL_TIME_6G;
5827 else
5828 ch_info->period = RTW89_CHANNEL_TIME;
5829
5830 ch_info->ch_band = rtw89_nl80211_to_hw_band(nl_band: channel->band);
5831 ch_info->central_ch = channel->hw_value;
5832 ch_info->pri_ch = channel->hw_value;
5833 ch_info->rand_seq_num = random_seq;
5834 ch_info->is_psc = cfg80211_channel_is_psc(chan: channel);
5835
5836 if (channel->flags &
5837 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR))
5838 type = RTW89_CHAN_DFS;
5839 else
5840 type = RTW89_CHAN_ACTIVE;
5841 rtw89_hw_scan_add_chan(rtwdev, chan_type: type, ssid_num: req->n_ssids, ch_info);
5842
5843 if (connected &&
5844 off_chan_time + ch_info->period > RTW89_OFF_CHAN_TIME) {
5845 tmp = kzalloc(size: sizeof(*tmp), GFP_KERNEL);
5846 if (!tmp) {
5847 ret = -ENOMEM;
5848 kfree(objp: ch_info);
5849 goto out;
5850 }
5851
5852 type = RTW89_CHAN_OPERATE;
5853 tmp->period = req->duration_mandatory ?
5854 req->duration : RTW89_CHANNEL_TIME;
5855 rtw89_hw_scan_add_chan(rtwdev, chan_type: type, ssid_num: 0, ch_info: tmp);
5856 list_add_tail(new: &tmp->list, head: &chan_list);
5857 off_chan_time = 0;
5858 list_len++;
5859 }
5860 list_add_tail(new: &ch_info->list, head: &chan_list);
5861 off_chan_time += ch_info->period;
5862 }
5863 rtwdev->scan_info.last_chan_idx = idx;
5864 ret = rtw89_fw_h2c_scan_list_offload(rtwdev, ch_num: list_len, chan_list: &chan_list);
5865
5866out:
5867 list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
5868 list_del(entry: &ch_info->list);
5869 kfree(objp: ch_info);
5870 }
5871
5872 return ret;
5873}
5874
5875int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
5876 struct rtw89_vif *rtwvif, bool connected)
5877{
5878 struct cfg80211_scan_request *req = rtwvif->scan_req;
5879 struct rtw89_mac_chinfo_be *ch_info, *tmp;
5880 struct ieee80211_channel *channel;
5881 struct list_head chan_list;
5882 enum rtw89_chan_type type;
5883 int list_len, ret;
5884 bool random_seq;
5885 u32 idx;
5886
5887 random_seq = !!(req->flags & NL80211_SCAN_FLAG_RANDOM_SN);
5888 INIT_LIST_HEAD(list: &chan_list);
5889
5890 for (idx = rtwdev->scan_info.last_chan_idx, list_len = 0;
5891 idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT;
5892 idx++, list_len++) {
5893 channel = req->channels[idx];
5894 ch_info = kzalloc(size: sizeof(*ch_info), GFP_KERNEL);
5895 if (!ch_info) {
5896 ret = -ENOMEM;
5897 goto out;
5898 }
5899
5900 if (req->duration)
5901 ch_info->period = req->duration;
5902 else if (channel->band == NL80211_BAND_6GHZ)
5903 ch_info->period = RTW89_CHANNEL_TIME_6G + RTW89_DWELL_TIME_6G;
5904 else
5905 ch_info->period = RTW89_CHANNEL_TIME;
5906
5907 ch_info->ch_band = rtw89_nl80211_to_hw_band(nl_band: channel->band);
5908 ch_info->central_ch = channel->hw_value;
5909 ch_info->pri_ch = channel->hw_value;
5910 ch_info->rand_seq_num = random_seq;
5911 ch_info->is_psc = cfg80211_channel_is_psc(chan: channel);
5912
5913 if (channel->flags & (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR))
5914 type = RTW89_CHAN_DFS;
5915 else
5916 type = RTW89_CHAN_ACTIVE;
5917 rtw89_hw_scan_add_chan_be(rtwdev, chan_type: type, ssid_num: req->n_ssids, ch_info);
5918
5919 list_add_tail(new: &ch_info->list, head: &chan_list);
5920 }
5921
5922 rtwdev->scan_info.last_chan_idx = idx;
5923 ret = rtw89_fw_h2c_scan_list_offload_be(rtwdev, ch_num: list_len, chan_list: &chan_list);
5924
5925out:
5926 list_for_each_entry_safe(ch_info, tmp, &chan_list, list) {
5927 list_del(entry: &ch_info->list);
5928 kfree(objp: ch_info);
5929 }
5930
5931 return ret;
5932}
5933
5934static int rtw89_hw_scan_prehandle(struct rtw89_dev *rtwdev,
5935 struct rtw89_vif *rtwvif, bool connected)
5936{
5937 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
5938 int ret;
5939
5940 ret = rtw89_hw_scan_update_probe_req(rtwdev, rtwvif);
5941 if (ret) {
5942 rtw89_err(rtwdev, "Update probe request failed\n");
5943 goto out;
5944 }
5945 ret = mac->add_chan_list(rtwdev, rtwvif, connected);
5946out:
5947 return ret;
5948}
5949
5950void rtw89_hw_scan_start(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
5951 struct ieee80211_scan_request *scan_req)
5952{
5953 struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
5954 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
5955 struct cfg80211_scan_request *req = &scan_req->req;
5956 u32 rx_fltr = rtwdev->hal.rx_fltr;
5957 u8 mac_addr[ETH_ALEN];
5958
5959 rtw89_get_channel(rtwdev, rtwvif, chan: &rtwdev->scan_info.op_chan);
5960 rtwdev->scan_info.scanning_vif = vif;
5961 rtwdev->scan_info.last_chan_idx = 0;
5962 rtwdev->scan_info.abort = false;
5963 rtwvif->scan_ies = &scan_req->ies;
5964 rtwvif->scan_req = req;
5965 ieee80211_stop_queues(hw: rtwdev->hw);
5966 rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, en: false);
5967
5968 if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
5969 get_random_mask_addr(buf: mac_addr, addr: req->mac_addr,
5970 mask: req->mac_addr_mask);
5971 else
5972 ether_addr_copy(dst: mac_addr, src: vif->addr);
5973 rtw89_core_scan_start(rtwdev, rtwvif, mac_addr, hw_scan: true);
5974
5975 rx_fltr &= ~B_AX_A_BCN_CHK_EN;
5976 rx_fltr &= ~B_AX_A_BC;
5977 rx_fltr &= ~B_AX_A_A1_MATCH;
5978 rtw89_write32_mask(rtwdev,
5979 addr: rtw89_mac_reg_by_idx(rtwdev, reg_base: mac->rx_fltr, band: RTW89_MAC_0),
5980 B_AX_RX_FLTR_CFG_MASK,
5981 data: rx_fltr);
5982
5983 rtw89_chanctx_pause(rtwdev, rsn: RTW89_CHANCTX_PAUSE_REASON_HW_SCAN);
5984}
5985
5986void rtw89_hw_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
5987 bool aborted)
5988{
5989 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
5990 struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
5991 struct rtw89_vif *rtwvif = vif_to_rtwvif_safe(vif);
5992 struct cfg80211_scan_info info = {
5993 .aborted = aborted,
5994 };
5995
5996 if (!vif)
5997 return;
5998
5999 rtw89_write32_mask(rtwdev,
6000 addr: rtw89_mac_reg_by_idx(rtwdev, reg_base: mac->rx_fltr, band: RTW89_MAC_0),
6001 B_AX_RX_FLTR_CFG_MASK,
6002 data: rtwdev->hal.rx_fltr);
6003
6004 rtw89_core_scan_complete(rtwdev, vif, hw_scan: true);
6005 ieee80211_scan_completed(hw: rtwdev->hw, info: &info);
6006 ieee80211_wake_queues(hw: rtwdev->hw);
6007 rtw89_mac_port_cfg_rx_sync(rtwdev, rtwvif, en: true);
6008 rtw89_mac_enable_beacon_for_ap_vifs(rtwdev, en: true);
6009
6010 rtw89_release_pkt_list(rtwdev);
6011 rtwvif->scan_req = NULL;
6012 rtwvif->scan_ies = NULL;
6013 scan_info->last_chan_idx = 0;
6014 scan_info->scanning_vif = NULL;
6015 scan_info->abort = false;
6016
6017 rtw89_chanctx_proceed(rtwdev);
6018}
6019
6020void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif)
6021{
6022 struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
6023 int ret;
6024
6025 scan_info->abort = true;
6026
6027 ret = rtw89_hw_scan_offload(rtwdev, vif, enable: false);
6028 if (ret)
6029 rtw89_hw_scan_complete(rtwdev, vif, aborted: true);
6030}
6031
6032static bool rtw89_is_any_vif_connected_or_connecting(struct rtw89_dev *rtwdev)
6033{
6034 struct rtw89_vif *rtwvif;
6035
6036 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
6037 /* This variable implies connected or during attempt to connect */
6038 if (!is_zero_ether_addr(addr: rtwvif->bssid))
6039 return true;
6040 }
6041
6042 return false;
6043}
6044
6045int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
6046 bool enable)
6047{
6048 const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
6049 struct rtw89_scan_option opt = {0};
6050 struct rtw89_vif *rtwvif;
6051 bool connected;
6052 int ret = 0;
6053
6054 rtwvif = vif ? (struct rtw89_vif *)vif->drv_priv : NULL;
6055 if (!rtwvif)
6056 return -EINVAL;
6057
6058 connected = rtw89_is_any_vif_connected_or_connecting(rtwdev);
6059 opt.enable = enable;
6060 opt.target_ch_mode = connected;
6061 if (enable) {
6062 ret = rtw89_hw_scan_prehandle(rtwdev, rtwvif, connected);
6063 if (ret)
6064 goto out;
6065 }
6066
6067 if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) {
6068 opt.operation = enable ? RTW89_SCAN_OP_START : RTW89_SCAN_OP_STOP;
6069 opt.scan_mode = RTW89_SCAN_MODE_SA;
6070 opt.band = RTW89_PHY_0;
6071 opt.num_macc_role = 0;
6072 opt.mlo_mode = rtwdev->mlo_dbcc_mode;
6073 opt.num_opch = connected ? 1 : 0;
6074 opt.opch_end = connected ? 0 : RTW89_CHAN_INVALID;
6075 }
6076
6077 ret = mac->scan_offload(rtwdev, &opt, rtwvif);
6078out:
6079 return ret;
6080}
6081
6082#define H2C_FW_CPU_EXCEPTION_LEN 4
6083#define H2C_FW_CPU_EXCEPTION_TYPE_DEF 0x5566
6084int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev)
6085{
6086 struct sk_buff *skb;
6087 int ret;
6088
6089 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_FW_CPU_EXCEPTION_LEN);
6090 if (!skb) {
6091 rtw89_err(rtwdev,
6092 "failed to alloc skb for fw cpu exception\n");
6093 return -ENOMEM;
6094 }
6095
6096 skb_put(skb, H2C_FW_CPU_EXCEPTION_LEN);
6097 RTW89_SET_FWCMD_CPU_EXCEPTION_TYPE(cmd: skb->data,
6098 H2C_FW_CPU_EXCEPTION_TYPE_DEF);
6099
6100 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6101 H2C_CAT_TEST,
6102 H2C_CL_FW_STATUS_TEST,
6103 H2C_FUNC_CPU_EXCEPTION, rack: 0, dack: 0,
6104 H2C_FW_CPU_EXCEPTION_LEN);
6105
6106 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6107 if (ret) {
6108 rtw89_err(rtwdev, "failed to send h2c\n");
6109 goto fail;
6110 }
6111
6112 return 0;
6113
6114fail:
6115 dev_kfree_skb_any(skb);
6116 return ret;
6117}
6118
6119#define H2C_PKT_DROP_LEN 24
6120int rtw89_fw_h2c_pkt_drop(struct rtw89_dev *rtwdev,
6121 const struct rtw89_pkt_drop_params *params)
6122{
6123 struct sk_buff *skb;
6124 int ret;
6125
6126 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_PKT_DROP_LEN);
6127 if (!skb) {
6128 rtw89_err(rtwdev,
6129 "failed to alloc skb for packet drop\n");
6130 return -ENOMEM;
6131 }
6132
6133 switch (params->sel) {
6134 case RTW89_PKT_DROP_SEL_MACID_BE_ONCE:
6135 case RTW89_PKT_DROP_SEL_MACID_BK_ONCE:
6136 case RTW89_PKT_DROP_SEL_MACID_VI_ONCE:
6137 case RTW89_PKT_DROP_SEL_MACID_VO_ONCE:
6138 case RTW89_PKT_DROP_SEL_BAND_ONCE:
6139 break;
6140 default:
6141 rtw89_debug(rtwdev, mask: RTW89_DBG_FW,
6142 fmt: "H2C of pkt drop might not fully support sel: %d yet\n",
6143 params->sel);
6144 break;
6145 }
6146
6147 skb_put(skb, H2C_PKT_DROP_LEN);
6148 RTW89_SET_FWCMD_PKT_DROP_SEL(cmd: skb->data, val: params->sel);
6149 RTW89_SET_FWCMD_PKT_DROP_MACID(cmd: skb->data, val: params->macid);
6150 RTW89_SET_FWCMD_PKT_DROP_BAND(cmd: skb->data, val: params->mac_band);
6151 RTW89_SET_FWCMD_PKT_DROP_PORT(cmd: skb->data, val: params->port);
6152 RTW89_SET_FWCMD_PKT_DROP_MBSSID(cmd: skb->data, val: params->mbssid);
6153 RTW89_SET_FWCMD_PKT_DROP_ROLE_A_INFO_TF_TRS(cmd: skb->data, val: params->tf_trs);
6154 RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_0(cmd: skb->data,
6155 val: params->macid_band_sel[0]);
6156 RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_1(cmd: skb->data,
6157 val: params->macid_band_sel[1]);
6158 RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_2(cmd: skb->data,
6159 val: params->macid_band_sel[2]);
6160 RTW89_SET_FWCMD_PKT_DROP_MACID_BAND_SEL_3(cmd: skb->data,
6161 val: params->macid_band_sel[3]);
6162
6163 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6164 H2C_CAT_MAC,
6165 H2C_CL_MAC_FW_OFLD,
6166 func: H2C_FUNC_PKT_DROP, rack: 0, dack: 0,
6167 H2C_PKT_DROP_LEN);
6168
6169 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6170 if (ret) {
6171 rtw89_err(rtwdev, "failed to send h2c\n");
6172 goto fail;
6173 }
6174
6175 return 0;
6176
6177fail:
6178 dev_kfree_skb_any(skb);
6179 return ret;
6180}
6181
6182#define H2C_KEEP_ALIVE_LEN 4
6183int rtw89_fw_h2c_keep_alive(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
6184 bool enable)
6185{
6186 struct sk_buff *skb;
6187 u8 pkt_id = 0;
6188 int ret;
6189
6190 if (enable) {
6191 ret = rtw89_fw_h2c_add_general_pkt(rtwdev, rtwvif,
6192 type: RTW89_PKT_OFLD_TYPE_NULL_DATA,
6193 id: &pkt_id);
6194 if (ret)
6195 return -EPERM;
6196 }
6197
6198 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_KEEP_ALIVE_LEN);
6199 if (!skb) {
6200 rtw89_err(rtwdev, "failed to alloc skb for keep alive\n");
6201 return -ENOMEM;
6202 }
6203
6204 skb_put(skb, H2C_KEEP_ALIVE_LEN);
6205
6206 RTW89_SET_KEEP_ALIVE_ENABLE(h2c: skb->data, val: enable);
6207 RTW89_SET_KEEP_ALIVE_PKT_NULL_ID(h2c: skb->data, val: pkt_id);
6208 RTW89_SET_KEEP_ALIVE_PERIOD(h2c: skb->data, val: 5);
6209 RTW89_SET_KEEP_ALIVE_MACID(h2c: skb->data, val: rtwvif->mac_id);
6210
6211 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6212 H2C_CAT_MAC,
6213 H2C_CL_MAC_WOW,
6214 H2C_FUNC_KEEP_ALIVE, rack: 0, dack: 1,
6215 H2C_KEEP_ALIVE_LEN);
6216
6217 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6218 if (ret) {
6219 rtw89_err(rtwdev, "failed to send h2c\n");
6220 goto fail;
6221 }
6222
6223 return 0;
6224
6225fail:
6226 dev_kfree_skb_any(skb);
6227
6228 return ret;
6229}
6230
6231#define H2C_DISCONNECT_DETECT_LEN 8
6232int rtw89_fw_h2c_disconnect_detect(struct rtw89_dev *rtwdev,
6233 struct rtw89_vif *rtwvif, bool enable)
6234{
6235 struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
6236 struct sk_buff *skb;
6237 u8 macid = rtwvif->mac_id;
6238 int ret;
6239
6240 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DISCONNECT_DETECT_LEN);
6241 if (!skb) {
6242 rtw89_err(rtwdev, "failed to alloc skb for keep alive\n");
6243 return -ENOMEM;
6244 }
6245
6246 skb_put(skb, H2C_DISCONNECT_DETECT_LEN);
6247
6248 if (test_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) {
6249 RTW89_SET_DISCONNECT_DETECT_ENABLE(h2c: skb->data, val: enable);
6250 RTW89_SET_DISCONNECT_DETECT_DISCONNECT(h2c: skb->data, val: !enable);
6251 RTW89_SET_DISCONNECT_DETECT_MAC_ID(h2c: skb->data, val: macid);
6252 RTW89_SET_DISCONNECT_DETECT_CHECK_PERIOD(h2c: skb->data, val: 100);
6253 RTW89_SET_DISCONNECT_DETECT_TRY_PKT_COUNT(h2c: skb->data, val: 5);
6254 }
6255
6256 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6257 H2C_CAT_MAC,
6258 H2C_CL_MAC_WOW,
6259 H2C_FUNC_DISCONNECT_DETECT, rack: 0, dack: 1,
6260 H2C_DISCONNECT_DETECT_LEN);
6261
6262 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6263 if (ret) {
6264 rtw89_err(rtwdev, "failed to send h2c\n");
6265 goto fail;
6266 }
6267
6268 return 0;
6269
6270fail:
6271 dev_kfree_skb_any(skb);
6272
6273 return ret;
6274}
6275
6276#define H2C_WOW_GLOBAL_LEN 8
6277int rtw89_fw_h2c_wow_global(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
6278 bool enable)
6279{
6280 struct sk_buff *skb;
6281 u8 macid = rtwvif->mac_id;
6282 int ret;
6283
6284 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WOW_GLOBAL_LEN);
6285 if (!skb) {
6286 rtw89_err(rtwdev, "failed to alloc skb for keep alive\n");
6287 return -ENOMEM;
6288 }
6289
6290 skb_put(skb, H2C_WOW_GLOBAL_LEN);
6291
6292 RTW89_SET_WOW_GLOBAL_ENABLE(h2c: skb->data, val: enable);
6293 RTW89_SET_WOW_GLOBAL_MAC_ID(h2c: skb->data, val: macid);
6294
6295 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6296 H2C_CAT_MAC,
6297 H2C_CL_MAC_WOW,
6298 H2C_FUNC_WOW_GLOBAL, rack: 0, dack: 1,
6299 H2C_WOW_GLOBAL_LEN);
6300
6301 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6302 if (ret) {
6303 rtw89_err(rtwdev, "failed to send h2c\n");
6304 goto fail;
6305 }
6306
6307 return 0;
6308
6309fail:
6310 dev_kfree_skb_any(skb);
6311
6312 return ret;
6313}
6314
6315#define H2C_WAKEUP_CTRL_LEN 4
6316int rtw89_fw_h2c_wow_wakeup_ctrl(struct rtw89_dev *rtwdev,
6317 struct rtw89_vif *rtwvif,
6318 bool enable)
6319{
6320 struct rtw89_wow_param *rtw_wow = &rtwdev->wow;
6321 struct sk_buff *skb;
6322 u8 macid = rtwvif->mac_id;
6323 int ret;
6324
6325 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WAKEUP_CTRL_LEN);
6326 if (!skb) {
6327 rtw89_err(rtwdev, "failed to alloc skb for keep alive\n");
6328 return -ENOMEM;
6329 }
6330
6331 skb_put(skb, H2C_WAKEUP_CTRL_LEN);
6332
6333 if (rtw_wow->pattern_cnt)
6334 RTW89_SET_WOW_WAKEUP_CTRL_PATTERN_MATCH_ENABLE(h2c: skb->data, val: enable);
6335 if (test_bit(RTW89_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags))
6336 RTW89_SET_WOW_WAKEUP_CTRL_MAGIC_ENABLE(h2c: skb->data, val: enable);
6337 if (test_bit(RTW89_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags))
6338 RTW89_SET_WOW_WAKEUP_CTRL_DEAUTH_ENABLE(h2c: skb->data, val: enable);
6339
6340 RTW89_SET_WOW_WAKEUP_CTRL_MAC_ID(h2c: skb->data, val: macid);
6341
6342 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6343 H2C_CAT_MAC,
6344 H2C_CL_MAC_WOW,
6345 H2C_FUNC_WAKEUP_CTRL, rack: 0, dack: 1,
6346 H2C_WAKEUP_CTRL_LEN);
6347
6348 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6349 if (ret) {
6350 rtw89_err(rtwdev, "failed to send h2c\n");
6351 goto fail;
6352 }
6353
6354 return 0;
6355
6356fail:
6357 dev_kfree_skb_any(skb);
6358
6359 return ret;
6360}
6361
6362#define H2C_WOW_CAM_UPD_LEN 24
6363int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev,
6364 struct rtw89_wow_cam_info *cam_info)
6365{
6366 struct sk_buff *skb;
6367 int ret;
6368
6369 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_WOW_CAM_UPD_LEN);
6370 if (!skb) {
6371 rtw89_err(rtwdev, "failed to alloc skb for keep alive\n");
6372 return -ENOMEM;
6373 }
6374
6375 skb_put(skb, H2C_WOW_CAM_UPD_LEN);
6376
6377 RTW89_SET_WOW_CAM_UPD_R_W(h2c: skb->data, val: cam_info->r_w);
6378 RTW89_SET_WOW_CAM_UPD_IDX(h2c: skb->data, val: cam_info->idx);
6379 if (cam_info->valid) {
6380 RTW89_SET_WOW_CAM_UPD_WKFM1(h2c: skb->data, val: cam_info->mask[0]);
6381 RTW89_SET_WOW_CAM_UPD_WKFM2(h2c: skb->data, val: cam_info->mask[1]);
6382 RTW89_SET_WOW_CAM_UPD_WKFM3(h2c: skb->data, val: cam_info->mask[2]);
6383 RTW89_SET_WOW_CAM_UPD_WKFM4(h2c: skb->data, val: cam_info->mask[3]);
6384 RTW89_SET_WOW_CAM_UPD_CRC(h2c: skb->data, val: cam_info->crc);
6385 RTW89_SET_WOW_CAM_UPD_NEGATIVE_PATTERN_MATCH(h2c: skb->data,
6386 val: cam_info->negative_pattern_match);
6387 RTW89_SET_WOW_CAM_UPD_SKIP_MAC_HDR(h2c: skb->data,
6388 val: cam_info->skip_mac_hdr);
6389 RTW89_SET_WOW_CAM_UPD_UC(h2c: skb->data, val: cam_info->uc);
6390 RTW89_SET_WOW_CAM_UPD_MC(h2c: skb->data, val: cam_info->mc);
6391 RTW89_SET_WOW_CAM_UPD_BC(h2c: skb->data, val: cam_info->bc);
6392 }
6393 RTW89_SET_WOW_CAM_UPD_VALID(h2c: skb->data, val: cam_info->valid);
6394
6395 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6396 H2C_CAT_MAC,
6397 H2C_CL_MAC_WOW,
6398 H2C_FUNC_WOW_CAM_UPD, rack: 0, dack: 1,
6399 H2C_WOW_CAM_UPD_LEN);
6400
6401 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6402 if (ret) {
6403 rtw89_err(rtwdev, "failed to send h2c\n");
6404 goto fail;
6405 }
6406
6407 return 0;
6408fail:
6409 dev_kfree_skb_any(skb);
6410
6411 return ret;
6412}
6413
6414/* Return < 0, if failures happen during waiting for the condition.
6415 * Return 0, when waiting for the condition succeeds.
6416 * Return > 0, if the wait is considered unreachable due to driver/FW design,
6417 * where 1 means during SER.
6418 */
6419static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb,
6420 struct rtw89_wait_info *wait, unsigned int cond)
6421{
6422 int ret;
6423
6424 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6425 if (ret) {
6426 rtw89_err(rtwdev, "failed to send h2c\n");
6427 dev_kfree_skb_any(skb);
6428 return -EBUSY;
6429 }
6430
6431 if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
6432 return 1;
6433
6434 return rtw89_wait_for_cond(wait, cond);
6435}
6436
6437#define H2C_ADD_MCC_LEN 16
6438int rtw89_fw_h2c_add_mcc(struct rtw89_dev *rtwdev,
6439 const struct rtw89_fw_mcc_add_req *p)
6440{
6441 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6442 struct sk_buff *skb;
6443 unsigned int cond;
6444
6445 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_ADD_MCC_LEN);
6446 if (!skb) {
6447 rtw89_err(rtwdev,
6448 "failed to alloc skb for add mcc\n");
6449 return -ENOMEM;
6450 }
6451
6452 skb_put(skb, H2C_ADD_MCC_LEN);
6453 RTW89_SET_FWCMD_ADD_MCC_MACID(cmd: skb->data, val: p->macid);
6454 RTW89_SET_FWCMD_ADD_MCC_CENTRAL_CH_SEG0(cmd: skb->data, val: p->central_ch_seg0);
6455 RTW89_SET_FWCMD_ADD_MCC_CENTRAL_CH_SEG1(cmd: skb->data, val: p->central_ch_seg1);
6456 RTW89_SET_FWCMD_ADD_MCC_PRIMARY_CH(cmd: skb->data, val: p->primary_ch);
6457 RTW89_SET_FWCMD_ADD_MCC_BANDWIDTH(cmd: skb->data, val: p->bandwidth);
6458 RTW89_SET_FWCMD_ADD_MCC_GROUP(cmd: skb->data, val: p->group);
6459 RTW89_SET_FWCMD_ADD_MCC_C2H_RPT(cmd: skb->data, val: p->c2h_rpt);
6460 RTW89_SET_FWCMD_ADD_MCC_DIS_TX_NULL(cmd: skb->data, val: p->dis_tx_null);
6461 RTW89_SET_FWCMD_ADD_MCC_DIS_SW_RETRY(cmd: skb->data, val: p->dis_sw_retry);
6462 RTW89_SET_FWCMD_ADD_MCC_IN_CURR_CH(cmd: skb->data, val: p->in_curr_ch);
6463 RTW89_SET_FWCMD_ADD_MCC_SW_RETRY_COUNT(cmd: skb->data, val: p->sw_retry_count);
6464 RTW89_SET_FWCMD_ADD_MCC_TX_NULL_EARLY(cmd: skb->data, val: p->tx_null_early);
6465 RTW89_SET_FWCMD_ADD_MCC_BTC_IN_2G(cmd: skb->data, val: p->btc_in_2g);
6466 RTW89_SET_FWCMD_ADD_MCC_PTA_EN(cmd: skb->data, val: p->pta_en);
6467 RTW89_SET_FWCMD_ADD_MCC_RFK_BY_PASS(cmd: skb->data, val: p->rfk_by_pass);
6468 RTW89_SET_FWCMD_ADD_MCC_CH_BAND_TYPE(cmd: skb->data, val: p->ch_band_type);
6469 RTW89_SET_FWCMD_ADD_MCC_DURATION(cmd: skb->data, val: p->duration);
6470 RTW89_SET_FWCMD_ADD_MCC_COURTESY_EN(cmd: skb->data, val: p->courtesy_en);
6471 RTW89_SET_FWCMD_ADD_MCC_COURTESY_NUM(cmd: skb->data, val: p->courtesy_num);
6472 RTW89_SET_FWCMD_ADD_MCC_COURTESY_TARGET(cmd: skb->data, val: p->courtesy_target);
6473
6474 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6475 H2C_CAT_MAC,
6476 H2C_CL_MCC,
6477 func: H2C_FUNC_ADD_MCC, rack: 0, dack: 0,
6478 H2C_ADD_MCC_LEN);
6479
6480 cond = RTW89_MCC_WAIT_COND(p->group, H2C_FUNC_ADD_MCC);
6481 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6482}
6483
6484#define H2C_START_MCC_LEN 12
6485int rtw89_fw_h2c_start_mcc(struct rtw89_dev *rtwdev,
6486 const struct rtw89_fw_mcc_start_req *p)
6487{
6488 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6489 struct sk_buff *skb;
6490 unsigned int cond;
6491
6492 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_START_MCC_LEN);
6493 if (!skb) {
6494 rtw89_err(rtwdev,
6495 "failed to alloc skb for start mcc\n");
6496 return -ENOMEM;
6497 }
6498
6499 skb_put(skb, H2C_START_MCC_LEN);
6500 RTW89_SET_FWCMD_START_MCC_GROUP(cmd: skb->data, val: p->group);
6501 RTW89_SET_FWCMD_START_MCC_BTC_IN_GROUP(cmd: skb->data, val: p->btc_in_group);
6502 RTW89_SET_FWCMD_START_MCC_OLD_GROUP_ACTION(cmd: skb->data, val: p->old_group_action);
6503 RTW89_SET_FWCMD_START_MCC_OLD_GROUP(cmd: skb->data, val: p->old_group);
6504 RTW89_SET_FWCMD_START_MCC_NOTIFY_CNT(cmd: skb->data, val: p->notify_cnt);
6505 RTW89_SET_FWCMD_START_MCC_NOTIFY_RXDBG_EN(cmd: skb->data, val: p->notify_rxdbg_en);
6506 RTW89_SET_FWCMD_START_MCC_MACID(cmd: skb->data, val: p->macid);
6507 RTW89_SET_FWCMD_START_MCC_TSF_LOW(cmd: skb->data, val: p->tsf_low);
6508 RTW89_SET_FWCMD_START_MCC_TSF_HIGH(cmd: skb->data, val: p->tsf_high);
6509
6510 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6511 H2C_CAT_MAC,
6512 H2C_CL_MCC,
6513 func: H2C_FUNC_START_MCC, rack: 0, dack: 0,
6514 H2C_START_MCC_LEN);
6515
6516 cond = RTW89_MCC_WAIT_COND(p->group, H2C_FUNC_START_MCC);
6517 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6518}
6519
6520#define H2C_STOP_MCC_LEN 4
6521int rtw89_fw_h2c_stop_mcc(struct rtw89_dev *rtwdev, u8 group, u8 macid,
6522 bool prev_groups)
6523{
6524 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6525 struct sk_buff *skb;
6526 unsigned int cond;
6527
6528 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_STOP_MCC_LEN);
6529 if (!skb) {
6530 rtw89_err(rtwdev,
6531 "failed to alloc skb for stop mcc\n");
6532 return -ENOMEM;
6533 }
6534
6535 skb_put(skb, H2C_STOP_MCC_LEN);
6536 RTW89_SET_FWCMD_STOP_MCC_MACID(cmd: skb->data, val: macid);
6537 RTW89_SET_FWCMD_STOP_MCC_GROUP(cmd: skb->data, val: group);
6538 RTW89_SET_FWCMD_STOP_MCC_PREV_GROUPS(cmd: skb->data, val: prev_groups);
6539
6540 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6541 H2C_CAT_MAC,
6542 H2C_CL_MCC,
6543 func: H2C_FUNC_STOP_MCC, rack: 0, dack: 0,
6544 H2C_STOP_MCC_LEN);
6545
6546 cond = RTW89_MCC_WAIT_COND(group, H2C_FUNC_STOP_MCC);
6547 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6548}
6549
6550#define H2C_DEL_MCC_GROUP_LEN 4
6551int rtw89_fw_h2c_del_mcc_group(struct rtw89_dev *rtwdev, u8 group,
6552 bool prev_groups)
6553{
6554 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6555 struct sk_buff *skb;
6556 unsigned int cond;
6557
6558 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_DEL_MCC_GROUP_LEN);
6559 if (!skb) {
6560 rtw89_err(rtwdev,
6561 "failed to alloc skb for del mcc group\n");
6562 return -ENOMEM;
6563 }
6564
6565 skb_put(skb, H2C_DEL_MCC_GROUP_LEN);
6566 RTW89_SET_FWCMD_DEL_MCC_GROUP_GROUP(cmd: skb->data, val: group);
6567 RTW89_SET_FWCMD_DEL_MCC_GROUP_PREV_GROUPS(cmd: skb->data, val: prev_groups);
6568
6569 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6570 H2C_CAT_MAC,
6571 H2C_CL_MCC,
6572 func: H2C_FUNC_DEL_MCC_GROUP, rack: 0, dack: 0,
6573 H2C_DEL_MCC_GROUP_LEN);
6574
6575 cond = RTW89_MCC_WAIT_COND(group, H2C_FUNC_DEL_MCC_GROUP);
6576 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6577}
6578
6579#define H2C_RESET_MCC_GROUP_LEN 4
6580int rtw89_fw_h2c_reset_mcc_group(struct rtw89_dev *rtwdev, u8 group)
6581{
6582 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6583 struct sk_buff *skb;
6584 unsigned int cond;
6585
6586 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_RESET_MCC_GROUP_LEN);
6587 if (!skb) {
6588 rtw89_err(rtwdev,
6589 "failed to alloc skb for reset mcc group\n");
6590 return -ENOMEM;
6591 }
6592
6593 skb_put(skb, H2C_RESET_MCC_GROUP_LEN);
6594 RTW89_SET_FWCMD_RESET_MCC_GROUP_GROUP(cmd: skb->data, val: group);
6595
6596 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6597 H2C_CAT_MAC,
6598 H2C_CL_MCC,
6599 func: H2C_FUNC_RESET_MCC_GROUP, rack: 0, dack: 0,
6600 H2C_RESET_MCC_GROUP_LEN);
6601
6602 cond = RTW89_MCC_WAIT_COND(group, H2C_FUNC_RESET_MCC_GROUP);
6603 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6604}
6605
6606#define H2C_MCC_REQ_TSF_LEN 4
6607int rtw89_fw_h2c_mcc_req_tsf(struct rtw89_dev *rtwdev,
6608 const struct rtw89_fw_mcc_tsf_req *req,
6609 struct rtw89_mac_mcc_tsf_rpt *rpt)
6610{
6611 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6612 struct rtw89_mac_mcc_tsf_rpt *tmp;
6613 struct sk_buff *skb;
6614 unsigned int cond;
6615 int ret;
6616
6617 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_MCC_REQ_TSF_LEN);
6618 if (!skb) {
6619 rtw89_err(rtwdev,
6620 "failed to alloc skb for mcc req tsf\n");
6621 return -ENOMEM;
6622 }
6623
6624 skb_put(skb, H2C_MCC_REQ_TSF_LEN);
6625 RTW89_SET_FWCMD_MCC_REQ_TSF_GROUP(cmd: skb->data, val: req->group);
6626 RTW89_SET_FWCMD_MCC_REQ_TSF_MACID_X(cmd: skb->data, val: req->macid_x);
6627 RTW89_SET_FWCMD_MCC_REQ_TSF_MACID_Y(cmd: skb->data, val: req->macid_y);
6628
6629 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6630 H2C_CAT_MAC,
6631 H2C_CL_MCC,
6632 func: H2C_FUNC_MCC_REQ_TSF, rack: 0, dack: 0,
6633 H2C_MCC_REQ_TSF_LEN);
6634
6635 cond = RTW89_MCC_WAIT_COND(req->group, H2C_FUNC_MCC_REQ_TSF);
6636 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6637 if (ret)
6638 return ret;
6639
6640 tmp = (struct rtw89_mac_mcc_tsf_rpt *)wait->data.buf;
6641 *rpt = *tmp;
6642
6643 return 0;
6644}
6645
6646#define H2C_MCC_MACID_BITMAP_DSC_LEN 4
6647int rtw89_fw_h2c_mcc_macid_bitmap(struct rtw89_dev *rtwdev, u8 group, u8 macid,
6648 u8 *bitmap)
6649{
6650 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6651 struct sk_buff *skb;
6652 unsigned int cond;
6653 u8 map_len;
6654 u8 h2c_len;
6655
6656 BUILD_BUG_ON(RTW89_MAX_MAC_ID_NUM % 8);
6657 map_len = RTW89_MAX_MAC_ID_NUM / 8;
6658 h2c_len = H2C_MCC_MACID_BITMAP_DSC_LEN + map_len;
6659 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len: h2c_len);
6660 if (!skb) {
6661 rtw89_err(rtwdev,
6662 "failed to alloc skb for mcc macid bitmap\n");
6663 return -ENOMEM;
6664 }
6665
6666 skb_put(skb, len: h2c_len);
6667 RTW89_SET_FWCMD_MCC_MACID_BITMAP_GROUP(cmd: skb->data, val: group);
6668 RTW89_SET_FWCMD_MCC_MACID_BITMAP_MACID(cmd: skb->data, val: macid);
6669 RTW89_SET_FWCMD_MCC_MACID_BITMAP_BITMAP_LENGTH(cmd: skb->data, val: map_len);
6670 RTW89_SET_FWCMD_MCC_MACID_BITMAP_BITMAP(cmd: skb->data, bitmap, len: map_len);
6671
6672 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6673 H2C_CAT_MAC,
6674 H2C_CL_MCC,
6675 func: H2C_FUNC_MCC_MACID_BITMAP, rack: 0, dack: 0,
6676 len: h2c_len);
6677
6678 cond = RTW89_MCC_WAIT_COND(group, H2C_FUNC_MCC_MACID_BITMAP);
6679 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6680}
6681
6682#define H2C_MCC_SYNC_LEN 4
6683int rtw89_fw_h2c_mcc_sync(struct rtw89_dev *rtwdev, u8 group, u8 source,
6684 u8 target, u8 offset)
6685{
6686 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6687 struct sk_buff *skb;
6688 unsigned int cond;
6689
6690 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_MCC_SYNC_LEN);
6691 if (!skb) {
6692 rtw89_err(rtwdev,
6693 "failed to alloc skb for mcc sync\n");
6694 return -ENOMEM;
6695 }
6696
6697 skb_put(skb, H2C_MCC_SYNC_LEN);
6698 RTW89_SET_FWCMD_MCC_SYNC_GROUP(cmd: skb->data, val: group);
6699 RTW89_SET_FWCMD_MCC_SYNC_MACID_SOURCE(cmd: skb->data, val: source);
6700 RTW89_SET_FWCMD_MCC_SYNC_MACID_TARGET(cmd: skb->data, val: target);
6701 RTW89_SET_FWCMD_MCC_SYNC_SYNC_OFFSET(cmd: skb->data, val: offset);
6702
6703 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6704 H2C_CAT_MAC,
6705 H2C_CL_MCC,
6706 func: H2C_FUNC_MCC_SYNC, rack: 0, dack: 0,
6707 H2C_MCC_SYNC_LEN);
6708
6709 cond = RTW89_MCC_WAIT_COND(group, H2C_FUNC_MCC_SYNC);
6710 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6711}
6712
6713#define H2C_MCC_SET_DURATION_LEN 20
6714int rtw89_fw_h2c_mcc_set_duration(struct rtw89_dev *rtwdev,
6715 const struct rtw89_fw_mcc_duration *p)
6716{
6717 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6718 struct sk_buff *skb;
6719 unsigned int cond;
6720
6721 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_MCC_SET_DURATION_LEN);
6722 if (!skb) {
6723 rtw89_err(rtwdev,
6724 "failed to alloc skb for mcc set duration\n");
6725 return -ENOMEM;
6726 }
6727
6728 skb_put(skb, H2C_MCC_SET_DURATION_LEN);
6729 RTW89_SET_FWCMD_MCC_SET_DURATION_GROUP(cmd: skb->data, val: p->group);
6730 RTW89_SET_FWCMD_MCC_SET_DURATION_BTC_IN_GROUP(cmd: skb->data, val: p->btc_in_group);
6731 RTW89_SET_FWCMD_MCC_SET_DURATION_START_MACID(cmd: skb->data, val: p->start_macid);
6732 RTW89_SET_FWCMD_MCC_SET_DURATION_MACID_X(cmd: skb->data, val: p->macid_x);
6733 RTW89_SET_FWCMD_MCC_SET_DURATION_MACID_Y(cmd: skb->data, val: p->macid_y);
6734 RTW89_SET_FWCMD_MCC_SET_DURATION_START_TSF_LOW(cmd: skb->data,
6735 val: p->start_tsf_low);
6736 RTW89_SET_FWCMD_MCC_SET_DURATION_START_TSF_HIGH(cmd: skb->data,
6737 val: p->start_tsf_high);
6738 RTW89_SET_FWCMD_MCC_SET_DURATION_DURATION_X(cmd: skb->data, val: p->duration_x);
6739 RTW89_SET_FWCMD_MCC_SET_DURATION_DURATION_Y(cmd: skb->data, val: p->duration_y);
6740
6741 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6742 H2C_CAT_MAC,
6743 H2C_CL_MCC,
6744 func: H2C_FUNC_MCC_SET_DURATION, rack: 0, dack: 0,
6745 H2C_MCC_SET_DURATION_LEN);
6746
6747 cond = RTW89_MCC_WAIT_COND(p->group, H2C_FUNC_MCC_SET_DURATION);
6748 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6749}
6750
6751static
6752u32 rtw89_fw_h2c_mrc_add_slot(struct rtw89_dev *rtwdev,
6753 const struct rtw89_fw_mrc_add_slot_arg *slot_arg,
6754 struct rtw89_h2c_mrc_add_slot *slot_h2c)
6755{
6756 bool fill_h2c = !!slot_h2c;
6757 unsigned int i;
6758
6759 if (!fill_h2c)
6760 goto calc_len;
6761
6762 slot_h2c->w0 = le32_encode_bits(v: slot_arg->duration,
6763 RTW89_H2C_MRC_ADD_SLOT_W0_DURATION) |
6764 le32_encode_bits(v: slot_arg->courtesy_en,
6765 RTW89_H2C_MRC_ADD_SLOT_W0_COURTESY_EN) |
6766 le32_encode_bits(v: slot_arg->role_num,
6767 RTW89_H2C_MRC_ADD_SLOT_W0_ROLE_NUM);
6768 slot_h2c->w1 = le32_encode_bits(v: slot_arg->courtesy_period,
6769 RTW89_H2C_MRC_ADD_SLOT_W1_COURTESY_PERIOD) |
6770 le32_encode_bits(v: slot_arg->courtesy_target,
6771 RTW89_H2C_MRC_ADD_SLOT_W1_COURTESY_TARGET);
6772
6773 for (i = 0; i < slot_arg->role_num; i++) {
6774 slot_h2c->roles[i].w0 =
6775 le32_encode_bits(v: slot_arg->roles[i].macid,
6776 RTW89_H2C_MRC_ADD_ROLE_W0_MACID) |
6777 le32_encode_bits(v: slot_arg->roles[i].role_type,
6778 RTW89_H2C_MRC_ADD_ROLE_W0_ROLE_TYPE) |
6779 le32_encode_bits(v: slot_arg->roles[i].is_master,
6780 RTW89_H2C_MRC_ADD_ROLE_W0_IS_MASTER) |
6781 le32_encode_bits(v: slot_arg->roles[i].en_tx_null,
6782 RTW89_H2C_MRC_ADD_ROLE_W0_TX_NULL_EN) |
6783 le32_encode_bits(v: false,
6784 RTW89_H2C_MRC_ADD_ROLE_W0_IS_ALT_ROLE) |
6785 le32_encode_bits(v: false,
6786 RTW89_H2C_MRC_ADD_ROLE_W0_ROLE_ALT_EN);
6787 slot_h2c->roles[i].w1 =
6788 le32_encode_bits(v: slot_arg->roles[i].central_ch,
6789 RTW89_H2C_MRC_ADD_ROLE_W1_CENTRAL_CH_SEG) |
6790 le32_encode_bits(v: slot_arg->roles[i].primary_ch,
6791 RTW89_H2C_MRC_ADD_ROLE_W1_PRI_CH) |
6792 le32_encode_bits(v: slot_arg->roles[i].bw,
6793 RTW89_H2C_MRC_ADD_ROLE_W1_BW) |
6794 le32_encode_bits(v: slot_arg->roles[i].band,
6795 RTW89_H2C_MRC_ADD_ROLE_W1_CH_BAND_TYPE) |
6796 le32_encode_bits(v: slot_arg->roles[i].null_early,
6797 RTW89_H2C_MRC_ADD_ROLE_W1_NULL_EARLY) |
6798 le32_encode_bits(v: false,
6799 RTW89_H2C_MRC_ADD_ROLE_W1_RFK_BY_PASS) |
6800 le32_encode_bits(v: true,
6801 RTW89_H2C_MRC_ADD_ROLE_W1_CAN_BTC);
6802 slot_h2c->roles[i].macid_main_bitmap =
6803 cpu_to_le32(slot_arg->roles[i].macid_main_bitmap);
6804 slot_h2c->roles[i].macid_paired_bitmap =
6805 cpu_to_le32(slot_arg->roles[i].macid_paired_bitmap);
6806 }
6807
6808calc_len:
6809 return struct_size(slot_h2c, roles, slot_arg->role_num);
6810}
6811
6812int rtw89_fw_h2c_mrc_add(struct rtw89_dev *rtwdev,
6813 const struct rtw89_fw_mrc_add_arg *arg)
6814{
6815 struct rtw89_h2c_mrc_add *h2c_head;
6816 struct sk_buff *skb;
6817 unsigned int i;
6818 void *tmp;
6819 u32 len;
6820 int ret;
6821
6822 len = sizeof(*h2c_head);
6823 for (i = 0; i < arg->slot_num; i++)
6824 len += rtw89_fw_h2c_mrc_add_slot(rtwdev, slot_arg: &arg->slots[i], NULL);
6825
6826 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
6827 if (!skb) {
6828 rtw89_err(rtwdev, "failed to alloc skb for mrc add\n");
6829 return -ENOMEM;
6830 }
6831
6832 skb_put(skb, len);
6833 tmp = skb->data;
6834
6835 h2c_head = tmp;
6836 h2c_head->w0 = le32_encode_bits(v: arg->sch_idx,
6837 RTW89_H2C_MRC_ADD_W0_SCH_IDX) |
6838 le32_encode_bits(v: arg->sch_type,
6839 RTW89_H2C_MRC_ADD_W0_SCH_TYPE) |
6840 le32_encode_bits(v: arg->slot_num,
6841 RTW89_H2C_MRC_ADD_W0_SLOT_NUM) |
6842 le32_encode_bits(v: arg->btc_in_sch,
6843 RTW89_H2C_MRC_ADD_W0_BTC_IN_SCH);
6844
6845 tmp += sizeof(*h2c_head);
6846 for (i = 0; i < arg->slot_num; i++)
6847 tmp += rtw89_fw_h2c_mrc_add_slot(rtwdev, slot_arg: &arg->slots[i], slot_h2c: tmp);
6848
6849 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6850 H2C_CAT_MAC,
6851 H2C_CL_MRC,
6852 func: H2C_FUNC_ADD_MRC, rack: 0, dack: 0,
6853 len);
6854
6855 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
6856 if (ret) {
6857 rtw89_err(rtwdev, "failed to send h2c\n");
6858 dev_kfree_skb_any(skb);
6859 return -EBUSY;
6860 }
6861
6862 return 0;
6863}
6864
6865int rtw89_fw_h2c_mrc_start(struct rtw89_dev *rtwdev,
6866 const struct rtw89_fw_mrc_start_arg *arg)
6867{
6868 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6869 struct rtw89_h2c_mrc_start *h2c;
6870 u32 len = sizeof(*h2c);
6871 struct sk_buff *skb;
6872 unsigned int cond;
6873
6874 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
6875 if (!skb) {
6876 rtw89_err(rtwdev, "failed to alloc skb for mrc start\n");
6877 return -ENOMEM;
6878 }
6879
6880 skb_put(skb, len);
6881 h2c = (struct rtw89_h2c_mrc_start *)skb->data;
6882
6883 h2c->w0 = le32_encode_bits(v: arg->sch_idx,
6884 RTW89_H2C_MRC_START_W0_SCH_IDX) |
6885 le32_encode_bits(v: arg->old_sch_idx,
6886 RTW89_H2C_MRC_START_W0_OLD_SCH_IDX) |
6887 le32_encode_bits(v: arg->action,
6888 RTW89_H2C_MRC_START_W0_ACTION);
6889
6890 h2c->start_tsf_high = cpu_to_le32(arg->start_tsf >> 32);
6891 h2c->start_tsf_low = cpu_to_le32(arg->start_tsf);
6892
6893 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6894 H2C_CAT_MAC,
6895 H2C_CL_MRC,
6896 func: H2C_FUNC_START_MRC, rack: 0, dack: 0,
6897 len);
6898
6899 cond = RTW89_MRC_WAIT_COND(arg->sch_idx, H2C_FUNC_START_MRC);
6900 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6901}
6902
6903int rtw89_fw_h2c_mrc_del(struct rtw89_dev *rtwdev, u8 sch_idx)
6904{
6905 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6906 struct rtw89_h2c_mrc_del *h2c;
6907 u32 len = sizeof(*h2c);
6908 struct sk_buff *skb;
6909 unsigned int cond;
6910
6911 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
6912 if (!skb) {
6913 rtw89_err(rtwdev, "failed to alloc skb for mrc del\n");
6914 return -ENOMEM;
6915 }
6916
6917 skb_put(skb, len);
6918 h2c = (struct rtw89_h2c_mrc_del *)skb->data;
6919
6920 h2c->w0 = le32_encode_bits(v: sch_idx, RTW89_H2C_MRC_DEL_W0_SCH_IDX);
6921
6922 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6923 H2C_CAT_MAC,
6924 H2C_CL_MRC,
6925 func: H2C_FUNC_DEL_MRC, rack: 0, dack: 0,
6926 len);
6927
6928 cond = RTW89_MRC_WAIT_COND(sch_idx, H2C_FUNC_DEL_MRC);
6929 return rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond);
6930}
6931
6932int rtw89_fw_h2c_mrc_req_tsf(struct rtw89_dev *rtwdev,
6933 const struct rtw89_fw_mrc_req_tsf_arg *arg,
6934 struct rtw89_mac_mrc_tsf_rpt *rpt)
6935{
6936 struct rtw89_wait_info *wait = &rtwdev->mcc.wait;
6937 struct rtw89_h2c_mrc_req_tsf *h2c;
6938 struct rtw89_mac_mrc_tsf_rpt *tmp;
6939 struct sk_buff *skb;
6940 unsigned int i;
6941 u32 len;
6942 int ret;
6943
6944 len = struct_size(h2c, infos, arg->num);
6945 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
6946 if (!skb) {
6947 rtw89_err(rtwdev, "failed to alloc skb for mrc req tsf\n");
6948 return -ENOMEM;
6949 }
6950
6951 skb_put(skb, len);
6952 h2c = (struct rtw89_h2c_mrc_req_tsf *)skb->data;
6953
6954 h2c->req_tsf_num = arg->num;
6955 for (i = 0; i < arg->num; i++)
6956 h2c->infos[i] =
6957 u8_encode_bits(v: arg->infos[i].band,
6958 RTW89_H2C_MRC_REQ_TSF_INFO_BAND) |
6959 u8_encode_bits(v: arg->infos[i].port,
6960 RTW89_H2C_MRC_REQ_TSF_INFO_PORT);
6961
6962 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
6963 H2C_CAT_MAC,
6964 H2C_CL_MRC,
6965 func: H2C_FUNC_MRC_REQ_TSF, rack: 0, dack: 0,
6966 len);
6967
6968 ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, RTW89_MRC_WAIT_COND_REQ_TSF);
6969 if (ret)
6970 return ret;
6971
6972 tmp = (struct rtw89_mac_mrc_tsf_rpt *)wait->data.buf;
6973 *rpt = *tmp;
6974
6975 return 0;
6976}
6977
6978int rtw89_fw_h2c_mrc_upd_bitmap(struct rtw89_dev *rtwdev,
6979 const struct rtw89_fw_mrc_upd_bitmap_arg *arg)
6980{
6981 struct rtw89_h2c_mrc_upd_bitmap *h2c;
6982 u32 len = sizeof(*h2c);
6983 struct sk_buff *skb;
6984 int ret;
6985
6986 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
6987 if (!skb) {
6988 rtw89_err(rtwdev, "failed to alloc skb for mrc upd bitmap\n");
6989 return -ENOMEM;
6990 }
6991
6992 skb_put(skb, len);
6993 h2c = (struct rtw89_h2c_mrc_upd_bitmap *)skb->data;
6994
6995 h2c->w0 = le32_encode_bits(v: arg->sch_idx,
6996 RTW89_H2C_MRC_UPD_BITMAP_W0_SCH_IDX) |
6997 le32_encode_bits(v: arg->action,
6998 RTW89_H2C_MRC_UPD_BITMAP_W0_ACTION) |
6999 le32_encode_bits(v: arg->macid,
7000 RTW89_H2C_MRC_UPD_BITMAP_W0_MACID);
7001 h2c->w1 = le32_encode_bits(v: arg->client_macid,
7002 RTW89_H2C_MRC_UPD_BITMAP_W1_CLIENT_MACID);
7003
7004 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
7005 H2C_CAT_MAC,
7006 H2C_CL_MRC,
7007 func: H2C_FUNC_MRC_UPD_BITMAP, rack: 0, dack: 0,
7008 len);
7009
7010 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
7011 if (ret) {
7012 rtw89_err(rtwdev, "failed to send h2c\n");
7013 dev_kfree_skb_any(skb);
7014 return -EBUSY;
7015 }
7016
7017 return 0;
7018}
7019
7020int rtw89_fw_h2c_mrc_sync(struct rtw89_dev *rtwdev,
7021 const struct rtw89_fw_mrc_sync_arg *arg)
7022{
7023 struct rtw89_h2c_mrc_sync *h2c;
7024 u32 len = sizeof(*h2c);
7025 struct sk_buff *skb;
7026 int ret;
7027
7028 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
7029 if (!skb) {
7030 rtw89_err(rtwdev, "failed to alloc skb for mrc sync\n");
7031 return -ENOMEM;
7032 }
7033
7034 skb_put(skb, len);
7035 h2c = (struct rtw89_h2c_mrc_sync *)skb->data;
7036
7037 h2c->w0 = le32_encode_bits(v: true, RTW89_H2C_MRC_SYNC_W0_SYNC_EN) |
7038 le32_encode_bits(v: arg->src.port,
7039 RTW89_H2C_MRC_SYNC_W0_SRC_PORT) |
7040 le32_encode_bits(v: arg->src.band,
7041 RTW89_H2C_MRC_SYNC_W0_SRC_BAND) |
7042 le32_encode_bits(v: arg->dest.port,
7043 RTW89_H2C_MRC_SYNC_W0_DEST_PORT) |
7044 le32_encode_bits(v: arg->dest.band,
7045 RTW89_H2C_MRC_SYNC_W0_DEST_BAND);
7046 h2c->w1 = le32_encode_bits(v: arg->offset, RTW89_H2C_MRC_SYNC_W1_OFFSET);
7047
7048 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
7049 H2C_CAT_MAC,
7050 H2C_CL_MRC,
7051 func: H2C_FUNC_MRC_SYNC, rack: 0, dack: 0,
7052 len);
7053
7054 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
7055 if (ret) {
7056 rtw89_err(rtwdev, "failed to send h2c\n");
7057 dev_kfree_skb_any(skb);
7058 return -EBUSY;
7059 }
7060
7061 return 0;
7062}
7063
7064int rtw89_fw_h2c_mrc_upd_duration(struct rtw89_dev *rtwdev,
7065 const struct rtw89_fw_mrc_upd_duration_arg *arg)
7066{
7067 struct rtw89_h2c_mrc_upd_duration *h2c;
7068 struct sk_buff *skb;
7069 unsigned int i;
7070 u32 len;
7071 int ret;
7072
7073 len = struct_size(h2c, slots, arg->slot_num);
7074 skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
7075 if (!skb) {
7076 rtw89_err(rtwdev, "failed to alloc skb for mrc upd duration\n");
7077 return -ENOMEM;
7078 }
7079
7080 skb_put(skb, len);
7081 h2c = (struct rtw89_h2c_mrc_upd_duration *)skb->data;
7082
7083 h2c->w0 = le32_encode_bits(v: arg->sch_idx,
7084 RTW89_H2C_MRC_UPD_DURATION_W0_SCH_IDX) |
7085 le32_encode_bits(v: arg->slot_num,
7086 RTW89_H2C_MRC_UPD_DURATION_W0_SLOT_NUM) |
7087 le32_encode_bits(v: false,
7088 RTW89_H2C_MRC_UPD_DURATION_W0_BTC_IN_SCH);
7089
7090 h2c->start_tsf_high = cpu_to_le32(arg->start_tsf >> 32);
7091 h2c->start_tsf_low = cpu_to_le32(arg->start_tsf);
7092
7093 for (i = 0; i < arg->slot_num; i++) {
7094 h2c->slots[i] =
7095 le32_encode_bits(v: arg->slots[i].slot_idx,
7096 RTW89_H2C_MRC_UPD_DURATION_SLOT_SLOT_IDX) |
7097 le32_encode_bits(v: arg->slots[i].duration,
7098 RTW89_H2C_MRC_UPD_DURATION_SLOT_DURATION);
7099 }
7100
7101 rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
7102 H2C_CAT_MAC,
7103 H2C_CL_MRC,
7104 func: H2C_FUNC_MRC_UPD_DURATION, rack: 0, dack: 0,
7105 len);
7106
7107 ret = rtw89_h2c_tx(rtwdev, skb, fwdl: false);
7108 if (ret) {
7109 rtw89_err(rtwdev, "failed to send h2c\n");
7110 dev_kfree_skb_any(skb);
7111 return -EBUSY;
7112 }
7113
7114 return 0;
7115}
7116
7117static bool __fw_txpwr_entry_zero_ext(const void *ext_ptr, u8 ext_len)
7118{
7119 static const u8 zeros[U8_MAX] = {};
7120
7121 return memcmp(p: ext_ptr, q: zeros, size: ext_len) == 0;
7122}
7123
7124#define __fw_txpwr_entry_acceptable(e, cursor, ent_sz) \
7125({ \
7126 u8 __var_sz = sizeof(*(e)); \
7127 bool __accept; \
7128 if (__var_sz >= (ent_sz)) \
7129 __accept = true; \
7130 else \
7131 __accept = __fw_txpwr_entry_zero_ext((cursor) + __var_sz,\
7132 (ent_sz) - __var_sz);\
7133 __accept; \
7134})
7135
7136static bool
7137fw_txpwr_byrate_entry_valid(const struct rtw89_fw_txpwr_byrate_entry *e,
7138 const void *cursor,
7139 const struct rtw89_txpwr_conf *conf)
7140{
7141 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7142 return false;
7143
7144 if (e->band >= RTW89_BAND_NUM || e->bw >= RTW89_BYR_BW_NUM)
7145 return false;
7146
7147 switch (e->rs) {
7148 case RTW89_RS_CCK:
7149 if (e->shf + e->len > RTW89_RATE_CCK_NUM)
7150 return false;
7151 break;
7152 case RTW89_RS_OFDM:
7153 if (e->shf + e->len > RTW89_RATE_OFDM_NUM)
7154 return false;
7155 break;
7156 case RTW89_RS_MCS:
7157 if (e->shf + e->len > __RTW89_RATE_MCS_NUM ||
7158 e->nss >= RTW89_NSS_NUM ||
7159 e->ofdma >= RTW89_OFDMA_NUM)
7160 return false;
7161 break;
7162 case RTW89_RS_HEDCM:
7163 if (e->shf + e->len > RTW89_RATE_HEDCM_NUM ||
7164 e->nss >= RTW89_NSS_HEDCM_NUM ||
7165 e->ofdma >= RTW89_OFDMA_NUM)
7166 return false;
7167 break;
7168 case RTW89_RS_OFFSET:
7169 if (e->shf + e->len > __RTW89_RATE_OFFSET_NUM)
7170 return false;
7171 break;
7172 default:
7173 return false;
7174 }
7175
7176 return true;
7177}
7178
7179static
7180void rtw89_fw_load_txpwr_byrate(struct rtw89_dev *rtwdev,
7181 const struct rtw89_txpwr_table *tbl)
7182{
7183 const struct rtw89_txpwr_conf *conf = tbl->data;
7184 struct rtw89_fw_txpwr_byrate_entry entry = {};
7185 struct rtw89_txpwr_byrate *byr_head;
7186 struct rtw89_rate_desc desc = {};
7187 const void *cursor;
7188 u32 data;
7189 s8 *byr;
7190 int i;
7191
7192 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7193 if (!fw_txpwr_byrate_entry_valid(e: &entry, cursor, conf))
7194 continue;
7195
7196 byr_head = &rtwdev->byr[entry.band][entry.bw];
7197 data = le32_to_cpu(entry.data);
7198 desc.ofdma = entry.ofdma;
7199 desc.nss = entry.nss;
7200 desc.rs = entry.rs;
7201
7202 for (i = 0; i < entry.len; i++, data >>= 8) {
7203 desc.idx = entry.shf + i;
7204 byr = rtw89_phy_raw_byr_seek(rtwdev, head: byr_head, desc: &desc);
7205 *byr = data & 0xff;
7206 }
7207 }
7208}
7209
7210static bool
7211fw_txpwr_lmt_2ghz_entry_valid(const struct rtw89_fw_txpwr_lmt_2ghz_entry *e,
7212 const void *cursor,
7213 const struct rtw89_txpwr_conf *conf)
7214{
7215 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7216 return false;
7217
7218 if (e->bw >= RTW89_2G_BW_NUM)
7219 return false;
7220 if (e->nt >= RTW89_NTX_NUM)
7221 return false;
7222 if (e->rs >= RTW89_RS_LMT_NUM)
7223 return false;
7224 if (e->bf >= RTW89_BF_NUM)
7225 return false;
7226 if (e->regd >= RTW89_REGD_NUM)
7227 return false;
7228 if (e->ch_idx >= RTW89_2G_CH_NUM)
7229 return false;
7230
7231 return true;
7232}
7233
7234static
7235void rtw89_fw_load_txpwr_lmt_2ghz(struct rtw89_txpwr_lmt_2ghz_data *data)
7236{
7237 const struct rtw89_txpwr_conf *conf = &data->conf;
7238 struct rtw89_fw_txpwr_lmt_2ghz_entry entry = {};
7239 const void *cursor;
7240
7241 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7242 if (!fw_txpwr_lmt_2ghz_entry_valid(e: &entry, cursor, conf))
7243 continue;
7244
7245 data->v[entry.bw][entry.nt][entry.rs][entry.bf][entry.regd]
7246 [entry.ch_idx] = entry.v;
7247 }
7248}
7249
7250static bool
7251fw_txpwr_lmt_5ghz_entry_valid(const struct rtw89_fw_txpwr_lmt_5ghz_entry *e,
7252 const void *cursor,
7253 const struct rtw89_txpwr_conf *conf)
7254{
7255 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7256 return false;
7257
7258 if (e->bw >= RTW89_5G_BW_NUM)
7259 return false;
7260 if (e->nt >= RTW89_NTX_NUM)
7261 return false;
7262 if (e->rs >= RTW89_RS_LMT_NUM)
7263 return false;
7264 if (e->bf >= RTW89_BF_NUM)
7265 return false;
7266 if (e->regd >= RTW89_REGD_NUM)
7267 return false;
7268 if (e->ch_idx >= RTW89_5G_CH_NUM)
7269 return false;
7270
7271 return true;
7272}
7273
7274static
7275void rtw89_fw_load_txpwr_lmt_5ghz(struct rtw89_txpwr_lmt_5ghz_data *data)
7276{
7277 const struct rtw89_txpwr_conf *conf = &data->conf;
7278 struct rtw89_fw_txpwr_lmt_5ghz_entry entry = {};
7279 const void *cursor;
7280
7281 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7282 if (!fw_txpwr_lmt_5ghz_entry_valid(e: &entry, cursor, conf))
7283 continue;
7284
7285 data->v[entry.bw][entry.nt][entry.rs][entry.bf][entry.regd]
7286 [entry.ch_idx] = entry.v;
7287 }
7288}
7289
7290static bool
7291fw_txpwr_lmt_6ghz_entry_valid(const struct rtw89_fw_txpwr_lmt_6ghz_entry *e,
7292 const void *cursor,
7293 const struct rtw89_txpwr_conf *conf)
7294{
7295 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7296 return false;
7297
7298 if (e->bw >= RTW89_6G_BW_NUM)
7299 return false;
7300 if (e->nt >= RTW89_NTX_NUM)
7301 return false;
7302 if (e->rs >= RTW89_RS_LMT_NUM)
7303 return false;
7304 if (e->bf >= RTW89_BF_NUM)
7305 return false;
7306 if (e->regd >= RTW89_REGD_NUM)
7307 return false;
7308 if (e->reg_6ghz_power >= NUM_OF_RTW89_REG_6GHZ_POWER)
7309 return false;
7310 if (e->ch_idx >= RTW89_6G_CH_NUM)
7311 return false;
7312
7313 return true;
7314}
7315
7316static
7317void rtw89_fw_load_txpwr_lmt_6ghz(struct rtw89_txpwr_lmt_6ghz_data *data)
7318{
7319 const struct rtw89_txpwr_conf *conf = &data->conf;
7320 struct rtw89_fw_txpwr_lmt_6ghz_entry entry = {};
7321 const void *cursor;
7322
7323 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7324 if (!fw_txpwr_lmt_6ghz_entry_valid(e: &entry, cursor, conf))
7325 continue;
7326
7327 data->v[entry.bw][entry.nt][entry.rs][entry.bf][entry.regd]
7328 [entry.reg_6ghz_power][entry.ch_idx] = entry.v;
7329 }
7330}
7331
7332static bool
7333fw_txpwr_lmt_ru_2ghz_entry_valid(const struct rtw89_fw_txpwr_lmt_ru_2ghz_entry *e,
7334 const void *cursor,
7335 const struct rtw89_txpwr_conf *conf)
7336{
7337 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7338 return false;
7339
7340 if (e->ru >= RTW89_RU_NUM)
7341 return false;
7342 if (e->nt >= RTW89_NTX_NUM)
7343 return false;
7344 if (e->regd >= RTW89_REGD_NUM)
7345 return false;
7346 if (e->ch_idx >= RTW89_2G_CH_NUM)
7347 return false;
7348
7349 return true;
7350}
7351
7352static
7353void rtw89_fw_load_txpwr_lmt_ru_2ghz(struct rtw89_txpwr_lmt_ru_2ghz_data *data)
7354{
7355 const struct rtw89_txpwr_conf *conf = &data->conf;
7356 struct rtw89_fw_txpwr_lmt_ru_2ghz_entry entry = {};
7357 const void *cursor;
7358
7359 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7360 if (!fw_txpwr_lmt_ru_2ghz_entry_valid(e: &entry, cursor, conf))
7361 continue;
7362
7363 data->v[entry.ru][entry.nt][entry.regd][entry.ch_idx] = entry.v;
7364 }
7365}
7366
7367static bool
7368fw_txpwr_lmt_ru_5ghz_entry_valid(const struct rtw89_fw_txpwr_lmt_ru_5ghz_entry *e,
7369 const void *cursor,
7370 const struct rtw89_txpwr_conf *conf)
7371{
7372 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7373 return false;
7374
7375 if (e->ru >= RTW89_RU_NUM)
7376 return false;
7377 if (e->nt >= RTW89_NTX_NUM)
7378 return false;
7379 if (e->regd >= RTW89_REGD_NUM)
7380 return false;
7381 if (e->ch_idx >= RTW89_5G_CH_NUM)
7382 return false;
7383
7384 return true;
7385}
7386
7387static
7388void rtw89_fw_load_txpwr_lmt_ru_5ghz(struct rtw89_txpwr_lmt_ru_5ghz_data *data)
7389{
7390 const struct rtw89_txpwr_conf *conf = &data->conf;
7391 struct rtw89_fw_txpwr_lmt_ru_5ghz_entry entry = {};
7392 const void *cursor;
7393
7394 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7395 if (!fw_txpwr_lmt_ru_5ghz_entry_valid(e: &entry, cursor, conf))
7396 continue;
7397
7398 data->v[entry.ru][entry.nt][entry.regd][entry.ch_idx] = entry.v;
7399 }
7400}
7401
7402static bool
7403fw_txpwr_lmt_ru_6ghz_entry_valid(const struct rtw89_fw_txpwr_lmt_ru_6ghz_entry *e,
7404 const void *cursor,
7405 const struct rtw89_txpwr_conf *conf)
7406{
7407 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7408 return false;
7409
7410 if (e->ru >= RTW89_RU_NUM)
7411 return false;
7412 if (e->nt >= RTW89_NTX_NUM)
7413 return false;
7414 if (e->regd >= RTW89_REGD_NUM)
7415 return false;
7416 if (e->reg_6ghz_power >= NUM_OF_RTW89_REG_6GHZ_POWER)
7417 return false;
7418 if (e->ch_idx >= RTW89_6G_CH_NUM)
7419 return false;
7420
7421 return true;
7422}
7423
7424static
7425void rtw89_fw_load_txpwr_lmt_ru_6ghz(struct rtw89_txpwr_lmt_ru_6ghz_data *data)
7426{
7427 const struct rtw89_txpwr_conf *conf = &data->conf;
7428 struct rtw89_fw_txpwr_lmt_ru_6ghz_entry entry = {};
7429 const void *cursor;
7430
7431 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7432 if (!fw_txpwr_lmt_ru_6ghz_entry_valid(e: &entry, cursor, conf))
7433 continue;
7434
7435 data->v[entry.ru][entry.nt][entry.regd][entry.reg_6ghz_power]
7436 [entry.ch_idx] = entry.v;
7437 }
7438}
7439
7440static bool
7441fw_tx_shape_lmt_entry_valid(const struct rtw89_fw_tx_shape_lmt_entry *e,
7442 const void *cursor,
7443 const struct rtw89_txpwr_conf *conf)
7444{
7445 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7446 return false;
7447
7448 if (e->band >= RTW89_BAND_NUM)
7449 return false;
7450 if (e->tx_shape_rs >= RTW89_RS_TX_SHAPE_NUM)
7451 return false;
7452 if (e->regd >= RTW89_REGD_NUM)
7453 return false;
7454
7455 return true;
7456}
7457
7458static
7459void rtw89_fw_load_tx_shape_lmt(struct rtw89_tx_shape_lmt_data *data)
7460{
7461 const struct rtw89_txpwr_conf *conf = &data->conf;
7462 struct rtw89_fw_tx_shape_lmt_entry entry = {};
7463 const void *cursor;
7464
7465 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7466 if (!fw_tx_shape_lmt_entry_valid(e: &entry, cursor, conf))
7467 continue;
7468
7469 data->v[entry.band][entry.tx_shape_rs][entry.regd] = entry.v;
7470 }
7471}
7472
7473static bool
7474fw_tx_shape_lmt_ru_entry_valid(const struct rtw89_fw_tx_shape_lmt_ru_entry *e,
7475 const void *cursor,
7476 const struct rtw89_txpwr_conf *conf)
7477{
7478 if (!__fw_txpwr_entry_acceptable(e, cursor, conf->ent_sz))
7479 return false;
7480
7481 if (e->band >= RTW89_BAND_NUM)
7482 return false;
7483 if (e->regd >= RTW89_REGD_NUM)
7484 return false;
7485
7486 return true;
7487}
7488
7489static
7490void rtw89_fw_load_tx_shape_lmt_ru(struct rtw89_tx_shape_lmt_ru_data *data)
7491{
7492 const struct rtw89_txpwr_conf *conf = &data->conf;
7493 struct rtw89_fw_tx_shape_lmt_ru_entry entry = {};
7494 const void *cursor;
7495
7496 rtw89_for_each_in_txpwr_conf(entry, cursor, conf) {
7497 if (!fw_tx_shape_lmt_ru_entry_valid(e: &entry, cursor, conf))
7498 continue;
7499
7500 data->v[entry.band][entry.regd] = entry.v;
7501 }
7502}
7503
7504const struct rtw89_rfe_parms *
7505rtw89_load_rfe_data_from_fw(struct rtw89_dev *rtwdev,
7506 const struct rtw89_rfe_parms *init)
7507{
7508 struct rtw89_rfe_data *rfe_data = rtwdev->rfe_data;
7509 struct rtw89_rfe_parms *parms;
7510
7511 if (!rfe_data)
7512 return init;
7513
7514 parms = &rfe_data->rfe_parms;
7515 if (init)
7516 *parms = *init;
7517
7518 if (rtw89_txpwr_conf_valid(&rfe_data->byrate.conf)) {
7519 rfe_data->byrate.tbl.data = &rfe_data->byrate.conf;
7520 rfe_data->byrate.tbl.size = 0; /* don't care here */
7521 rfe_data->byrate.tbl.load = rtw89_fw_load_txpwr_byrate;
7522 parms->byr_tbl = &rfe_data->byrate.tbl;
7523 }
7524
7525 if (rtw89_txpwr_conf_valid(&rfe_data->lmt_2ghz.conf)) {
7526 rtw89_fw_load_txpwr_lmt_2ghz(data: &rfe_data->lmt_2ghz);
7527 parms->rule_2ghz.lmt = &rfe_data->lmt_2ghz.v;
7528 }
7529
7530 if (rtw89_txpwr_conf_valid(&rfe_data->lmt_5ghz.conf)) {
7531 rtw89_fw_load_txpwr_lmt_5ghz(data: &rfe_data->lmt_5ghz);
7532 parms->rule_5ghz.lmt = &rfe_data->lmt_5ghz.v;
7533 }
7534
7535 if (rtw89_txpwr_conf_valid(&rfe_data->lmt_6ghz.conf)) {
7536 rtw89_fw_load_txpwr_lmt_6ghz(data: &rfe_data->lmt_6ghz);
7537 parms->rule_6ghz.lmt = &rfe_data->lmt_6ghz.v;
7538 }
7539
7540 if (rtw89_txpwr_conf_valid(&rfe_data->lmt_ru_2ghz.conf)) {
7541 rtw89_fw_load_txpwr_lmt_ru_2ghz(data: &rfe_data->lmt_ru_2ghz);
7542 parms->rule_2ghz.lmt_ru = &rfe_data->lmt_ru_2ghz.v;
7543 }
7544
7545 if (rtw89_txpwr_conf_valid(&rfe_data->lmt_ru_5ghz.conf)) {
7546 rtw89_fw_load_txpwr_lmt_ru_5ghz(data: &rfe_data->lmt_ru_5ghz);
7547 parms->rule_5ghz.lmt_ru = &rfe_data->lmt_ru_5ghz.v;
7548 }
7549
7550 if (rtw89_txpwr_conf_valid(&rfe_data->lmt_ru_6ghz.conf)) {
7551 rtw89_fw_load_txpwr_lmt_ru_6ghz(data: &rfe_data->lmt_ru_6ghz);
7552 parms->rule_6ghz.lmt_ru = &rfe_data->lmt_ru_6ghz.v;
7553 }
7554
7555 if (rtw89_txpwr_conf_valid(&rfe_data->tx_shape_lmt.conf)) {
7556 rtw89_fw_load_tx_shape_lmt(data: &rfe_data->tx_shape_lmt);
7557 parms->tx_shape.lmt = &rfe_data->tx_shape_lmt.v;
7558 }
7559
7560 if (rtw89_txpwr_conf_valid(&rfe_data->tx_shape_lmt_ru.conf)) {
7561 rtw89_fw_load_tx_shape_lmt_ru(data: &rfe_data->tx_shape_lmt_ru);
7562 parms->tx_shape.lmt_ru = &rfe_data->tx_shape_lmt_ru.v;
7563 }
7564
7565 return parms;
7566}
7567

source code of linux/drivers/net/wireless/realtek/rtw89/fw.c