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 | |
16 | static const u8 mss_signature[] = {0x4D, 0x53, 0x53, 0x4B, 0x50, 0x4F, 0x4F, 0x4C}; |
17 | |
18 | union rtw89_fw_element_arg { |
19 | size_t offset; |
20 | enum rtw89_rf_path rf_path; |
21 | enum rtw89_fw_type fw_type; |
22 | }; |
23 | |
24 | struct 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 | |
32 | static void rtw89_fw_c2h_cmd_handle(struct rtw89_dev *rtwdev, |
33 | struct sk_buff *skb); |
34 | static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, |
35 | struct rtw89_wait_info *wait, unsigned int cond); |
36 | |
37 | static struct sk_buff *rtw89_fw_h2c_alloc_skb(struct rtw89_dev *rtwdev, u32 len, |
38 | bool ) |
39 | { |
40 | struct sk_buff *skb; |
41 | u32 = 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 | |
56 | struct 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 | |
61 | struct 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 | |
66 | int 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 | |
100 | static 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 | |
168 | static 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 | |
212 | static 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 | |
279 | out: |
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 | |
289 | ignore: |
290 | section_info->ignore = true; |
291 | |
292 | return 0; |
293 | } |
294 | |
295 | static 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 | |
323 | static 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 | |
409 | static 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 | |
431 | static |
432 | int 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 | |
467 | found: |
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 | |
473 | static 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 | |
493 | static 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 | |
510 | static 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 | |
527 | static 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 | |
561 | static |
562 | int __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 | |
575 | static |
576 | int __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) \ |
595 | static 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 | |
604 | struct __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 | |
619 | static 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 | |
642 | static 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 | |
659 | static 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 | |
671 | const struct firmware * |
672 | rtw89_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 | |
707 | out: |
708 | return firmware; |
709 | } |
710 | |
711 | int 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 | |
726 | normal_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 | |
740 | static |
741 | int 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 | |
797 | out: |
798 | kfree(objp: tbl); |
799 | return -ENOMEM; |
800 | } |
801 | |
802 | static |
803 | int 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 | |
834 | setup: |
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 | |
845 | static |
846 | int 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 | |
902 | err: |
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 | |
911 | static |
912 | int 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 | |
926 | allocated: |
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 | |
936 | static 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 | |
996 | int 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); |
1044 | next: |
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 | |
1058 | void 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 | |
1082 | static 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 | |
1101 | static 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 | |
1111 | static 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 | |
1141 | static 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; |
1192 | fail: |
1193 | dev_kfree_skb_any(skb); |
1194 | |
1195 | return ret; |
1196 | } |
1197 | |
1198 | static 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 | |
1223 | static 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; |
1273 | fail: |
1274 | dev_kfree_skb_any(skb); |
1275 | |
1276 | return ret; |
1277 | } |
1278 | |
1279 | static enum rtw89_fwdl_check_type |
1280 | rtw89_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 | |
1293 | static 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 | |
1324 | static 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 | |
1341 | dump: |
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 | |
1349 | static 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 | |
1363 | static 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 | |
1397 | int 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 | |
1441 | fwdl_err: |
1442 | rtw89_fw_dl_fail_dump(rtwdev); |
1443 | return ret; |
1444 | } |
1445 | |
1446 | int 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 | |
1457 | static 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 | |
1480 | void 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 | |
1493 | static 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 | |
1502 | static 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 | |
1517 | void 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 | |
1536 | static 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 | |
1551 | static 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 | |
1583 | int 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 | |
1598 | static 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 | |
1637 | void 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 | |
1673 | plain_log: |
1674 | rtw89_info(rtwdev, "C2H log: %.*s" , len, buf); |
1675 | |
1676 | } |
1677 | |
1678 | #define H2C_CAM_LEN 60 |
1679 | int 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; |
1707 | fail: |
1708 | dev_kfree_skb_any(skb); |
1709 | |
1710 | return ret; |
1711 | } |
1712 | |
1713 | #define H2C_DCTL_SEC_CAM_LEN 68 |
1714 | int 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; |
1743 | fail: |
1744 | dev_kfree_skb_any(skb); |
1745 | |
1746 | return ret; |
1747 | } |
1748 | EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1); |
1749 | |
1750 | int 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; |
1782 | fail: |
1783 | dev_kfree_skb_any(skb); |
1784 | |
1785 | return ret; |
1786 | } |
1787 | EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v2); |
1788 | |
1789 | int 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; |
1837 | fail: |
1838 | dev_kfree_skb_any(skb); |
1839 | |
1840 | return ret; |
1841 | } |
1842 | EXPORT_SYMBOL(rtw89_fw_h2c_default_dmac_tbl_v2); |
1843 | |
1844 | int 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 | |
1899 | end: |
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; |
1913 | fail: |
1914 | dev_kfree_skb_any(skb); |
1915 | |
1916 | return ret; |
1917 | } |
1918 | EXPORT_SYMBOL(rtw89_fw_h2c_ba_cam); |
1919 | |
1920 | static 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; |
1955 | fail: |
1956 | dev_kfree_skb_any(skb); |
1957 | |
1958 | return ret; |
1959 | } |
1960 | |
1961 | void 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 | |
1975 | int 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; |
2043 | fail: |
2044 | dev_kfree_skb_any(skb); |
2045 | |
2046 | return ret; |
2047 | } |
2048 | EXPORT_SYMBOL(rtw89_fw_h2c_ba_cam_v1); |
2049 | |
2050 | int 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; |
2083 | fail: |
2084 | dev_kfree_skb_any(skb); |
2085 | |
2086 | return ret; |
2087 | } |
2088 | |
2089 | #define H2C_LOG_CFG_LEN 12 |
2090 | int 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; |
2126 | fail: |
2127 | dev_kfree_skb_any(skb); |
2128 | |
2129 | return ret; |
2130 | } |
2131 | |
2132 | static 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 | |
2176 | err: |
2177 | kfree(objp: info); |
2178 | return -ENOMEM; |
2179 | } |
2180 | |
2181 | void 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 | |
2197 | void 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 |
2207 | int 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; |
2249 | fail: |
2250 | dev_kfree_skb_any(skb); |
2251 | |
2252 | return ret; |
2253 | } |
2254 | |
2255 | #define H2C_LPS_PARM_LEN 8 |
2256 | int 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; |
2293 | fail: |
2294 | dev_kfree_skb_any(skb); |
2295 | |
2296 | return ret; |
2297 | } |
2298 | |
2299 | int 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; |
2337 | fail: |
2338 | dev_kfree_skb_any(skb); |
2339 | |
2340 | return ret; |
2341 | } |
2342 | |
2343 | #define H2C_P2P_ACT_LEN 20 |
2344 | int 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; |
2389 | fail: |
2390 | dev_kfree_skb_any(skb); |
2391 | |
2392 | return ret; |
2393 | } |
2394 | |
2395 | static 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 |
2419 | int 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; |
2461 | fail: |
2462 | dev_kfree_skb_any(skb); |
2463 | |
2464 | return ret; |
2465 | } |
2466 | EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl); |
2467 | |
2468 | int 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; |
2545 | fail: |
2546 | dev_kfree_skb_any(skb); |
2547 | |
2548 | return ret; |
2549 | } |
2550 | EXPORT_SYMBOL(rtw89_fw_h2c_default_cmac_tbl_g7); |
2551 | |
2552 | static 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 | |
2606 | int 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; |
2679 | fail: |
2680 | dev_kfree_skb_any(skb); |
2681 | |
2682 | return ret; |
2683 | } |
2684 | EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl); |
2685 | |
2686 | static 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 | |
2743 | int 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; |
2852 | fail: |
2853 | dev_kfree_skb_any(skb); |
2854 | |
2855 | return ret; |
2856 | } |
2857 | EXPORT_SYMBOL(rtw89_fw_h2c_assoc_cmac_tbl_g7); |
2858 | |
2859 | int 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; |
2918 | fail: |
2919 | dev_kfree_skb_any(skb); |
2920 | |
2921 | return ret; |
2922 | } |
2923 | EXPORT_SYMBOL(rtw89_fw_h2c_ampdu_cmac_tbl_g7); |
2924 | |
2925 | int 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; |
2961 | fail: |
2962 | dev_kfree_skb_any(skb); |
2963 | |
2964 | return ret; |
2965 | } |
2966 | |
2967 | int 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; |
3000 | fail: |
3001 | dev_kfree_skb_any(skb); |
3002 | |
3003 | return ret; |
3004 | } |
3005 | |
3006 | int 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 | } |
3084 | EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon); |
3085 | |
3086 | int 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 | |
3162 | fail: |
3163 | dev_kfree_skb_any(skb); |
3164 | |
3165 | return ret; |
3166 | } |
3167 | EXPORT_SYMBOL(rtw89_fw_h2c_update_beacon_be); |
3168 | |
3169 | #define H2C_ROLE_MAINTAIN_LEN 4 |
3170 | int 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; |
3212 | fail: |
3213 | dev_kfree_skb_any(skb); |
3214 | |
3215 | return ret; |
3216 | } |
3217 | |
3218 | static enum rtw89_fw_sta_type |
3219 | rtw89_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 | |
3235 | by_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 | |
3244 | int 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 | |
3300 | done: |
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; |
3313 | fail: |
3314 | dev_kfree_skb_any(skb); |
3315 | |
3316 | return ret; |
3317 | } |
3318 | |
3319 | int 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; |
3348 | fail: |
3349 | dev_kfree_skb_any(skb); |
3350 | |
3351 | return ret; |
3352 | } |
3353 | |
3354 | int 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; |
3409 | fail: |
3410 | dev_kfree_skb_any(skb); |
3411 | |
3412 | return ret; |
3413 | } |
3414 | |
3415 | #define H2C_EDCA_LEN 12 |
3416 | int 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; |
3446 | fail: |
3447 | dev_kfree_skb_any(skb); |
3448 | |
3449 | return ret; |
3450 | } |
3451 | |
3452 | #define H2C_TSF32_TOGL_LEN 4 |
3453 | int 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; |
3486 | fail: |
3487 | dev_kfree_skb_any(skb); |
3488 | |
3489 | return ret; |
3490 | } |
3491 | |
3492 | #define H2C_OFLD_CFG_LEN 8 |
3493 | int 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; |
3518 | fail: |
3519 | dev_kfree_skb_any(skb); |
3520 | |
3521 | return ret; |
3522 | } |
3523 | |
3524 | int 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; |
3579 | fail: |
3580 | dev_kfree_skb_any(skb); |
3581 | |
3582 | return ret; |
3583 | } |
3584 | |
3585 | int (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 ; |
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; |
3625 | fail: |
3626 | dev_kfree_skb_any(skb); |
3627 | |
3628 | return ret; |
3629 | } |
3630 | |
3631 | int 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; |
3666 | fail: |
3667 | dev_kfree_skb_any(skb); |
3668 | |
3669 | return ret; |
3670 | } |
3671 | |
3672 | int 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 | |
3723 | csi: |
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 | |
3737 | done: |
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; |
3750 | fail: |
3751 | dev_kfree_skb_any(skb); |
3752 | |
3753 | return ret; |
3754 | } |
3755 | |
3756 | int 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; |
3817 | fail: |
3818 | dev_kfree_skb_any(skb); |
3819 | |
3820 | return ret; |
3821 | } |
3822 | |
3823 | int 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; |
3858 | fail: |
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 | |
3869 | int 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; |
3941 | fail: |
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 | |
3950 | int 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; |
4031 | fail: |
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 | |
4040 | int 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; |
4117 | fail: |
4118 | dev_kfree_skb_any(skb); |
4119 | |
4120 | return ret; |
4121 | } |
4122 | |
4123 | #define H2C_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR) |
4124 | int 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; |
4162 | fail: |
4163 | dev_kfree_skb_any(skb); |
4164 | |
4165 | return ret; |
4166 | } |
4167 | |
4168 | int 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; |
4201 | fail: |
4202 | dev_kfree_skb_any(skb); |
4203 | |
4204 | return ret; |
4205 | } |
4206 | |
4207 | #define H2C_LEN_CXDRVINFO_TRX (28 + H2C_LEN_CXDRVHDR) |
4208 | int 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; |
4257 | fail: |
4258 | dev_kfree_skb_any(skb); |
4259 | |
4260 | return ret; |
4261 | } |
4262 | |
4263 | #define H2C_LEN_CXDRVINFO_RFK (4 + H2C_LEN_CXDRVHDR) |
4264 | int 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; |
4302 | fail: |
4303 | dev_kfree_skb_any(skb); |
4304 | |
4305 | return ret; |
4306 | } |
4307 | |
4308 | #define H2C_LEN_PKT_OFLD 4 |
4309 | int 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 | |
4347 | int 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 | |
4397 | int 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 | |
4468 | int 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 | |
4564 | int 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 | |
4626 | static 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 | |
4644 | int 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 | |
4789 | int 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; |
4816 | fail: |
4817 | dev_kfree_skb_any(skb); |
4818 | |
4819 | return ret; |
4820 | } |
4821 | |
4822 | int 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; |
4858 | fail: |
4859 | dev_kfree_skb_any(skb); |
4860 | |
4861 | return ret; |
4862 | } |
4863 | EXPORT_SYMBOL(rtw89_fw_h2c_rf_ntfy_mcc); |
4864 | |
4865 | int 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; |
4932 | fail: |
4933 | dev_kfree_skb_any(skb); |
4934 | |
4935 | return ret; |
4936 | } |
4937 | |
4938 | int 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; |
4980 | fail: |
4981 | dev_kfree_skb_any(skb); |
4982 | |
4983 | return ret; |
4984 | } |
4985 | |
4986 | int 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; |
5015 | fail: |
5016 | dev_kfree_skb_any(skb); |
5017 | |
5018 | return ret; |
5019 | } |
5020 | |
5021 | int 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; |
5058 | fail: |
5059 | dev_kfree_skb_any(skb); |
5060 | |
5061 | return ret; |
5062 | } |
5063 | |
5064 | int 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; |
5102 | fail: |
5103 | dev_kfree_skb_any(skb); |
5104 | |
5105 | return ret; |
5106 | } |
5107 | |
5108 | int 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; |
5138 | fail: |
5139 | dev_kfree_skb_any(skb); |
5140 | |
5141 | return ret; |
5142 | } |
5143 | |
5144 | int 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; |
5181 | fail: |
5182 | dev_kfree_skb_any(skb); |
5183 | |
5184 | return ret; |
5185 | } |
5186 | |
5187 | int 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; |
5212 | fail: |
5213 | dev_kfree_skb_any(skb); |
5214 | |
5215 | return ret; |
5216 | } |
5217 | |
5218 | int 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; |
5237 | fail: |
5238 | dev_kfree_skb_any(skb); |
5239 | |
5240 | return ret; |
5241 | } |
5242 | |
5243 | void 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 | |
5254 | void 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 | |
5267 | static 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 | |
5278 | static 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 | |
5296 | void 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 | |
5306 | enqueue: |
5307 | skb_queue_tail(list: &rtwdev->c2h_queue, newsk: c2h); |
5308 | ieee80211_queue_work(hw: rtwdev->hw, work: &rtwdev->c2h_work); |
5309 | } |
5310 | |
5311 | static 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 | |
5346 | void 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 | |
5361 | static 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 | |
5394 | static 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 | |
5430 | int 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 | |
5449 | recv_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 | |
5460 | void 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 | |
5479 | static 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 | |
5498 | static 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 | |
5518 | static 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 | } |
5565 | out: |
5566 | return ret; |
5567 | } |
5568 | |
5569 | static 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 | |
5595 | static 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 | |
5662 | out: |
5663 | return ret; |
5664 | } |
5665 | |
5666 | static 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 | |
5740 | static 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 | |
5798 | int 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 | |
5866 | out: |
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 | |
5875 | int 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 | |
5925 | out: |
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 | |
5934 | static 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); |
5946 | out: |
5947 | return ret; |
5948 | } |
5949 | |
5950 | void 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 | |
5986 | void 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 | |
6020 | void 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 | |
6032 | static 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 | |
6045 | int 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); |
6078 | out: |
6079 | return ret; |
6080 | } |
6081 | |
6082 | #define H2C_FW_CPU_EXCEPTION_LEN 4 |
6083 | #define H2C_FW_CPU_EXCEPTION_TYPE_DEF 0x5566 |
6084 | int 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 | |
6114 | fail: |
6115 | dev_kfree_skb_any(skb); |
6116 | return ret; |
6117 | } |
6118 | |
6119 | #define H2C_PKT_DROP_LEN 24 |
6120 | int 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 | |
6177 | fail: |
6178 | dev_kfree_skb_any(skb); |
6179 | return ret; |
6180 | } |
6181 | |
6182 | #define H2C_KEEP_ALIVE_LEN 4 |
6183 | int 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 | |
6225 | fail: |
6226 | dev_kfree_skb_any(skb); |
6227 | |
6228 | return ret; |
6229 | } |
6230 | |
6231 | #define H2C_DISCONNECT_DETECT_LEN 8 |
6232 | int 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 | |
6270 | fail: |
6271 | dev_kfree_skb_any(skb); |
6272 | |
6273 | return ret; |
6274 | } |
6275 | |
6276 | #define H2C_WOW_GLOBAL_LEN 8 |
6277 | int 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 | |
6309 | fail: |
6310 | dev_kfree_skb_any(skb); |
6311 | |
6312 | return ret; |
6313 | } |
6314 | |
6315 | #define H2C_WAKEUP_CTRL_LEN 4 |
6316 | int 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 | |
6356 | fail: |
6357 | dev_kfree_skb_any(skb); |
6358 | |
6359 | return ret; |
6360 | } |
6361 | |
6362 | #define H2C_WOW_CAM_UPD_LEN 24 |
6363 | int 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; |
6408 | fail: |
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 | */ |
6419 | static 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 |
6438 | int 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 |
6485 | int 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 |
6521 | int 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 |
6551 | int 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 |
6580 | int 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 |
6607 | int 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 |
6647 | int 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 |
6683 | int 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 |
6714 | int 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 | |
6751 | static |
6752 | u32 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 | |
6808 | calc_len: |
6809 | return struct_size(slot_h2c, roles, slot_arg->role_num); |
6810 | } |
6811 | |
6812 | int 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 | |
6865 | int 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 | |
6903 | int 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 | |
6932 | int 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 | |
6978 | int 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 | |
7020 | int 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 | |
7064 | int 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 | |
7117 | static 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 | |
7136 | static bool |
7137 | fw_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 | |
7179 | static |
7180 | void 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 | |
7210 | static bool |
7211 | fw_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 | |
7234 | static |
7235 | void 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 | |
7250 | static bool |
7251 | fw_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 | |
7274 | static |
7275 | void 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 | |
7290 | static bool |
7291 | fw_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 | |
7316 | static |
7317 | void 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 | |
7332 | static bool |
7333 | fw_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 | |
7352 | static |
7353 | void 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 | |
7367 | static bool |
7368 | fw_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 | |
7387 | static |
7388 | void 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 | |
7402 | static bool |
7403 | fw_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 | |
7424 | static |
7425 | void 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 | |
7440 | static bool |
7441 | fw_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 | |
7458 | static |
7459 | void 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 | |
7473 | static bool |
7474 | fw_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 | |
7489 | static |
7490 | void 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 | |
7504 | const struct rtw89_rfe_parms * |
7505 | rtw89_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 | |