.. | .. |
---|
| 1 | +// SPDX-License-Identifier: ISC |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2005-2011 Atheros Communications Inc. |
---|
3 | 4 | * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. |
---|
4 | | - * Copyright (c) 2018, The Linux Foundation. All rights reserved. |
---|
5 | | - * |
---|
6 | | - * Permission to use, copy, modify, and/or distribute this software for any |
---|
7 | | - * purpose with or without fee is hereby granted, provided that the above |
---|
8 | | - * copyright notice and this permission notice appear in all copies. |
---|
9 | | - * |
---|
10 | | - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
---|
11 | | - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
---|
12 | | - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
---|
13 | | - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
---|
14 | | - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
---|
15 | | - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
---|
16 | | - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
---|
| 5 | + * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. |
---|
17 | 6 | */ |
---|
18 | 7 | |
---|
19 | 8 | #include <linux/module.h> |
---|
20 | 9 | #include <linux/firmware.h> |
---|
21 | 10 | #include <linux/of.h> |
---|
| 11 | +#include <linux/property.h> |
---|
22 | 12 | #include <linux/dmi.h> |
---|
23 | 13 | #include <linux/ctype.h> |
---|
| 14 | +#include <linux/pm_qos.h> |
---|
24 | 15 | #include <asm/byteorder.h> |
---|
25 | 16 | |
---|
26 | 17 | #include "core.h" |
---|
.. | .. |
---|
36 | 27 | #include "coredump.h" |
---|
37 | 28 | |
---|
38 | 29 | unsigned int ath10k_debug_mask; |
---|
| 30 | +EXPORT_SYMBOL(ath10k_debug_mask); |
---|
| 31 | + |
---|
39 | 32 | static unsigned int ath10k_cryptmode_param; |
---|
40 | 33 | static bool uart_print; |
---|
41 | 34 | static bool skip_otp; |
---|
42 | 35 | static bool rawmode; |
---|
| 36 | +static bool fw_diag_log; |
---|
43 | 37 | |
---|
44 | 38 | unsigned long ath10k_coredump_mask = BIT(ATH10K_FW_CRASH_DUMP_REGISTERS) | |
---|
45 | 39 | BIT(ATH10K_FW_CRASH_DUMP_CE_DATA); |
---|
.. | .. |
---|
50 | 44 | module_param(uart_print, bool, 0644); |
---|
51 | 45 | module_param(skip_otp, bool, 0644); |
---|
52 | 46 | module_param(rawmode, bool, 0644); |
---|
| 47 | +module_param(fw_diag_log, bool, 0644); |
---|
53 | 48 | module_param_named(coredump_mask, ath10k_coredump_mask, ulong, 0444); |
---|
54 | 49 | |
---|
55 | 50 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); |
---|
.. | .. |
---|
58 | 53 | MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software"); |
---|
59 | 54 | MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath"); |
---|
60 | 55 | MODULE_PARM_DESC(coredump_mask, "Bitfield of what to include in firmware crash file"); |
---|
| 56 | +MODULE_PARM_DESC(fw_diag_log, "Diag based fw log debugging"); |
---|
61 | 57 | |
---|
62 | 58 | static const struct ath10k_hw_params ath10k_hw_params_list[] = { |
---|
63 | 59 | { |
---|
64 | 60 | .id = QCA988X_HW_2_0_VERSION, |
---|
65 | 61 | .dev_id = QCA988X_2_0_DEVICE_ID, |
---|
| 62 | + .bus = ATH10K_BUS_PCI, |
---|
66 | 63 | .name = "qca988x hw2.0", |
---|
67 | 64 | .patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR, |
---|
68 | 65 | .uart_pin = 7, |
---|
.. | .. |
---|
84 | 81 | .vht160_mcs_rx_highest = 0, |
---|
85 | 82 | .vht160_mcs_tx_highest = 0, |
---|
86 | 83 | .n_cipher_suites = 8, |
---|
87 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
88 | 84 | .ast_skid_limit = 0x10, |
---|
89 | 85 | .num_wds_entries = 0x20, |
---|
90 | 86 | .target_64bit = false, |
---|
.. | .. |
---|
92 | 88 | .shadow_reg_support = false, |
---|
93 | 89 | .rri_on_ddr = false, |
---|
94 | 90 | .hw_filter_reset_required = true, |
---|
| 91 | + .fw_diag_ce_download = false, |
---|
| 92 | + .credit_size_workaround = false, |
---|
| 93 | + .tx_stats_over_pktlog = true, |
---|
95 | 94 | }, |
---|
96 | 95 | { |
---|
97 | 96 | .id = QCA988X_HW_2_0_VERSION, |
---|
.. | .. |
---|
117 | 116 | .vht160_mcs_rx_highest = 0, |
---|
118 | 117 | .vht160_mcs_tx_highest = 0, |
---|
119 | 118 | .n_cipher_suites = 8, |
---|
120 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
121 | 119 | .ast_skid_limit = 0x10, |
---|
122 | 120 | .num_wds_entries = 0x20, |
---|
123 | 121 | .target_64bit = false, |
---|
124 | 122 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
125 | | - .per_ce_irq = false, |
---|
126 | 123 | .shadow_reg_support = false, |
---|
127 | 124 | .rri_on_ddr = false, |
---|
128 | 125 | .hw_filter_reset_required = true, |
---|
| 126 | + .fw_diag_ce_download = false, |
---|
| 127 | + .credit_size_workaround = false, |
---|
| 128 | + .tx_stats_over_pktlog = true, |
---|
129 | 129 | }, |
---|
130 | 130 | { |
---|
131 | 131 | .id = QCA9887_HW_1_0_VERSION, |
---|
132 | 132 | .dev_id = QCA9887_1_0_DEVICE_ID, |
---|
| 133 | + .bus = ATH10K_BUS_PCI, |
---|
133 | 134 | .name = "qca9887 hw1.0", |
---|
134 | 135 | .patch_load_addr = QCA9887_HW_1_0_PATCH_LOAD_ADDR, |
---|
135 | 136 | .uart_pin = 7, |
---|
.. | .. |
---|
151 | 152 | .vht160_mcs_rx_highest = 0, |
---|
152 | 153 | .vht160_mcs_tx_highest = 0, |
---|
153 | 154 | .n_cipher_suites = 8, |
---|
154 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
155 | 155 | .ast_skid_limit = 0x10, |
---|
156 | 156 | .num_wds_entries = 0x20, |
---|
157 | 157 | .target_64bit = false, |
---|
158 | 158 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
159 | | - .per_ce_irq = false, |
---|
160 | 159 | .shadow_reg_support = false, |
---|
161 | 160 | .rri_on_ddr = false, |
---|
162 | 161 | .hw_filter_reset_required = true, |
---|
| 162 | + .fw_diag_ce_download = false, |
---|
| 163 | + .credit_size_workaround = false, |
---|
| 164 | + .tx_stats_over_pktlog = false, |
---|
| 165 | + }, |
---|
| 166 | + { |
---|
| 167 | + .id = QCA6174_HW_3_2_VERSION, |
---|
| 168 | + .dev_id = QCA6174_3_2_DEVICE_ID, |
---|
| 169 | + .bus = ATH10K_BUS_SDIO, |
---|
| 170 | + .name = "qca6174 hw3.2 sdio", |
---|
| 171 | + .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, |
---|
| 172 | + .uart_pin = 19, |
---|
| 173 | + .otp_exe_param = 0, |
---|
| 174 | + .channel_counters_freq_hz = 88000, |
---|
| 175 | + .max_probe_resp_desc_thres = 0, |
---|
| 176 | + .cal_data_len = 0, |
---|
| 177 | + .fw = { |
---|
| 178 | + .dir = QCA6174_HW_3_0_FW_DIR, |
---|
| 179 | + .board = QCA6174_HW_3_0_BOARD_DATA_FILE, |
---|
| 180 | + .board_size = QCA6174_BOARD_DATA_SZ, |
---|
| 181 | + .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ, |
---|
| 182 | + }, |
---|
| 183 | + .hw_ops = &qca6174_sdio_ops, |
---|
| 184 | + .hw_clk = qca6174_clk, |
---|
| 185 | + .target_cpu_freq = 176000000, |
---|
| 186 | + .decap_align_bytes = 4, |
---|
| 187 | + .n_cipher_suites = 8, |
---|
| 188 | + .num_peers = 10, |
---|
| 189 | + .ast_skid_limit = 0x10, |
---|
| 190 | + .num_wds_entries = 0x20, |
---|
| 191 | + .uart_pin_workaround = true, |
---|
| 192 | + .tx_stats_over_pktlog = false, |
---|
| 193 | + .credit_size_workaround = false, |
---|
| 194 | + .bmi_large_size_download = true, |
---|
| 195 | + .supports_peer_stats_info = true, |
---|
163 | 196 | }, |
---|
164 | 197 | { |
---|
165 | 198 | .id = QCA6174_HW_2_1_VERSION, |
---|
166 | 199 | .dev_id = QCA6164_2_1_DEVICE_ID, |
---|
| 200 | + .bus = ATH10K_BUS_PCI, |
---|
167 | 201 | .name = "qca6164 hw2.1", |
---|
168 | 202 | .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, |
---|
169 | 203 | .uart_pin = 6, |
---|
.. | .. |
---|
184 | 218 | .vht160_mcs_rx_highest = 0, |
---|
185 | 219 | .vht160_mcs_tx_highest = 0, |
---|
186 | 220 | .n_cipher_suites = 8, |
---|
187 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
188 | 221 | .ast_skid_limit = 0x10, |
---|
189 | 222 | .num_wds_entries = 0x20, |
---|
190 | 223 | .target_64bit = false, |
---|
191 | 224 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
192 | | - .per_ce_irq = false, |
---|
193 | 225 | .shadow_reg_support = false, |
---|
194 | 226 | .rri_on_ddr = false, |
---|
195 | 227 | .hw_filter_reset_required = true, |
---|
| 228 | + .fw_diag_ce_download = false, |
---|
| 229 | + .credit_size_workaround = false, |
---|
| 230 | + .tx_stats_over_pktlog = false, |
---|
196 | 231 | }, |
---|
197 | 232 | { |
---|
198 | 233 | .id = QCA6174_HW_2_1_VERSION, |
---|
199 | 234 | .dev_id = QCA6174_2_1_DEVICE_ID, |
---|
| 235 | + .bus = ATH10K_BUS_PCI, |
---|
200 | 236 | .name = "qca6174 hw2.1", |
---|
201 | 237 | .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR, |
---|
202 | 238 | .uart_pin = 6, |
---|
.. | .. |
---|
217 | 253 | .vht160_mcs_rx_highest = 0, |
---|
218 | 254 | .vht160_mcs_tx_highest = 0, |
---|
219 | 255 | .n_cipher_suites = 8, |
---|
220 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
221 | 256 | .ast_skid_limit = 0x10, |
---|
222 | 257 | .num_wds_entries = 0x20, |
---|
223 | 258 | .target_64bit = false, |
---|
224 | 259 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
225 | | - .per_ce_irq = false, |
---|
226 | 260 | .shadow_reg_support = false, |
---|
227 | 261 | .rri_on_ddr = false, |
---|
228 | 262 | .hw_filter_reset_required = true, |
---|
| 263 | + .fw_diag_ce_download = false, |
---|
| 264 | + .credit_size_workaround = false, |
---|
| 265 | + .tx_stats_over_pktlog = false, |
---|
229 | 266 | }, |
---|
230 | 267 | { |
---|
231 | 268 | .id = QCA6174_HW_3_0_VERSION, |
---|
232 | 269 | .dev_id = QCA6174_2_1_DEVICE_ID, |
---|
| 270 | + .bus = ATH10K_BUS_PCI, |
---|
233 | 271 | .name = "qca6174 hw3.0", |
---|
234 | 272 | .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, |
---|
235 | 273 | .uart_pin = 6, |
---|
.. | .. |
---|
250 | 288 | .vht160_mcs_rx_highest = 0, |
---|
251 | 289 | .vht160_mcs_tx_highest = 0, |
---|
252 | 290 | .n_cipher_suites = 8, |
---|
253 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
254 | 291 | .ast_skid_limit = 0x10, |
---|
255 | 292 | .num_wds_entries = 0x20, |
---|
256 | 293 | .target_64bit = false, |
---|
257 | 294 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
258 | | - .per_ce_irq = false, |
---|
259 | 295 | .shadow_reg_support = false, |
---|
260 | 296 | .rri_on_ddr = false, |
---|
261 | 297 | .hw_filter_reset_required = true, |
---|
| 298 | + .fw_diag_ce_download = false, |
---|
| 299 | + .credit_size_workaround = false, |
---|
| 300 | + .tx_stats_over_pktlog = false, |
---|
262 | 301 | }, |
---|
263 | 302 | { |
---|
264 | 303 | .id = QCA6174_HW_3_2_VERSION, |
---|
265 | 304 | .dev_id = QCA6174_2_1_DEVICE_ID, |
---|
| 305 | + .bus = ATH10K_BUS_PCI, |
---|
266 | 306 | .name = "qca6174 hw3.2", |
---|
267 | 307 | .patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR, |
---|
268 | 308 | .uart_pin = 6, |
---|
.. | .. |
---|
286 | 326 | .vht160_mcs_rx_highest = 0, |
---|
287 | 327 | .vht160_mcs_tx_highest = 0, |
---|
288 | 328 | .n_cipher_suites = 8, |
---|
289 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
290 | 329 | .ast_skid_limit = 0x10, |
---|
291 | 330 | .num_wds_entries = 0x20, |
---|
292 | 331 | .target_64bit = false, |
---|
293 | 332 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
294 | | - .per_ce_irq = false, |
---|
295 | 333 | .shadow_reg_support = false, |
---|
296 | 334 | .rri_on_ddr = false, |
---|
297 | 335 | .hw_filter_reset_required = true, |
---|
| 336 | + .fw_diag_ce_download = true, |
---|
| 337 | + .credit_size_workaround = false, |
---|
| 338 | + .tx_stats_over_pktlog = false, |
---|
| 339 | + .supports_peer_stats_info = true, |
---|
298 | 340 | }, |
---|
299 | 341 | { |
---|
300 | 342 | .id = QCA99X0_HW_2_0_DEV_VERSION, |
---|
301 | 343 | .dev_id = QCA99X0_2_0_DEVICE_ID, |
---|
| 344 | + .bus = ATH10K_BUS_PCI, |
---|
302 | 345 | .name = "qca99x0 hw2.0", |
---|
303 | 346 | .patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR, |
---|
304 | 347 | .uart_pin = 7, |
---|
.. | .. |
---|
325 | 368 | .vht160_mcs_rx_highest = 0, |
---|
326 | 369 | .vht160_mcs_tx_highest = 0, |
---|
327 | 370 | .n_cipher_suites = 11, |
---|
328 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
329 | 371 | .ast_skid_limit = 0x10, |
---|
330 | 372 | .num_wds_entries = 0x20, |
---|
331 | 373 | .target_64bit = false, |
---|
332 | 374 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
333 | | - .per_ce_irq = false, |
---|
334 | 375 | .shadow_reg_support = false, |
---|
335 | 376 | .rri_on_ddr = false, |
---|
336 | 377 | .hw_filter_reset_required = true, |
---|
| 378 | + .fw_diag_ce_download = false, |
---|
| 379 | + .credit_size_workaround = false, |
---|
| 380 | + .tx_stats_over_pktlog = false, |
---|
337 | 381 | }, |
---|
338 | 382 | { |
---|
339 | 383 | .id = QCA9984_HW_1_0_DEV_VERSION, |
---|
340 | 384 | .dev_id = QCA9984_1_0_DEVICE_ID, |
---|
| 385 | + .bus = ATH10K_BUS_PCI, |
---|
341 | 386 | .name = "qca9984/qca9994 hw1.0", |
---|
342 | 387 | .patch_load_addr = QCA9984_HW_1_0_PATCH_LOAD_ADDR, |
---|
343 | 388 | .uart_pin = 7, |
---|
.. | .. |
---|
354 | 399 | .fw = { |
---|
355 | 400 | .dir = QCA9984_HW_1_0_FW_DIR, |
---|
356 | 401 | .board = QCA9984_HW_1_0_BOARD_DATA_FILE, |
---|
| 402 | + .eboard = QCA9984_HW_1_0_EBOARD_DATA_FILE, |
---|
357 | 403 | .board_size = QCA99X0_BOARD_DATA_SZ, |
---|
358 | 404 | .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ, |
---|
| 405 | + .ext_board_size = QCA99X0_EXT_BOARD_DATA_SZ, |
---|
359 | 406 | }, |
---|
360 | 407 | .sw_decrypt_mcast_mgmt = true, |
---|
361 | 408 | .hw_ops = &qca99x0_ops, |
---|
.. | .. |
---|
369 | 416 | .vht160_mcs_rx_highest = 1560, |
---|
370 | 417 | .vht160_mcs_tx_highest = 1560, |
---|
371 | 418 | .n_cipher_suites = 11, |
---|
372 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
373 | 419 | .ast_skid_limit = 0x10, |
---|
374 | 420 | .num_wds_entries = 0x20, |
---|
375 | 421 | .target_64bit = false, |
---|
376 | 422 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
377 | | - .per_ce_irq = false, |
---|
378 | 423 | .shadow_reg_support = false, |
---|
379 | 424 | .rri_on_ddr = false, |
---|
380 | 425 | .hw_filter_reset_required = true, |
---|
| 426 | + .fw_diag_ce_download = false, |
---|
| 427 | + .credit_size_workaround = false, |
---|
| 428 | + .tx_stats_over_pktlog = false, |
---|
381 | 429 | }, |
---|
382 | 430 | { |
---|
383 | 431 | .id = QCA9888_HW_2_0_DEV_VERSION, |
---|
384 | 432 | .dev_id = QCA9888_2_0_DEVICE_ID, |
---|
| 433 | + .bus = ATH10K_BUS_PCI, |
---|
385 | 434 | .name = "qca9888 hw2.0", |
---|
386 | 435 | .patch_load_addr = QCA9888_HW_2_0_PATCH_LOAD_ADDR, |
---|
387 | 436 | .uart_pin = 7, |
---|
.. | .. |
---|
412 | 461 | .vht160_mcs_rx_highest = 780, |
---|
413 | 462 | .vht160_mcs_tx_highest = 780, |
---|
414 | 463 | .n_cipher_suites = 11, |
---|
415 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
416 | 464 | .ast_skid_limit = 0x10, |
---|
417 | 465 | .num_wds_entries = 0x20, |
---|
418 | 466 | .target_64bit = false, |
---|
419 | 467 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
420 | | - .per_ce_irq = false, |
---|
421 | 468 | .shadow_reg_support = false, |
---|
422 | 469 | .rri_on_ddr = false, |
---|
423 | 470 | .hw_filter_reset_required = true, |
---|
| 471 | + .fw_diag_ce_download = false, |
---|
| 472 | + .credit_size_workaround = false, |
---|
| 473 | + .tx_stats_over_pktlog = false, |
---|
424 | 474 | }, |
---|
425 | 475 | { |
---|
426 | 476 | .id = QCA9377_HW_1_0_DEV_VERSION, |
---|
427 | 477 | .dev_id = QCA9377_1_0_DEVICE_ID, |
---|
| 478 | + .bus = ATH10K_BUS_PCI, |
---|
428 | 479 | .name = "qca9377 hw1.0", |
---|
429 | 480 | .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, |
---|
430 | 481 | .uart_pin = 6, |
---|
.. | .. |
---|
445 | 496 | .vht160_mcs_rx_highest = 0, |
---|
446 | 497 | .vht160_mcs_tx_highest = 0, |
---|
447 | 498 | .n_cipher_suites = 8, |
---|
448 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
449 | 499 | .ast_skid_limit = 0x10, |
---|
450 | 500 | .num_wds_entries = 0x20, |
---|
451 | 501 | .target_64bit = false, |
---|
452 | 502 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
453 | | - .per_ce_irq = false, |
---|
454 | 503 | .shadow_reg_support = false, |
---|
455 | 504 | .rri_on_ddr = false, |
---|
456 | 505 | .hw_filter_reset_required = true, |
---|
| 506 | + .fw_diag_ce_download = false, |
---|
| 507 | + .credit_size_workaround = false, |
---|
| 508 | + .tx_stats_over_pktlog = false, |
---|
457 | 509 | }, |
---|
458 | 510 | { |
---|
459 | 511 | .id = QCA9377_HW_1_1_DEV_VERSION, |
---|
460 | 512 | .dev_id = QCA9377_1_0_DEVICE_ID, |
---|
| 513 | + .bus = ATH10K_BUS_PCI, |
---|
461 | 514 | .name = "qca9377 hw1.1", |
---|
462 | 515 | .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, |
---|
463 | 516 | .uart_pin = 6, |
---|
.. | .. |
---|
480 | 533 | .vht160_mcs_rx_highest = 0, |
---|
481 | 534 | .vht160_mcs_tx_highest = 0, |
---|
482 | 535 | .n_cipher_suites = 8, |
---|
483 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
484 | 536 | .ast_skid_limit = 0x10, |
---|
485 | 537 | .num_wds_entries = 0x20, |
---|
486 | 538 | .target_64bit = false, |
---|
487 | 539 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
488 | | - .per_ce_irq = false, |
---|
489 | 540 | .shadow_reg_support = false, |
---|
490 | 541 | .rri_on_ddr = false, |
---|
491 | 542 | .hw_filter_reset_required = true, |
---|
| 543 | + .fw_diag_ce_download = true, |
---|
| 544 | + .credit_size_workaround = false, |
---|
| 545 | + .tx_stats_over_pktlog = false, |
---|
| 546 | + }, |
---|
| 547 | + { |
---|
| 548 | + .id = QCA9377_HW_1_1_DEV_VERSION, |
---|
| 549 | + .dev_id = QCA9377_1_0_DEVICE_ID, |
---|
| 550 | + .bus = ATH10K_BUS_SDIO, |
---|
| 551 | + .name = "qca9377 hw1.1 sdio", |
---|
| 552 | + .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR, |
---|
| 553 | + .uart_pin = 19, |
---|
| 554 | + .otp_exe_param = 0, |
---|
| 555 | + .channel_counters_freq_hz = 88000, |
---|
| 556 | + .max_probe_resp_desc_thres = 0, |
---|
| 557 | + .cal_data_len = 8124, |
---|
| 558 | + .fw = { |
---|
| 559 | + .dir = QCA9377_HW_1_0_FW_DIR, |
---|
| 560 | + .board = QCA9377_HW_1_0_BOARD_DATA_FILE, |
---|
| 561 | + .board_size = QCA9377_BOARD_DATA_SZ, |
---|
| 562 | + .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ, |
---|
| 563 | + }, |
---|
| 564 | + .hw_ops = &qca6174_ops, |
---|
| 565 | + .hw_clk = qca6174_clk, |
---|
| 566 | + .target_cpu_freq = 176000000, |
---|
| 567 | + .decap_align_bytes = 4, |
---|
| 568 | + .n_cipher_suites = 8, |
---|
| 569 | + .num_peers = TARGET_QCA9377_HL_NUM_PEERS, |
---|
| 570 | + .ast_skid_limit = 0x10, |
---|
| 571 | + .num_wds_entries = 0x20, |
---|
| 572 | + .uart_pin_workaround = true, |
---|
| 573 | + .credit_size_workaround = true, |
---|
492 | 574 | }, |
---|
493 | 575 | { |
---|
494 | 576 | .id = QCA4019_HW_1_0_DEV_VERSION, |
---|
495 | 577 | .dev_id = 0, |
---|
| 578 | + .bus = ATH10K_BUS_AHB, |
---|
496 | 579 | .name = "qca4019 hw1.0", |
---|
497 | 580 | .patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR, |
---|
498 | 581 | .uart_pin = 7, |
---|
.. | .. |
---|
520 | 603 | .vht160_mcs_rx_highest = 0, |
---|
521 | 604 | .vht160_mcs_tx_highest = 0, |
---|
522 | 605 | .n_cipher_suites = 11, |
---|
523 | | - .num_peers = TARGET_TLV_NUM_PEERS, |
---|
524 | 606 | .ast_skid_limit = 0x10, |
---|
525 | 607 | .num_wds_entries = 0x20, |
---|
526 | 608 | .target_64bit = false, |
---|
527 | 609 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, |
---|
528 | | - .per_ce_irq = false, |
---|
529 | 610 | .shadow_reg_support = false, |
---|
530 | 611 | .rri_on_ddr = false, |
---|
531 | 612 | .hw_filter_reset_required = true, |
---|
| 613 | + .fw_diag_ce_download = false, |
---|
| 614 | + .credit_size_workaround = false, |
---|
| 615 | + .tx_stats_over_pktlog = false, |
---|
532 | 616 | }, |
---|
533 | 617 | { |
---|
534 | 618 | .id = WCN3990_HW_1_0_DEV_VERSION, |
---|
535 | 619 | .dev_id = 0, |
---|
| 620 | + .bus = ATH10K_BUS_SNOC, |
---|
536 | 621 | .name = "wcn3990 hw1.0", |
---|
537 | 622 | .continuous_frag_desc = true, |
---|
538 | 623 | .tx_chain_mask = 0x7, |
---|
.. | .. |
---|
544 | 629 | .sw_decrypt_mcast_mgmt = true, |
---|
545 | 630 | .hw_ops = &wcn3990_ops, |
---|
546 | 631 | .decap_align_bytes = 1, |
---|
547 | | - .num_peers = TARGET_HL_10_TLV_NUM_PEERS, |
---|
| 632 | + .num_peers = TARGET_HL_TLV_NUM_PEERS, |
---|
548 | 633 | .n_cipher_suites = 11, |
---|
549 | | - .ast_skid_limit = TARGET_HL_10_TLV_AST_SKID_LIMIT, |
---|
550 | | - .num_wds_entries = TARGET_HL_10_TLV_NUM_WDS_ENTRIES, |
---|
| 634 | + .ast_skid_limit = TARGET_HL_TLV_AST_SKID_LIMIT, |
---|
| 635 | + .num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES, |
---|
551 | 636 | .target_64bit = true, |
---|
552 | 637 | .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, |
---|
553 | | - .per_ce_irq = true, |
---|
554 | 638 | .shadow_reg_support = true, |
---|
555 | 639 | .rri_on_ddr = true, |
---|
556 | 640 | .hw_filter_reset_required = false, |
---|
| 641 | + .fw_diag_ce_download = false, |
---|
| 642 | + .credit_size_workaround = false, |
---|
| 643 | + .tx_stats_over_pktlog = false, |
---|
557 | 644 | }, |
---|
558 | 645 | }; |
---|
559 | 646 | |
---|
.. | .. |
---|
578 | 665 | [ATH10K_FW_FEATURE_NO_PS] = "no-ps", |
---|
579 | 666 | [ATH10K_FW_FEATURE_MGMT_TX_BY_REF] = "mgmt-tx-by-reference", |
---|
580 | 667 | [ATH10K_FW_FEATURE_NON_BMI] = "non-bmi", |
---|
| 668 | + [ATH10K_FW_FEATURE_SINGLE_CHAN_INFO_PER_CHANNEL] = "single-chan-info-per-channel", |
---|
| 669 | + [ATH10K_FW_FEATURE_PEER_FIXED_RATE] = "peer-fixed-rate", |
---|
581 | 670 | }; |
---|
582 | 671 | |
---|
583 | 672 | static unsigned int ath10k_core_get_fw_feature_str(char *buf, |
---|
.. | .. |
---|
622 | 711 | complete(&ar->target_suspend); |
---|
623 | 712 | } |
---|
624 | 713 | |
---|
625 | | -static void ath10k_init_sdio(struct ath10k *ar) |
---|
| 714 | +static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode) |
---|
626 | 715 | { |
---|
| 716 | + bool mtu_workaround = ar->hw_params.credit_size_workaround; |
---|
| 717 | + int ret; |
---|
627 | 718 | u32 param = 0; |
---|
628 | 719 | |
---|
629 | | - ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256); |
---|
630 | | - ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99); |
---|
631 | | - ath10k_bmi_read32(ar, hi_acs_flags, ¶m); |
---|
| 720 | + ret = ath10k_bmi_write32(ar, hi_mbox_io_block_sz, 256); |
---|
| 721 | + if (ret) |
---|
| 722 | + return ret; |
---|
632 | 723 | |
---|
633 | | - param |= (HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET | |
---|
634 | | - HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET | |
---|
635 | | - HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE); |
---|
| 724 | + ret = ath10k_bmi_write32(ar, hi_mbox_isr_yield_limit, 99); |
---|
| 725 | + if (ret) |
---|
| 726 | + return ret; |
---|
636 | 727 | |
---|
637 | | - ath10k_bmi_write32(ar, hi_acs_flags, param); |
---|
| 728 | + ret = ath10k_bmi_read32(ar, hi_acs_flags, ¶m); |
---|
| 729 | + if (ret) |
---|
| 730 | + return ret; |
---|
| 731 | + |
---|
| 732 | + param |= HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_SET; |
---|
| 733 | + |
---|
| 734 | + if (mode == ATH10K_FIRMWARE_MODE_NORMAL && !mtu_workaround) |
---|
| 735 | + param |= HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; |
---|
| 736 | + else |
---|
| 737 | + param &= ~HI_ACS_FLAGS_ALT_DATA_CREDIT_SIZE; |
---|
| 738 | + |
---|
| 739 | + if (mode == ATH10K_FIRMWARE_MODE_UTF) |
---|
| 740 | + param &= ~HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET; |
---|
| 741 | + else |
---|
| 742 | + param |= HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_SET; |
---|
| 743 | + |
---|
| 744 | + ret = ath10k_bmi_write32(ar, hi_acs_flags, param); |
---|
| 745 | + if (ret) |
---|
| 746 | + return ret; |
---|
| 747 | + |
---|
| 748 | + ret = ath10k_bmi_read32(ar, hi_option_flag2, ¶m); |
---|
| 749 | + if (ret) |
---|
| 750 | + return ret; |
---|
| 751 | + |
---|
| 752 | + param |= HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_HOST; |
---|
| 753 | + |
---|
| 754 | + ret = ath10k_bmi_write32(ar, hi_option_flag2, param); |
---|
| 755 | + if (ret) |
---|
| 756 | + return ret; |
---|
| 757 | + |
---|
| 758 | + return 0; |
---|
638 | 759 | } |
---|
639 | 760 | |
---|
640 | 761 | static int ath10k_init_configure_target(struct ath10k *ar) |
---|
.. | .. |
---|
777 | 898 | return 0; |
---|
778 | 899 | } |
---|
779 | 900 | |
---|
| 901 | +static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) |
---|
| 902 | +{ |
---|
| 903 | + u32 result, address; |
---|
| 904 | + u8 board_id, chip_id; |
---|
| 905 | + bool ext_bid_support; |
---|
| 906 | + int ret, bmi_board_id_param; |
---|
| 907 | + |
---|
| 908 | + address = ar->hw_params.patch_load_addr; |
---|
| 909 | + |
---|
| 910 | + if (!ar->normal_mode_fw.fw_file.otp_data || |
---|
| 911 | + !ar->normal_mode_fw.fw_file.otp_len) { |
---|
| 912 | + ath10k_warn(ar, |
---|
| 913 | + "failed to retrieve board id because of invalid otp\n"); |
---|
| 914 | + return -ENODATA; |
---|
| 915 | + } |
---|
| 916 | + |
---|
| 917 | + if (ar->id.bmi_ids_valid) { |
---|
| 918 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 919 | + "boot already acquired valid otp board id,skip download, board_id %d chip_id %d\n", |
---|
| 920 | + ar->id.bmi_board_id, ar->id.bmi_chip_id); |
---|
| 921 | + goto skip_otp_download; |
---|
| 922 | + } |
---|
| 923 | + |
---|
| 924 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 925 | + "boot upload otp to 0x%x len %zd for board id\n", |
---|
| 926 | + address, ar->normal_mode_fw.fw_file.otp_len); |
---|
| 927 | + |
---|
| 928 | + ret = ath10k_bmi_fast_download(ar, address, |
---|
| 929 | + ar->normal_mode_fw.fw_file.otp_data, |
---|
| 930 | + ar->normal_mode_fw.fw_file.otp_len); |
---|
| 931 | + if (ret) { |
---|
| 932 | + ath10k_err(ar, "could not write otp for board id check: %d\n", |
---|
| 933 | + ret); |
---|
| 934 | + return ret; |
---|
| 935 | + } |
---|
| 936 | + |
---|
| 937 | + if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || |
---|
| 938 | + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) |
---|
| 939 | + bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID; |
---|
| 940 | + else |
---|
| 941 | + bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID; |
---|
| 942 | + |
---|
| 943 | + ret = ath10k_bmi_execute(ar, address, bmi_board_id_param, &result); |
---|
| 944 | + if (ret) { |
---|
| 945 | + ath10k_err(ar, "could not execute otp for board id check: %d\n", |
---|
| 946 | + ret); |
---|
| 947 | + return ret; |
---|
| 948 | + } |
---|
| 949 | + |
---|
| 950 | + board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP); |
---|
| 951 | + chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP); |
---|
| 952 | + ext_bid_support = (result & ATH10K_BMI_EXT_BOARD_ID_SUPPORT); |
---|
| 953 | + |
---|
| 954 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 955 | + "boot get otp board id result 0x%08x board_id %d chip_id %d ext_bid_support %d\n", |
---|
| 956 | + result, board_id, chip_id, ext_bid_support); |
---|
| 957 | + |
---|
| 958 | + ar->id.ext_bid_supported = ext_bid_support; |
---|
| 959 | + |
---|
| 960 | + if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 || |
---|
| 961 | + (board_id == 0)) { |
---|
| 962 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 963 | + "board id does not exist in otp, ignore it\n"); |
---|
| 964 | + return -EOPNOTSUPP; |
---|
| 965 | + } |
---|
| 966 | + |
---|
| 967 | + ar->id.bmi_ids_valid = true; |
---|
| 968 | + ar->id.bmi_board_id = board_id; |
---|
| 969 | + ar->id.bmi_chip_id = chip_id; |
---|
| 970 | + |
---|
| 971 | +skip_otp_download: |
---|
| 972 | + |
---|
| 973 | + return 0; |
---|
| 974 | +} |
---|
| 975 | + |
---|
| 976 | +static void ath10k_core_check_bdfext(const struct dmi_header *hdr, void *data) |
---|
| 977 | +{ |
---|
| 978 | + struct ath10k *ar = data; |
---|
| 979 | + const char *bdf_ext; |
---|
| 980 | + const char *magic = ATH10K_SMBIOS_BDF_EXT_MAGIC; |
---|
| 981 | + u8 bdf_enabled; |
---|
| 982 | + int i; |
---|
| 983 | + |
---|
| 984 | + if (hdr->type != ATH10K_SMBIOS_BDF_EXT_TYPE) |
---|
| 985 | + return; |
---|
| 986 | + |
---|
| 987 | + if (hdr->length != ATH10K_SMBIOS_BDF_EXT_LENGTH) { |
---|
| 988 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 989 | + "wrong smbios bdf ext type length (%d).\n", |
---|
| 990 | + hdr->length); |
---|
| 991 | + return; |
---|
| 992 | + } |
---|
| 993 | + |
---|
| 994 | + bdf_enabled = *((u8 *)hdr + ATH10K_SMBIOS_BDF_EXT_OFFSET); |
---|
| 995 | + if (!bdf_enabled) { |
---|
| 996 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not found.\n"); |
---|
| 997 | + return; |
---|
| 998 | + } |
---|
| 999 | + |
---|
| 1000 | + /* Only one string exists (per spec) */ |
---|
| 1001 | + bdf_ext = (char *)hdr + hdr->length; |
---|
| 1002 | + |
---|
| 1003 | + if (memcmp(bdf_ext, magic, strlen(magic)) != 0) { |
---|
| 1004 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1005 | + "bdf variant magic does not match.\n"); |
---|
| 1006 | + return; |
---|
| 1007 | + } |
---|
| 1008 | + |
---|
| 1009 | + for (i = 0; i < strlen(bdf_ext); i++) { |
---|
| 1010 | + if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) { |
---|
| 1011 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1012 | + "bdf variant name contains non ascii chars.\n"); |
---|
| 1013 | + return; |
---|
| 1014 | + } |
---|
| 1015 | + } |
---|
| 1016 | + |
---|
| 1017 | + /* Copy extension name without magic suffix */ |
---|
| 1018 | + if (strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic), |
---|
| 1019 | + sizeof(ar->id.bdf_ext)) < 0) { |
---|
| 1020 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1021 | + "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", |
---|
| 1022 | + bdf_ext); |
---|
| 1023 | + return; |
---|
| 1024 | + } |
---|
| 1025 | + |
---|
| 1026 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1027 | + "found and validated bdf variant smbios_type 0x%x bdf %s\n", |
---|
| 1028 | + ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext); |
---|
| 1029 | +} |
---|
| 1030 | + |
---|
| 1031 | +static int ath10k_core_check_smbios(struct ath10k *ar) |
---|
| 1032 | +{ |
---|
| 1033 | + ar->id.bdf_ext[0] = '\0'; |
---|
| 1034 | + dmi_walk(ath10k_core_check_bdfext, ar); |
---|
| 1035 | + |
---|
| 1036 | + if (ar->id.bdf_ext[0] == '\0') |
---|
| 1037 | + return -ENODATA; |
---|
| 1038 | + |
---|
| 1039 | + return 0; |
---|
| 1040 | +} |
---|
| 1041 | + |
---|
| 1042 | +int ath10k_core_check_dt(struct ath10k *ar) |
---|
| 1043 | +{ |
---|
| 1044 | + struct device_node *node; |
---|
| 1045 | + const char *variant = NULL; |
---|
| 1046 | + |
---|
| 1047 | + node = ar->dev->of_node; |
---|
| 1048 | + if (!node) |
---|
| 1049 | + return -ENOENT; |
---|
| 1050 | + |
---|
| 1051 | + of_property_read_string(node, "qcom,ath10k-calibration-variant", |
---|
| 1052 | + &variant); |
---|
| 1053 | + if (!variant) |
---|
| 1054 | + return -ENODATA; |
---|
| 1055 | + |
---|
| 1056 | + if (strscpy(ar->id.bdf_ext, variant, sizeof(ar->id.bdf_ext)) < 0) |
---|
| 1057 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1058 | + "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", |
---|
| 1059 | + variant); |
---|
| 1060 | + |
---|
| 1061 | + return 0; |
---|
| 1062 | +} |
---|
| 1063 | +EXPORT_SYMBOL(ath10k_core_check_dt); |
---|
| 1064 | + |
---|
| 1065 | +static int ath10k_download_fw(struct ath10k *ar) |
---|
| 1066 | +{ |
---|
| 1067 | + u32 address, data_len; |
---|
| 1068 | + const void *data; |
---|
| 1069 | + int ret; |
---|
| 1070 | + struct pm_qos_request latency_qos; |
---|
| 1071 | + |
---|
| 1072 | + address = ar->hw_params.patch_load_addr; |
---|
| 1073 | + |
---|
| 1074 | + data = ar->running_fw->fw_file.firmware_data; |
---|
| 1075 | + data_len = ar->running_fw->fw_file.firmware_len; |
---|
| 1076 | + |
---|
| 1077 | + ret = ath10k_swap_code_seg_configure(ar, &ar->running_fw->fw_file); |
---|
| 1078 | + if (ret) { |
---|
| 1079 | + ath10k_err(ar, "failed to configure fw code swap: %d\n", |
---|
| 1080 | + ret); |
---|
| 1081 | + return ret; |
---|
| 1082 | + } |
---|
| 1083 | + |
---|
| 1084 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1085 | + "boot uploading firmware image %pK len %d\n", |
---|
| 1086 | + data, data_len); |
---|
| 1087 | + |
---|
| 1088 | + /* Check if device supports to download firmware via |
---|
| 1089 | + * diag copy engine. Downloading firmware via diag CE |
---|
| 1090 | + * greatly reduces the time to download firmware. |
---|
| 1091 | + */ |
---|
| 1092 | + if (ar->hw_params.fw_diag_ce_download) { |
---|
| 1093 | + ret = ath10k_hw_diag_fast_download(ar, address, |
---|
| 1094 | + data, data_len); |
---|
| 1095 | + if (ret == 0) |
---|
| 1096 | + /* firmware upload via diag ce was successful */ |
---|
| 1097 | + return 0; |
---|
| 1098 | + |
---|
| 1099 | + ath10k_warn(ar, |
---|
| 1100 | + "failed to upload firmware via diag ce, trying BMI: %d", |
---|
| 1101 | + ret); |
---|
| 1102 | + } |
---|
| 1103 | + |
---|
| 1104 | + memset(&latency_qos, 0, sizeof(latency_qos)); |
---|
| 1105 | + cpu_latency_qos_add_request(&latency_qos, 0); |
---|
| 1106 | + |
---|
| 1107 | + ret = ath10k_bmi_fast_download(ar, address, data, data_len); |
---|
| 1108 | + |
---|
| 1109 | + cpu_latency_qos_remove_request(&latency_qos); |
---|
| 1110 | + |
---|
| 1111 | + return ret; |
---|
| 1112 | +} |
---|
| 1113 | + |
---|
| 1114 | +void ath10k_core_free_board_files(struct ath10k *ar) |
---|
| 1115 | +{ |
---|
| 1116 | + if (!IS_ERR(ar->normal_mode_fw.board)) |
---|
| 1117 | + release_firmware(ar->normal_mode_fw.board); |
---|
| 1118 | + |
---|
| 1119 | + if (!IS_ERR(ar->normal_mode_fw.ext_board)) |
---|
| 1120 | + release_firmware(ar->normal_mode_fw.ext_board); |
---|
| 1121 | + |
---|
| 1122 | + ar->normal_mode_fw.board = NULL; |
---|
| 1123 | + ar->normal_mode_fw.board_data = NULL; |
---|
| 1124 | + ar->normal_mode_fw.board_len = 0; |
---|
| 1125 | + ar->normal_mode_fw.ext_board = NULL; |
---|
| 1126 | + ar->normal_mode_fw.ext_board_data = NULL; |
---|
| 1127 | + ar->normal_mode_fw.ext_board_len = 0; |
---|
| 1128 | +} |
---|
| 1129 | +EXPORT_SYMBOL(ath10k_core_free_board_files); |
---|
| 1130 | + |
---|
| 1131 | +static void ath10k_core_free_firmware_files(struct ath10k *ar) |
---|
| 1132 | +{ |
---|
| 1133 | + if (!IS_ERR(ar->normal_mode_fw.fw_file.firmware)) |
---|
| 1134 | + release_firmware(ar->normal_mode_fw.fw_file.firmware); |
---|
| 1135 | + |
---|
| 1136 | + if (!IS_ERR(ar->cal_file)) |
---|
| 1137 | + release_firmware(ar->cal_file); |
---|
| 1138 | + |
---|
| 1139 | + if (!IS_ERR(ar->pre_cal_file)) |
---|
| 1140 | + release_firmware(ar->pre_cal_file); |
---|
| 1141 | + |
---|
| 1142 | + ath10k_swap_code_seg_release(ar, &ar->normal_mode_fw.fw_file); |
---|
| 1143 | + |
---|
| 1144 | + ar->normal_mode_fw.fw_file.otp_data = NULL; |
---|
| 1145 | + ar->normal_mode_fw.fw_file.otp_len = 0; |
---|
| 1146 | + |
---|
| 1147 | + ar->normal_mode_fw.fw_file.firmware = NULL; |
---|
| 1148 | + ar->normal_mode_fw.fw_file.firmware_data = NULL; |
---|
| 1149 | + ar->normal_mode_fw.fw_file.firmware_len = 0; |
---|
| 1150 | + |
---|
| 1151 | + ar->cal_file = NULL; |
---|
| 1152 | + ar->pre_cal_file = NULL; |
---|
| 1153 | +} |
---|
| 1154 | + |
---|
| 1155 | +static int ath10k_fetch_cal_file(struct ath10k *ar) |
---|
| 1156 | +{ |
---|
| 1157 | + char filename[100]; |
---|
| 1158 | + |
---|
| 1159 | + /* pre-cal-<bus>-<id>.bin */ |
---|
| 1160 | + scnprintf(filename, sizeof(filename), "pre-cal-%s-%s.bin", |
---|
| 1161 | + ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); |
---|
| 1162 | + |
---|
| 1163 | + ar->pre_cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); |
---|
| 1164 | + if (!IS_ERR(ar->pre_cal_file)) |
---|
| 1165 | + goto success; |
---|
| 1166 | + |
---|
| 1167 | + /* cal-<bus>-<id>.bin */ |
---|
| 1168 | + scnprintf(filename, sizeof(filename), "cal-%s-%s.bin", |
---|
| 1169 | + ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); |
---|
| 1170 | + |
---|
| 1171 | + ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); |
---|
| 1172 | + if (IS_ERR(ar->cal_file)) |
---|
| 1173 | + /* calibration file is optional, don't print any warnings */ |
---|
| 1174 | + return PTR_ERR(ar->cal_file); |
---|
| 1175 | +success: |
---|
| 1176 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n", |
---|
| 1177 | + ATH10K_FW_DIR, filename); |
---|
| 1178 | + |
---|
| 1179 | + return 0; |
---|
| 1180 | +} |
---|
| 1181 | + |
---|
| 1182 | +static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar, int bd_ie_type) |
---|
| 1183 | +{ |
---|
| 1184 | + const struct firmware *fw; |
---|
| 1185 | + |
---|
| 1186 | + if (bd_ie_type == ATH10K_BD_IE_BOARD) { |
---|
| 1187 | + if (!ar->hw_params.fw.board) { |
---|
| 1188 | + ath10k_err(ar, "failed to find board file fw entry\n"); |
---|
| 1189 | + return -EINVAL; |
---|
| 1190 | + } |
---|
| 1191 | + |
---|
| 1192 | + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, |
---|
| 1193 | + ar->hw_params.fw.dir, |
---|
| 1194 | + ar->hw_params.fw.board); |
---|
| 1195 | + if (IS_ERR(ar->normal_mode_fw.board)) |
---|
| 1196 | + return PTR_ERR(ar->normal_mode_fw.board); |
---|
| 1197 | + |
---|
| 1198 | + ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data; |
---|
| 1199 | + ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size; |
---|
| 1200 | + } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) { |
---|
| 1201 | + if (!ar->hw_params.fw.eboard) { |
---|
| 1202 | + ath10k_err(ar, "failed to find eboard file fw entry\n"); |
---|
| 1203 | + return -EINVAL; |
---|
| 1204 | + } |
---|
| 1205 | + |
---|
| 1206 | + fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, |
---|
| 1207 | + ar->hw_params.fw.eboard); |
---|
| 1208 | + ar->normal_mode_fw.ext_board = fw; |
---|
| 1209 | + if (IS_ERR(ar->normal_mode_fw.ext_board)) |
---|
| 1210 | + return PTR_ERR(ar->normal_mode_fw.ext_board); |
---|
| 1211 | + |
---|
| 1212 | + ar->normal_mode_fw.ext_board_data = ar->normal_mode_fw.ext_board->data; |
---|
| 1213 | + ar->normal_mode_fw.ext_board_len = ar->normal_mode_fw.ext_board->size; |
---|
| 1214 | + } |
---|
| 1215 | + |
---|
| 1216 | + return 0; |
---|
| 1217 | +} |
---|
| 1218 | + |
---|
| 1219 | +static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, |
---|
| 1220 | + const void *buf, size_t buf_len, |
---|
| 1221 | + const char *boardname, |
---|
| 1222 | + int bd_ie_type) |
---|
| 1223 | +{ |
---|
| 1224 | + const struct ath10k_fw_ie *hdr; |
---|
| 1225 | + bool name_match_found; |
---|
| 1226 | + int ret, board_ie_id; |
---|
| 1227 | + size_t board_ie_len; |
---|
| 1228 | + const void *board_ie_data; |
---|
| 1229 | + |
---|
| 1230 | + name_match_found = false; |
---|
| 1231 | + |
---|
| 1232 | + /* go through ATH10K_BD_IE_BOARD_ elements */ |
---|
| 1233 | + while (buf_len > sizeof(struct ath10k_fw_ie)) { |
---|
| 1234 | + hdr = buf; |
---|
| 1235 | + board_ie_id = le32_to_cpu(hdr->id); |
---|
| 1236 | + board_ie_len = le32_to_cpu(hdr->len); |
---|
| 1237 | + board_ie_data = hdr->data; |
---|
| 1238 | + |
---|
| 1239 | + buf_len -= sizeof(*hdr); |
---|
| 1240 | + buf += sizeof(*hdr); |
---|
| 1241 | + |
---|
| 1242 | + if (buf_len < ALIGN(board_ie_len, 4)) { |
---|
| 1243 | + ath10k_err(ar, "invalid ATH10K_BD_IE_BOARD length: %zu < %zu\n", |
---|
| 1244 | + buf_len, ALIGN(board_ie_len, 4)); |
---|
| 1245 | + ret = -EINVAL; |
---|
| 1246 | + goto out; |
---|
| 1247 | + } |
---|
| 1248 | + |
---|
| 1249 | + switch (board_ie_id) { |
---|
| 1250 | + case ATH10K_BD_IE_BOARD_NAME: |
---|
| 1251 | + ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "board name", "", |
---|
| 1252 | + board_ie_data, board_ie_len); |
---|
| 1253 | + |
---|
| 1254 | + if (board_ie_len != strlen(boardname)) |
---|
| 1255 | + break; |
---|
| 1256 | + |
---|
| 1257 | + ret = memcmp(board_ie_data, boardname, strlen(boardname)); |
---|
| 1258 | + if (ret) |
---|
| 1259 | + break; |
---|
| 1260 | + |
---|
| 1261 | + name_match_found = true; |
---|
| 1262 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1263 | + "boot found match for name '%s'", |
---|
| 1264 | + boardname); |
---|
| 1265 | + break; |
---|
| 1266 | + case ATH10K_BD_IE_BOARD_DATA: |
---|
| 1267 | + if (!name_match_found) |
---|
| 1268 | + /* no match found */ |
---|
| 1269 | + break; |
---|
| 1270 | + |
---|
| 1271 | + if (bd_ie_type == ATH10K_BD_IE_BOARD) { |
---|
| 1272 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1273 | + "boot found board data for '%s'", |
---|
| 1274 | + boardname); |
---|
| 1275 | + |
---|
| 1276 | + ar->normal_mode_fw.board_data = board_ie_data; |
---|
| 1277 | + ar->normal_mode_fw.board_len = board_ie_len; |
---|
| 1278 | + } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) { |
---|
| 1279 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1280 | + "boot found eboard data for '%s'", |
---|
| 1281 | + boardname); |
---|
| 1282 | + |
---|
| 1283 | + ar->normal_mode_fw.ext_board_data = board_ie_data; |
---|
| 1284 | + ar->normal_mode_fw.ext_board_len = board_ie_len; |
---|
| 1285 | + } |
---|
| 1286 | + |
---|
| 1287 | + ret = 0; |
---|
| 1288 | + goto out; |
---|
| 1289 | + default: |
---|
| 1290 | + ath10k_warn(ar, "unknown ATH10K_BD_IE_BOARD found: %d\n", |
---|
| 1291 | + board_ie_id); |
---|
| 1292 | + break; |
---|
| 1293 | + } |
---|
| 1294 | + |
---|
| 1295 | + /* jump over the padding */ |
---|
| 1296 | + board_ie_len = ALIGN(board_ie_len, 4); |
---|
| 1297 | + |
---|
| 1298 | + buf_len -= board_ie_len; |
---|
| 1299 | + buf += board_ie_len; |
---|
| 1300 | + } |
---|
| 1301 | + |
---|
| 1302 | + /* no match found */ |
---|
| 1303 | + ret = -ENOENT; |
---|
| 1304 | + |
---|
| 1305 | +out: |
---|
| 1306 | + return ret; |
---|
| 1307 | +} |
---|
| 1308 | + |
---|
| 1309 | +static int ath10k_core_search_bd(struct ath10k *ar, |
---|
| 1310 | + const char *boardname, |
---|
| 1311 | + const u8 *data, |
---|
| 1312 | + size_t len) |
---|
| 1313 | +{ |
---|
| 1314 | + size_t ie_len; |
---|
| 1315 | + struct ath10k_fw_ie *hdr; |
---|
| 1316 | + int ret = -ENOENT, ie_id; |
---|
| 1317 | + |
---|
| 1318 | + while (len > sizeof(struct ath10k_fw_ie)) { |
---|
| 1319 | + hdr = (struct ath10k_fw_ie *)data; |
---|
| 1320 | + ie_id = le32_to_cpu(hdr->id); |
---|
| 1321 | + ie_len = le32_to_cpu(hdr->len); |
---|
| 1322 | + |
---|
| 1323 | + len -= sizeof(*hdr); |
---|
| 1324 | + data = hdr->data; |
---|
| 1325 | + |
---|
| 1326 | + if (len < ALIGN(ie_len, 4)) { |
---|
| 1327 | + ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", |
---|
| 1328 | + ie_id, ie_len, len); |
---|
| 1329 | + return -EINVAL; |
---|
| 1330 | + } |
---|
| 1331 | + |
---|
| 1332 | + switch (ie_id) { |
---|
| 1333 | + case ATH10K_BD_IE_BOARD: |
---|
| 1334 | + ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, |
---|
| 1335 | + boardname, |
---|
| 1336 | + ATH10K_BD_IE_BOARD); |
---|
| 1337 | + if (ret == -ENOENT) |
---|
| 1338 | + /* no match found, continue */ |
---|
| 1339 | + break; |
---|
| 1340 | + |
---|
| 1341 | + /* either found or error, so stop searching */ |
---|
| 1342 | + goto out; |
---|
| 1343 | + case ATH10K_BD_IE_BOARD_EXT: |
---|
| 1344 | + ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, |
---|
| 1345 | + boardname, |
---|
| 1346 | + ATH10K_BD_IE_BOARD_EXT); |
---|
| 1347 | + if (ret == -ENOENT) |
---|
| 1348 | + /* no match found, continue */ |
---|
| 1349 | + break; |
---|
| 1350 | + |
---|
| 1351 | + /* either found or error, so stop searching */ |
---|
| 1352 | + goto out; |
---|
| 1353 | + } |
---|
| 1354 | + |
---|
| 1355 | + /* jump over the padding */ |
---|
| 1356 | + ie_len = ALIGN(ie_len, 4); |
---|
| 1357 | + |
---|
| 1358 | + len -= ie_len; |
---|
| 1359 | + data += ie_len; |
---|
| 1360 | + } |
---|
| 1361 | + |
---|
| 1362 | +out: |
---|
| 1363 | + /* return result of parse_bd_ie_board() or -ENOENT */ |
---|
| 1364 | + return ret; |
---|
| 1365 | +} |
---|
| 1366 | + |
---|
| 1367 | +static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, |
---|
| 1368 | + const char *boardname, |
---|
| 1369 | + const char *fallback_boardname, |
---|
| 1370 | + const char *filename) |
---|
| 1371 | +{ |
---|
| 1372 | + size_t len, magic_len; |
---|
| 1373 | + const u8 *data; |
---|
| 1374 | + int ret; |
---|
| 1375 | + |
---|
| 1376 | + /* Skip if already fetched during board data download */ |
---|
| 1377 | + if (!ar->normal_mode_fw.board) |
---|
| 1378 | + ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, |
---|
| 1379 | + ar->hw_params.fw.dir, |
---|
| 1380 | + filename); |
---|
| 1381 | + if (IS_ERR(ar->normal_mode_fw.board)) |
---|
| 1382 | + return PTR_ERR(ar->normal_mode_fw.board); |
---|
| 1383 | + |
---|
| 1384 | + data = ar->normal_mode_fw.board->data; |
---|
| 1385 | + len = ar->normal_mode_fw.board->size; |
---|
| 1386 | + |
---|
| 1387 | + /* magic has extra null byte padded */ |
---|
| 1388 | + magic_len = strlen(ATH10K_BOARD_MAGIC) + 1; |
---|
| 1389 | + if (len < magic_len) { |
---|
| 1390 | + ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n", |
---|
| 1391 | + ar->hw_params.fw.dir, filename, len); |
---|
| 1392 | + ret = -EINVAL; |
---|
| 1393 | + goto err; |
---|
| 1394 | + } |
---|
| 1395 | + |
---|
| 1396 | + if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) { |
---|
| 1397 | + ath10k_err(ar, "found invalid board magic\n"); |
---|
| 1398 | + ret = -EINVAL; |
---|
| 1399 | + goto err; |
---|
| 1400 | + } |
---|
| 1401 | + |
---|
| 1402 | + /* magic is padded to 4 bytes */ |
---|
| 1403 | + magic_len = ALIGN(magic_len, 4); |
---|
| 1404 | + if (len < magic_len) { |
---|
| 1405 | + ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n", |
---|
| 1406 | + ar->hw_params.fw.dir, filename, len); |
---|
| 1407 | + ret = -EINVAL; |
---|
| 1408 | + goto err; |
---|
| 1409 | + } |
---|
| 1410 | + |
---|
| 1411 | + data += magic_len; |
---|
| 1412 | + len -= magic_len; |
---|
| 1413 | + |
---|
| 1414 | + /* attempt to find boardname in the IE list */ |
---|
| 1415 | + ret = ath10k_core_search_bd(ar, boardname, data, len); |
---|
| 1416 | + |
---|
| 1417 | + /* if we didn't find it and have a fallback name, try that */ |
---|
| 1418 | + if (ret == -ENOENT && fallback_boardname) |
---|
| 1419 | + ret = ath10k_core_search_bd(ar, fallback_boardname, data, len); |
---|
| 1420 | + |
---|
| 1421 | + if (ret == -ENOENT) { |
---|
| 1422 | + ath10k_err(ar, |
---|
| 1423 | + "failed to fetch board data for %s from %s/%s\n", |
---|
| 1424 | + boardname, ar->hw_params.fw.dir, filename); |
---|
| 1425 | + ret = -ENODATA; |
---|
| 1426 | + } |
---|
| 1427 | + |
---|
| 1428 | + if (ret) |
---|
| 1429 | + goto err; |
---|
| 1430 | + |
---|
| 1431 | + return 0; |
---|
| 1432 | + |
---|
| 1433 | +err: |
---|
| 1434 | + ath10k_core_free_board_files(ar); |
---|
| 1435 | + return ret; |
---|
| 1436 | +} |
---|
| 1437 | + |
---|
| 1438 | +static int ath10k_core_create_board_name(struct ath10k *ar, char *name, |
---|
| 1439 | + size_t name_len, bool with_variant) |
---|
| 1440 | +{ |
---|
| 1441 | + /* strlen(',variant=') + strlen(ar->id.bdf_ext) */ |
---|
| 1442 | + char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 }; |
---|
| 1443 | + |
---|
| 1444 | + if (with_variant && ar->id.bdf_ext[0] != '\0') |
---|
| 1445 | + scnprintf(variant, sizeof(variant), ",variant=%s", |
---|
| 1446 | + ar->id.bdf_ext); |
---|
| 1447 | + |
---|
| 1448 | + if (ar->id.bmi_ids_valid) { |
---|
| 1449 | + scnprintf(name, name_len, |
---|
| 1450 | + "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s", |
---|
| 1451 | + ath10k_bus_str(ar->hif.bus), |
---|
| 1452 | + ar->id.bmi_chip_id, |
---|
| 1453 | + ar->id.bmi_board_id, variant); |
---|
| 1454 | + goto out; |
---|
| 1455 | + } |
---|
| 1456 | + |
---|
| 1457 | + if (ar->id.qmi_ids_valid) { |
---|
| 1458 | + if (with_variant && ar->id.bdf_ext[0] != '\0') |
---|
| 1459 | + scnprintf(name, name_len, |
---|
| 1460 | + "bus=%s,qmi-board-id=%x,qmi-chip-id=%x%s", |
---|
| 1461 | + ath10k_bus_str(ar->hif.bus), |
---|
| 1462 | + ar->id.qmi_board_id, ar->id.qmi_chip_id, |
---|
| 1463 | + variant); |
---|
| 1464 | + else |
---|
| 1465 | + scnprintf(name, name_len, |
---|
| 1466 | + "bus=%s,qmi-board-id=%x", |
---|
| 1467 | + ath10k_bus_str(ar->hif.bus), |
---|
| 1468 | + ar->id.qmi_board_id); |
---|
| 1469 | + goto out; |
---|
| 1470 | + } |
---|
| 1471 | + |
---|
| 1472 | + scnprintf(name, name_len, |
---|
| 1473 | + "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s", |
---|
| 1474 | + ath10k_bus_str(ar->hif.bus), |
---|
| 1475 | + ar->id.vendor, ar->id.device, |
---|
| 1476 | + ar->id.subsystem_vendor, ar->id.subsystem_device, variant); |
---|
| 1477 | +out: |
---|
| 1478 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name); |
---|
| 1479 | + |
---|
| 1480 | + return 0; |
---|
| 1481 | +} |
---|
| 1482 | + |
---|
| 1483 | +static int ath10k_core_create_eboard_name(struct ath10k *ar, char *name, |
---|
| 1484 | + size_t name_len) |
---|
| 1485 | +{ |
---|
| 1486 | + if (ar->id.bmi_ids_valid) { |
---|
| 1487 | + scnprintf(name, name_len, |
---|
| 1488 | + "bus=%s,bmi-chip-id=%d,bmi-eboard-id=%d", |
---|
| 1489 | + ath10k_bus_str(ar->hif.bus), |
---|
| 1490 | + ar->id.bmi_chip_id, |
---|
| 1491 | + ar->id.bmi_eboard_id); |
---|
| 1492 | + |
---|
| 1493 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using eboard name '%s'\n", name); |
---|
| 1494 | + return 0; |
---|
| 1495 | + } |
---|
| 1496 | + /* Fallback if returned board id is zero */ |
---|
| 1497 | + return -1; |
---|
| 1498 | +} |
---|
| 1499 | + |
---|
| 1500 | +int ath10k_core_fetch_board_file(struct ath10k *ar, int bd_ie_type) |
---|
| 1501 | +{ |
---|
| 1502 | + char boardname[100], fallback_boardname[100]; |
---|
| 1503 | + int ret; |
---|
| 1504 | + |
---|
| 1505 | + if (bd_ie_type == ATH10K_BD_IE_BOARD) { |
---|
| 1506 | + ret = ath10k_core_create_board_name(ar, boardname, |
---|
| 1507 | + sizeof(boardname), true); |
---|
| 1508 | + if (ret) { |
---|
| 1509 | + ath10k_err(ar, "failed to create board name: %d", ret); |
---|
| 1510 | + return ret; |
---|
| 1511 | + } |
---|
| 1512 | + |
---|
| 1513 | + ret = ath10k_core_create_board_name(ar, fallback_boardname, |
---|
| 1514 | + sizeof(boardname), false); |
---|
| 1515 | + if (ret) { |
---|
| 1516 | + ath10k_err(ar, "failed to create fallback board name: %d", ret); |
---|
| 1517 | + return ret; |
---|
| 1518 | + } |
---|
| 1519 | + } else if (bd_ie_type == ATH10K_BD_IE_BOARD_EXT) { |
---|
| 1520 | + ret = ath10k_core_create_eboard_name(ar, boardname, |
---|
| 1521 | + sizeof(boardname)); |
---|
| 1522 | + if (ret) { |
---|
| 1523 | + ath10k_err(ar, "fallback to eboard.bin since board id 0"); |
---|
| 1524 | + goto fallback; |
---|
| 1525 | + } |
---|
| 1526 | + } |
---|
| 1527 | + |
---|
| 1528 | + ar->bd_api = 2; |
---|
| 1529 | + ret = ath10k_core_fetch_board_data_api_n(ar, boardname, |
---|
| 1530 | + fallback_boardname, |
---|
| 1531 | + ATH10K_BOARD_API2_FILE); |
---|
| 1532 | + if (!ret) |
---|
| 1533 | + goto success; |
---|
| 1534 | + |
---|
| 1535 | +fallback: |
---|
| 1536 | + ar->bd_api = 1; |
---|
| 1537 | + ret = ath10k_core_fetch_board_data_api_1(ar, bd_ie_type); |
---|
| 1538 | + if (ret) { |
---|
| 1539 | + ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n", |
---|
| 1540 | + ar->hw_params.fw.dir); |
---|
| 1541 | + return ret; |
---|
| 1542 | + } |
---|
| 1543 | + |
---|
| 1544 | +success: |
---|
| 1545 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api); |
---|
| 1546 | + return 0; |
---|
| 1547 | +} |
---|
| 1548 | +EXPORT_SYMBOL(ath10k_core_fetch_board_file); |
---|
| 1549 | + |
---|
| 1550 | +static int ath10k_core_get_ext_board_id_from_otp(struct ath10k *ar) |
---|
| 1551 | +{ |
---|
| 1552 | + u32 result, address; |
---|
| 1553 | + u8 ext_board_id; |
---|
| 1554 | + int ret; |
---|
| 1555 | + |
---|
| 1556 | + address = ar->hw_params.patch_load_addr; |
---|
| 1557 | + |
---|
| 1558 | + if (!ar->normal_mode_fw.fw_file.otp_data || |
---|
| 1559 | + !ar->normal_mode_fw.fw_file.otp_len) { |
---|
| 1560 | + ath10k_warn(ar, |
---|
| 1561 | + "failed to retrieve extended board id due to otp binary missing\n"); |
---|
| 1562 | + return -ENODATA; |
---|
| 1563 | + } |
---|
| 1564 | + |
---|
| 1565 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1566 | + "boot upload otp to 0x%x len %zd for ext board id\n", |
---|
| 1567 | + address, ar->normal_mode_fw.fw_file.otp_len); |
---|
| 1568 | + |
---|
| 1569 | + ret = ath10k_bmi_fast_download(ar, address, |
---|
| 1570 | + ar->normal_mode_fw.fw_file.otp_data, |
---|
| 1571 | + ar->normal_mode_fw.fw_file.otp_len); |
---|
| 1572 | + if (ret) { |
---|
| 1573 | + ath10k_err(ar, "could not write otp for ext board id check: %d\n", |
---|
| 1574 | + ret); |
---|
| 1575 | + return ret; |
---|
| 1576 | + } |
---|
| 1577 | + |
---|
| 1578 | + ret = ath10k_bmi_execute(ar, address, BMI_PARAM_GET_EXT_BOARD_ID, &result); |
---|
| 1579 | + if (ret) { |
---|
| 1580 | + ath10k_err(ar, "could not execute otp for ext board id check: %d\n", |
---|
| 1581 | + ret); |
---|
| 1582 | + return ret; |
---|
| 1583 | + } |
---|
| 1584 | + |
---|
| 1585 | + if (!result) { |
---|
| 1586 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1587 | + "ext board id does not exist in otp, ignore it\n"); |
---|
| 1588 | + return -EOPNOTSUPP; |
---|
| 1589 | + } |
---|
| 1590 | + |
---|
| 1591 | + ext_board_id = result & ATH10K_BMI_EBOARD_ID_STATUS_MASK; |
---|
| 1592 | + |
---|
| 1593 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1594 | + "boot get otp ext board id result 0x%08x ext_board_id %d\n", |
---|
| 1595 | + result, ext_board_id); |
---|
| 1596 | + |
---|
| 1597 | + ar->id.bmi_eboard_id = ext_board_id; |
---|
| 1598 | + |
---|
| 1599 | + return 0; |
---|
| 1600 | +} |
---|
| 1601 | + |
---|
780 | 1602 | static int ath10k_download_board_data(struct ath10k *ar, const void *data, |
---|
781 | 1603 | size_t data_len) |
---|
782 | 1604 | { |
---|
783 | 1605 | u32 board_data_size = ar->hw_params.fw.board_size; |
---|
784 | | - u32 address; |
---|
| 1606 | + u32 eboard_data_size = ar->hw_params.fw.ext_board_size; |
---|
| 1607 | + u32 board_address; |
---|
| 1608 | + u32 ext_board_address; |
---|
785 | 1609 | int ret; |
---|
786 | 1610 | |
---|
787 | 1611 | ret = ath10k_push_board_ext_data(ar, data, data_len); |
---|
.. | .. |
---|
790 | 1614 | goto exit; |
---|
791 | 1615 | } |
---|
792 | 1616 | |
---|
793 | | - ret = ath10k_bmi_read32(ar, hi_board_data, &address); |
---|
| 1617 | + ret = ath10k_bmi_read32(ar, hi_board_data, &board_address); |
---|
794 | 1618 | if (ret) { |
---|
795 | 1619 | ath10k_err(ar, "could not read board data addr (%d)\n", ret); |
---|
796 | 1620 | goto exit; |
---|
797 | 1621 | } |
---|
798 | 1622 | |
---|
799 | | - ret = ath10k_bmi_write_memory(ar, address, data, |
---|
| 1623 | + ret = ath10k_bmi_write_memory(ar, board_address, data, |
---|
800 | 1624 | min_t(u32, board_data_size, |
---|
801 | 1625 | data_len)); |
---|
802 | 1626 | if (ret) { |
---|
.. | .. |
---|
810 | 1634 | goto exit; |
---|
811 | 1635 | } |
---|
812 | 1636 | |
---|
| 1637 | + if (!ar->id.ext_bid_supported) |
---|
| 1638 | + goto exit; |
---|
| 1639 | + |
---|
| 1640 | + /* Extended board data download */ |
---|
| 1641 | + ret = ath10k_core_get_ext_board_id_from_otp(ar); |
---|
| 1642 | + if (ret == -EOPNOTSUPP) { |
---|
| 1643 | + /* Not fetching ext_board_data if ext board id is 0 */ |
---|
| 1644 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "otp returned ext board id 0\n"); |
---|
| 1645 | + return 0; |
---|
| 1646 | + } else if (ret) { |
---|
| 1647 | + ath10k_err(ar, "failed to get extended board id: %d\n", ret); |
---|
| 1648 | + goto exit; |
---|
| 1649 | + } |
---|
| 1650 | + |
---|
| 1651 | + ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD_EXT); |
---|
| 1652 | + if (ret) |
---|
| 1653 | + goto exit; |
---|
| 1654 | + |
---|
| 1655 | + if (ar->normal_mode_fw.ext_board_data) { |
---|
| 1656 | + ext_board_address = board_address + EXT_BOARD_ADDRESS_OFFSET; |
---|
| 1657 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
| 1658 | + "boot writing ext board data to addr 0x%x", |
---|
| 1659 | + ext_board_address); |
---|
| 1660 | + ret = ath10k_bmi_write_memory(ar, ext_board_address, |
---|
| 1661 | + ar->normal_mode_fw.ext_board_data, |
---|
| 1662 | + min_t(u32, eboard_data_size, data_len)); |
---|
| 1663 | + if (ret) |
---|
| 1664 | + ath10k_err(ar, "failed to write ext board data: %d\n", ret); |
---|
| 1665 | + } |
---|
| 1666 | + |
---|
813 | 1667 | exit: |
---|
814 | 1668 | return ret; |
---|
| 1669 | +} |
---|
| 1670 | + |
---|
| 1671 | +static int ath10k_download_and_run_otp(struct ath10k *ar) |
---|
| 1672 | +{ |
---|
| 1673 | + u32 result, address = ar->hw_params.patch_load_addr; |
---|
| 1674 | + u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; |
---|
| 1675 | + int ret; |
---|
| 1676 | + |
---|
| 1677 | + ret = ath10k_download_board_data(ar, |
---|
| 1678 | + ar->running_fw->board_data, |
---|
| 1679 | + ar->running_fw->board_len); |
---|
| 1680 | + if (ret) { |
---|
| 1681 | + ath10k_err(ar, "failed to download board data: %d\n", ret); |
---|
| 1682 | + return ret; |
---|
| 1683 | + } |
---|
| 1684 | + |
---|
| 1685 | + /* OTP is optional */ |
---|
| 1686 | + |
---|
| 1687 | + if (!ar->running_fw->fw_file.otp_data || |
---|
| 1688 | + !ar->running_fw->fw_file.otp_len) { |
---|
| 1689 | + ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n", |
---|
| 1690 | + ar->running_fw->fw_file.otp_data, |
---|
| 1691 | + ar->running_fw->fw_file.otp_len); |
---|
| 1692 | + return 0; |
---|
| 1693 | + } |
---|
| 1694 | + |
---|
| 1695 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", |
---|
| 1696 | + address, ar->running_fw->fw_file.otp_len); |
---|
| 1697 | + |
---|
| 1698 | + ret = ath10k_bmi_fast_download(ar, address, |
---|
| 1699 | + ar->running_fw->fw_file.otp_data, |
---|
| 1700 | + ar->running_fw->fw_file.otp_len); |
---|
| 1701 | + if (ret) { |
---|
| 1702 | + ath10k_err(ar, "could not write otp (%d)\n", ret); |
---|
| 1703 | + return ret; |
---|
| 1704 | + } |
---|
| 1705 | + |
---|
| 1706 | + /* As of now pre-cal is valid for 10_4 variants */ |
---|
| 1707 | + if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || |
---|
| 1708 | + ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) |
---|
| 1709 | + bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; |
---|
| 1710 | + |
---|
| 1711 | + ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); |
---|
| 1712 | + if (ret) { |
---|
| 1713 | + ath10k_err(ar, "could not execute otp (%d)\n", ret); |
---|
| 1714 | + return ret; |
---|
| 1715 | + } |
---|
| 1716 | + |
---|
| 1717 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); |
---|
| 1718 | + |
---|
| 1719 | + if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, |
---|
| 1720 | + ar->running_fw->fw_file.fw_features)) && |
---|
| 1721 | + result != 0) { |
---|
| 1722 | + ath10k_err(ar, "otp calibration failed: %d", result); |
---|
| 1723 | + return -EINVAL; |
---|
| 1724 | + } |
---|
| 1725 | + |
---|
| 1726 | + return 0; |
---|
815 | 1727 | } |
---|
816 | 1728 | |
---|
817 | 1729 | static int ath10k_download_cal_file(struct ath10k *ar, |
---|
.. | .. |
---|
918 | 1830 | kfree(data); |
---|
919 | 1831 | |
---|
920 | 1832 | return ret; |
---|
921 | | -} |
---|
922 | | - |
---|
923 | | -static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) |
---|
924 | | -{ |
---|
925 | | - u32 result, address; |
---|
926 | | - u8 board_id, chip_id; |
---|
927 | | - int ret, bmi_board_id_param; |
---|
928 | | - |
---|
929 | | - address = ar->hw_params.patch_load_addr; |
---|
930 | | - |
---|
931 | | - if (!ar->normal_mode_fw.fw_file.otp_data || |
---|
932 | | - !ar->normal_mode_fw.fw_file.otp_len) { |
---|
933 | | - ath10k_warn(ar, |
---|
934 | | - "failed to retrieve board id because of invalid otp\n"); |
---|
935 | | - return -ENODATA; |
---|
936 | | - } |
---|
937 | | - |
---|
938 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
939 | | - "boot upload otp to 0x%x len %zd for board id\n", |
---|
940 | | - address, ar->normal_mode_fw.fw_file.otp_len); |
---|
941 | | - |
---|
942 | | - ret = ath10k_bmi_fast_download(ar, address, |
---|
943 | | - ar->normal_mode_fw.fw_file.otp_data, |
---|
944 | | - ar->normal_mode_fw.fw_file.otp_len); |
---|
945 | | - if (ret) { |
---|
946 | | - ath10k_err(ar, "could not write otp for board id check: %d\n", |
---|
947 | | - ret); |
---|
948 | | - return ret; |
---|
949 | | - } |
---|
950 | | - |
---|
951 | | - if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || |
---|
952 | | - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) |
---|
953 | | - bmi_board_id_param = BMI_PARAM_GET_FLASH_BOARD_ID; |
---|
954 | | - else |
---|
955 | | - bmi_board_id_param = BMI_PARAM_GET_EEPROM_BOARD_ID; |
---|
956 | | - |
---|
957 | | - ret = ath10k_bmi_execute(ar, address, bmi_board_id_param, &result); |
---|
958 | | - if (ret) { |
---|
959 | | - ath10k_err(ar, "could not execute otp for board id check: %d\n", |
---|
960 | | - ret); |
---|
961 | | - return ret; |
---|
962 | | - } |
---|
963 | | - |
---|
964 | | - board_id = MS(result, ATH10K_BMI_BOARD_ID_FROM_OTP); |
---|
965 | | - chip_id = MS(result, ATH10K_BMI_CHIP_ID_FROM_OTP); |
---|
966 | | - |
---|
967 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
968 | | - "boot get otp board id result 0x%08x board_id %d chip_id %d\n", |
---|
969 | | - result, board_id, chip_id); |
---|
970 | | - |
---|
971 | | - if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 || |
---|
972 | | - (board_id == 0)) { |
---|
973 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
974 | | - "board id does not exist in otp, ignore it\n"); |
---|
975 | | - return -EOPNOTSUPP; |
---|
976 | | - } |
---|
977 | | - |
---|
978 | | - ar->id.bmi_ids_valid = true; |
---|
979 | | - ar->id.bmi_board_id = board_id; |
---|
980 | | - ar->id.bmi_chip_id = chip_id; |
---|
981 | | - |
---|
982 | | - return 0; |
---|
983 | | -} |
---|
984 | | - |
---|
985 | | -static void ath10k_core_check_bdfext(const struct dmi_header *hdr, void *data) |
---|
986 | | -{ |
---|
987 | | - struct ath10k *ar = data; |
---|
988 | | - const char *bdf_ext; |
---|
989 | | - const char *magic = ATH10K_SMBIOS_BDF_EXT_MAGIC; |
---|
990 | | - u8 bdf_enabled; |
---|
991 | | - int i; |
---|
992 | | - |
---|
993 | | - if (hdr->type != ATH10K_SMBIOS_BDF_EXT_TYPE) |
---|
994 | | - return; |
---|
995 | | - |
---|
996 | | - if (hdr->length != ATH10K_SMBIOS_BDF_EXT_LENGTH) { |
---|
997 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
998 | | - "wrong smbios bdf ext type length (%d).\n", |
---|
999 | | - hdr->length); |
---|
1000 | | - return; |
---|
1001 | | - } |
---|
1002 | | - |
---|
1003 | | - bdf_enabled = *((u8 *)hdr + ATH10K_SMBIOS_BDF_EXT_OFFSET); |
---|
1004 | | - if (!bdf_enabled) { |
---|
1005 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not found.\n"); |
---|
1006 | | - return; |
---|
1007 | | - } |
---|
1008 | | - |
---|
1009 | | - /* Only one string exists (per spec) */ |
---|
1010 | | - bdf_ext = (char *)hdr + hdr->length; |
---|
1011 | | - |
---|
1012 | | - if (memcmp(bdf_ext, magic, strlen(magic)) != 0) { |
---|
1013 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1014 | | - "bdf variant magic does not match.\n"); |
---|
1015 | | - return; |
---|
1016 | | - } |
---|
1017 | | - |
---|
1018 | | - for (i = 0; i < strlen(bdf_ext); i++) { |
---|
1019 | | - if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) { |
---|
1020 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1021 | | - "bdf variant name contains non ascii chars.\n"); |
---|
1022 | | - return; |
---|
1023 | | - } |
---|
1024 | | - } |
---|
1025 | | - |
---|
1026 | | - /* Copy extension name without magic suffix */ |
---|
1027 | | - if (strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic), |
---|
1028 | | - sizeof(ar->id.bdf_ext)) < 0) { |
---|
1029 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1030 | | - "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", |
---|
1031 | | - bdf_ext); |
---|
1032 | | - return; |
---|
1033 | | - } |
---|
1034 | | - |
---|
1035 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1036 | | - "found and validated bdf variant smbios_type 0x%x bdf %s\n", |
---|
1037 | | - ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext); |
---|
1038 | | -} |
---|
1039 | | - |
---|
1040 | | -static int ath10k_core_check_smbios(struct ath10k *ar) |
---|
1041 | | -{ |
---|
1042 | | - ar->id.bdf_ext[0] = '\0'; |
---|
1043 | | - dmi_walk(ath10k_core_check_bdfext, ar); |
---|
1044 | | - |
---|
1045 | | - if (ar->id.bdf_ext[0] == '\0') |
---|
1046 | | - return -ENODATA; |
---|
1047 | | - |
---|
1048 | | - return 0; |
---|
1049 | | -} |
---|
1050 | | - |
---|
1051 | | -static int ath10k_core_check_dt(struct ath10k *ar) |
---|
1052 | | -{ |
---|
1053 | | - struct device_node *node; |
---|
1054 | | - const char *variant = NULL; |
---|
1055 | | - |
---|
1056 | | - node = ar->dev->of_node; |
---|
1057 | | - if (!node) |
---|
1058 | | - return -ENOENT; |
---|
1059 | | - |
---|
1060 | | - of_property_read_string(node, "qcom,ath10k-calibration-variant", |
---|
1061 | | - &variant); |
---|
1062 | | - if (!variant) |
---|
1063 | | - return -ENODATA; |
---|
1064 | | - |
---|
1065 | | - if (strscpy(ar->id.bdf_ext, variant, sizeof(ar->id.bdf_ext)) < 0) |
---|
1066 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1067 | | - "bdf variant string is longer than the buffer can accommodate (variant: %s)\n", |
---|
1068 | | - variant); |
---|
1069 | | - |
---|
1070 | | - return 0; |
---|
1071 | | -} |
---|
1072 | | - |
---|
1073 | | -static int ath10k_download_and_run_otp(struct ath10k *ar) |
---|
1074 | | -{ |
---|
1075 | | - u32 result, address = ar->hw_params.patch_load_addr; |
---|
1076 | | - u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param; |
---|
1077 | | - int ret; |
---|
1078 | | - |
---|
1079 | | - ret = ath10k_download_board_data(ar, |
---|
1080 | | - ar->running_fw->board_data, |
---|
1081 | | - ar->running_fw->board_len); |
---|
1082 | | - if (ret) { |
---|
1083 | | - ath10k_err(ar, "failed to download board data: %d\n", ret); |
---|
1084 | | - return ret; |
---|
1085 | | - } |
---|
1086 | | - |
---|
1087 | | - /* OTP is optional */ |
---|
1088 | | - |
---|
1089 | | - if (!ar->running_fw->fw_file.otp_data || |
---|
1090 | | - !ar->running_fw->fw_file.otp_len) { |
---|
1091 | | - ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %pK otp_len %zd)!\n", |
---|
1092 | | - ar->running_fw->fw_file.otp_data, |
---|
1093 | | - ar->running_fw->fw_file.otp_len); |
---|
1094 | | - return 0; |
---|
1095 | | - } |
---|
1096 | | - |
---|
1097 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n", |
---|
1098 | | - address, ar->running_fw->fw_file.otp_len); |
---|
1099 | | - |
---|
1100 | | - ret = ath10k_bmi_fast_download(ar, address, |
---|
1101 | | - ar->running_fw->fw_file.otp_data, |
---|
1102 | | - ar->running_fw->fw_file.otp_len); |
---|
1103 | | - if (ret) { |
---|
1104 | | - ath10k_err(ar, "could not write otp (%d)\n", ret); |
---|
1105 | | - return ret; |
---|
1106 | | - } |
---|
1107 | | - |
---|
1108 | | - /* As of now pre-cal is valid for 10_4 variants */ |
---|
1109 | | - if (ar->cal_mode == ATH10K_PRE_CAL_MODE_DT || |
---|
1110 | | - ar->cal_mode == ATH10K_PRE_CAL_MODE_FILE) |
---|
1111 | | - bmi_otp_exe_param = BMI_PARAM_FLASH_SECTION_ALL; |
---|
1112 | | - |
---|
1113 | | - ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result); |
---|
1114 | | - if (ret) { |
---|
1115 | | - ath10k_err(ar, "could not execute otp (%d)\n", ret); |
---|
1116 | | - return ret; |
---|
1117 | | - } |
---|
1118 | | - |
---|
1119 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); |
---|
1120 | | - |
---|
1121 | | - if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT, |
---|
1122 | | - ar->running_fw->fw_file.fw_features)) && |
---|
1123 | | - result != 0) { |
---|
1124 | | - ath10k_err(ar, "otp calibration failed: %d", result); |
---|
1125 | | - return -EINVAL; |
---|
1126 | | - } |
---|
1127 | | - |
---|
1128 | | - return 0; |
---|
1129 | | -} |
---|
1130 | | - |
---|
1131 | | -static int ath10k_download_fw(struct ath10k *ar) |
---|
1132 | | -{ |
---|
1133 | | - u32 address, data_len; |
---|
1134 | | - const void *data; |
---|
1135 | | - int ret; |
---|
1136 | | - |
---|
1137 | | - address = ar->hw_params.patch_load_addr; |
---|
1138 | | - |
---|
1139 | | - data = ar->running_fw->fw_file.firmware_data; |
---|
1140 | | - data_len = ar->running_fw->fw_file.firmware_len; |
---|
1141 | | - |
---|
1142 | | - ret = ath10k_swap_code_seg_configure(ar, &ar->running_fw->fw_file); |
---|
1143 | | - if (ret) { |
---|
1144 | | - ath10k_err(ar, "failed to configure fw code swap: %d\n", |
---|
1145 | | - ret); |
---|
1146 | | - return ret; |
---|
1147 | | - } |
---|
1148 | | - |
---|
1149 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1150 | | - "boot uploading firmware image %pK len %d\n", |
---|
1151 | | - data, data_len); |
---|
1152 | | - |
---|
1153 | | - ret = ath10k_bmi_fast_download(ar, address, data, data_len); |
---|
1154 | | - if (ret) { |
---|
1155 | | - ath10k_err(ar, "failed to download firmware: %d\n", |
---|
1156 | | - ret); |
---|
1157 | | - return ret; |
---|
1158 | | - } |
---|
1159 | | - |
---|
1160 | | - return ret; |
---|
1161 | | -} |
---|
1162 | | - |
---|
1163 | | -static void ath10k_core_free_board_files(struct ath10k *ar) |
---|
1164 | | -{ |
---|
1165 | | - if (!IS_ERR(ar->normal_mode_fw.board)) |
---|
1166 | | - release_firmware(ar->normal_mode_fw.board); |
---|
1167 | | - |
---|
1168 | | - ar->normal_mode_fw.board = NULL; |
---|
1169 | | - ar->normal_mode_fw.board_data = NULL; |
---|
1170 | | - ar->normal_mode_fw.board_len = 0; |
---|
1171 | | -} |
---|
1172 | | - |
---|
1173 | | -static void ath10k_core_free_firmware_files(struct ath10k *ar) |
---|
1174 | | -{ |
---|
1175 | | - if (!IS_ERR(ar->normal_mode_fw.fw_file.firmware)) |
---|
1176 | | - release_firmware(ar->normal_mode_fw.fw_file.firmware); |
---|
1177 | | - |
---|
1178 | | - if (!IS_ERR(ar->cal_file)) |
---|
1179 | | - release_firmware(ar->cal_file); |
---|
1180 | | - |
---|
1181 | | - if (!IS_ERR(ar->pre_cal_file)) |
---|
1182 | | - release_firmware(ar->pre_cal_file); |
---|
1183 | | - |
---|
1184 | | - ath10k_swap_code_seg_release(ar, &ar->normal_mode_fw.fw_file); |
---|
1185 | | - |
---|
1186 | | - ar->normal_mode_fw.fw_file.otp_data = NULL; |
---|
1187 | | - ar->normal_mode_fw.fw_file.otp_len = 0; |
---|
1188 | | - |
---|
1189 | | - ar->normal_mode_fw.fw_file.firmware = NULL; |
---|
1190 | | - ar->normal_mode_fw.fw_file.firmware_data = NULL; |
---|
1191 | | - ar->normal_mode_fw.fw_file.firmware_len = 0; |
---|
1192 | | - |
---|
1193 | | - ar->cal_file = NULL; |
---|
1194 | | - ar->pre_cal_file = NULL; |
---|
1195 | | -} |
---|
1196 | | - |
---|
1197 | | -static int ath10k_fetch_cal_file(struct ath10k *ar) |
---|
1198 | | -{ |
---|
1199 | | - char filename[100]; |
---|
1200 | | - |
---|
1201 | | - /* pre-cal-<bus>-<id>.bin */ |
---|
1202 | | - scnprintf(filename, sizeof(filename), "pre-cal-%s-%s.bin", |
---|
1203 | | - ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); |
---|
1204 | | - |
---|
1205 | | - ar->pre_cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); |
---|
1206 | | - if (!IS_ERR(ar->pre_cal_file)) |
---|
1207 | | - goto success; |
---|
1208 | | - |
---|
1209 | | - /* cal-<bus>-<id>.bin */ |
---|
1210 | | - scnprintf(filename, sizeof(filename), "cal-%s-%s.bin", |
---|
1211 | | - ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); |
---|
1212 | | - |
---|
1213 | | - ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); |
---|
1214 | | - if (IS_ERR(ar->cal_file)) |
---|
1215 | | - /* calibration file is optional, don't print any warnings */ |
---|
1216 | | - return PTR_ERR(ar->cal_file); |
---|
1217 | | -success: |
---|
1218 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n", |
---|
1219 | | - ATH10K_FW_DIR, filename); |
---|
1220 | | - |
---|
1221 | | - return 0; |
---|
1222 | | -} |
---|
1223 | | - |
---|
1224 | | -static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar) |
---|
1225 | | -{ |
---|
1226 | | - if (!ar->hw_params.fw.board) { |
---|
1227 | | - ath10k_err(ar, "failed to find board file fw entry\n"); |
---|
1228 | | - return -EINVAL; |
---|
1229 | | - } |
---|
1230 | | - |
---|
1231 | | - ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, |
---|
1232 | | - ar->hw_params.fw.dir, |
---|
1233 | | - ar->hw_params.fw.board); |
---|
1234 | | - if (IS_ERR(ar->normal_mode_fw.board)) |
---|
1235 | | - return PTR_ERR(ar->normal_mode_fw.board); |
---|
1236 | | - |
---|
1237 | | - ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data; |
---|
1238 | | - ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size; |
---|
1239 | | - |
---|
1240 | | - return 0; |
---|
1241 | | -} |
---|
1242 | | - |
---|
1243 | | -static int ath10k_core_parse_bd_ie_board(struct ath10k *ar, |
---|
1244 | | - const void *buf, size_t buf_len, |
---|
1245 | | - const char *boardname) |
---|
1246 | | -{ |
---|
1247 | | - const struct ath10k_fw_ie *hdr; |
---|
1248 | | - bool name_match_found; |
---|
1249 | | - int ret, board_ie_id; |
---|
1250 | | - size_t board_ie_len; |
---|
1251 | | - const void *board_ie_data; |
---|
1252 | | - |
---|
1253 | | - name_match_found = false; |
---|
1254 | | - |
---|
1255 | | - /* go through ATH10K_BD_IE_BOARD_ elements */ |
---|
1256 | | - while (buf_len > sizeof(struct ath10k_fw_ie)) { |
---|
1257 | | - hdr = buf; |
---|
1258 | | - board_ie_id = le32_to_cpu(hdr->id); |
---|
1259 | | - board_ie_len = le32_to_cpu(hdr->len); |
---|
1260 | | - board_ie_data = hdr->data; |
---|
1261 | | - |
---|
1262 | | - buf_len -= sizeof(*hdr); |
---|
1263 | | - buf += sizeof(*hdr); |
---|
1264 | | - |
---|
1265 | | - if (buf_len < ALIGN(board_ie_len, 4)) { |
---|
1266 | | - ath10k_err(ar, "invalid ATH10K_BD_IE_BOARD length: %zu < %zu\n", |
---|
1267 | | - buf_len, ALIGN(board_ie_len, 4)); |
---|
1268 | | - ret = -EINVAL; |
---|
1269 | | - goto out; |
---|
1270 | | - } |
---|
1271 | | - |
---|
1272 | | - switch (board_ie_id) { |
---|
1273 | | - case ATH10K_BD_IE_BOARD_NAME: |
---|
1274 | | - ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "board name", "", |
---|
1275 | | - board_ie_data, board_ie_len); |
---|
1276 | | - |
---|
1277 | | - if (board_ie_len != strlen(boardname)) |
---|
1278 | | - break; |
---|
1279 | | - |
---|
1280 | | - ret = memcmp(board_ie_data, boardname, strlen(boardname)); |
---|
1281 | | - if (ret) |
---|
1282 | | - break; |
---|
1283 | | - |
---|
1284 | | - name_match_found = true; |
---|
1285 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1286 | | - "boot found match for name '%s'", |
---|
1287 | | - boardname); |
---|
1288 | | - break; |
---|
1289 | | - case ATH10K_BD_IE_BOARD_DATA: |
---|
1290 | | - if (!name_match_found) |
---|
1291 | | - /* no match found */ |
---|
1292 | | - break; |
---|
1293 | | - |
---|
1294 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, |
---|
1295 | | - "boot found board data for '%s'", |
---|
1296 | | - boardname); |
---|
1297 | | - |
---|
1298 | | - ar->normal_mode_fw.board_data = board_ie_data; |
---|
1299 | | - ar->normal_mode_fw.board_len = board_ie_len; |
---|
1300 | | - |
---|
1301 | | - ret = 0; |
---|
1302 | | - goto out; |
---|
1303 | | - default: |
---|
1304 | | - ath10k_warn(ar, "unknown ATH10K_BD_IE_BOARD found: %d\n", |
---|
1305 | | - board_ie_id); |
---|
1306 | | - break; |
---|
1307 | | - } |
---|
1308 | | - |
---|
1309 | | - /* jump over the padding */ |
---|
1310 | | - board_ie_len = ALIGN(board_ie_len, 4); |
---|
1311 | | - |
---|
1312 | | - buf_len -= board_ie_len; |
---|
1313 | | - buf += board_ie_len; |
---|
1314 | | - } |
---|
1315 | | - |
---|
1316 | | - /* no match found */ |
---|
1317 | | - ret = -ENOENT; |
---|
1318 | | - |
---|
1319 | | -out: |
---|
1320 | | - return ret; |
---|
1321 | | -} |
---|
1322 | | - |
---|
1323 | | -static int ath10k_core_search_bd(struct ath10k *ar, |
---|
1324 | | - const char *boardname, |
---|
1325 | | - const u8 *data, |
---|
1326 | | - size_t len) |
---|
1327 | | -{ |
---|
1328 | | - size_t ie_len; |
---|
1329 | | - struct ath10k_fw_ie *hdr; |
---|
1330 | | - int ret = -ENOENT, ie_id; |
---|
1331 | | - |
---|
1332 | | - while (len > sizeof(struct ath10k_fw_ie)) { |
---|
1333 | | - hdr = (struct ath10k_fw_ie *)data; |
---|
1334 | | - ie_id = le32_to_cpu(hdr->id); |
---|
1335 | | - ie_len = le32_to_cpu(hdr->len); |
---|
1336 | | - |
---|
1337 | | - len -= sizeof(*hdr); |
---|
1338 | | - data = hdr->data; |
---|
1339 | | - |
---|
1340 | | - if (len < ALIGN(ie_len, 4)) { |
---|
1341 | | - ath10k_err(ar, "invalid length for board ie_id %d ie_len %zu len %zu\n", |
---|
1342 | | - ie_id, ie_len, len); |
---|
1343 | | - return -EINVAL; |
---|
1344 | | - } |
---|
1345 | | - |
---|
1346 | | - switch (ie_id) { |
---|
1347 | | - case ATH10K_BD_IE_BOARD: |
---|
1348 | | - ret = ath10k_core_parse_bd_ie_board(ar, data, ie_len, |
---|
1349 | | - boardname); |
---|
1350 | | - if (ret == -ENOENT) |
---|
1351 | | - /* no match found, continue */ |
---|
1352 | | - break; |
---|
1353 | | - |
---|
1354 | | - /* either found or error, so stop searching */ |
---|
1355 | | - goto out; |
---|
1356 | | - } |
---|
1357 | | - |
---|
1358 | | - /* jump over the padding */ |
---|
1359 | | - ie_len = ALIGN(ie_len, 4); |
---|
1360 | | - |
---|
1361 | | - len -= ie_len; |
---|
1362 | | - data += ie_len; |
---|
1363 | | - } |
---|
1364 | | - |
---|
1365 | | -out: |
---|
1366 | | - /* return result of parse_bd_ie_board() or -ENOENT */ |
---|
1367 | | - return ret; |
---|
1368 | | -} |
---|
1369 | | - |
---|
1370 | | -static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar, |
---|
1371 | | - const char *boardname, |
---|
1372 | | - const char *fallback_boardname, |
---|
1373 | | - const char *filename) |
---|
1374 | | -{ |
---|
1375 | | - size_t len, magic_len; |
---|
1376 | | - const u8 *data; |
---|
1377 | | - int ret; |
---|
1378 | | - |
---|
1379 | | - ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar, |
---|
1380 | | - ar->hw_params.fw.dir, |
---|
1381 | | - filename); |
---|
1382 | | - if (IS_ERR(ar->normal_mode_fw.board)) |
---|
1383 | | - return PTR_ERR(ar->normal_mode_fw.board); |
---|
1384 | | - |
---|
1385 | | - data = ar->normal_mode_fw.board->data; |
---|
1386 | | - len = ar->normal_mode_fw.board->size; |
---|
1387 | | - |
---|
1388 | | - /* magic has extra null byte padded */ |
---|
1389 | | - magic_len = strlen(ATH10K_BOARD_MAGIC) + 1; |
---|
1390 | | - if (len < magic_len) { |
---|
1391 | | - ath10k_err(ar, "failed to find magic value in %s/%s, file too short: %zu\n", |
---|
1392 | | - ar->hw_params.fw.dir, filename, len); |
---|
1393 | | - ret = -EINVAL; |
---|
1394 | | - goto err; |
---|
1395 | | - } |
---|
1396 | | - |
---|
1397 | | - if (memcmp(data, ATH10K_BOARD_MAGIC, magic_len)) { |
---|
1398 | | - ath10k_err(ar, "found invalid board magic\n"); |
---|
1399 | | - ret = -EINVAL; |
---|
1400 | | - goto err; |
---|
1401 | | - } |
---|
1402 | | - |
---|
1403 | | - /* magic is padded to 4 bytes */ |
---|
1404 | | - magic_len = ALIGN(magic_len, 4); |
---|
1405 | | - if (len < magic_len) { |
---|
1406 | | - ath10k_err(ar, "failed: %s/%s too small to contain board data, len: %zu\n", |
---|
1407 | | - ar->hw_params.fw.dir, filename, len); |
---|
1408 | | - ret = -EINVAL; |
---|
1409 | | - goto err; |
---|
1410 | | - } |
---|
1411 | | - |
---|
1412 | | - data += magic_len; |
---|
1413 | | - len -= magic_len; |
---|
1414 | | - |
---|
1415 | | - /* attempt to find boardname in the IE list */ |
---|
1416 | | - ret = ath10k_core_search_bd(ar, boardname, data, len); |
---|
1417 | | - |
---|
1418 | | - /* if we didn't find it and have a fallback name, try that */ |
---|
1419 | | - if (ret == -ENOENT && fallback_boardname) |
---|
1420 | | - ret = ath10k_core_search_bd(ar, fallback_boardname, data, len); |
---|
1421 | | - |
---|
1422 | | - if (ret == -ENOENT) { |
---|
1423 | | - ath10k_err(ar, |
---|
1424 | | - "failed to fetch board data for %s from %s/%s\n", |
---|
1425 | | - boardname, ar->hw_params.fw.dir, filename); |
---|
1426 | | - ret = -ENODATA; |
---|
1427 | | - } |
---|
1428 | | - |
---|
1429 | | - if (ret) |
---|
1430 | | - goto err; |
---|
1431 | | - |
---|
1432 | | - return 0; |
---|
1433 | | - |
---|
1434 | | -err: |
---|
1435 | | - ath10k_core_free_board_files(ar); |
---|
1436 | | - return ret; |
---|
1437 | | -} |
---|
1438 | | - |
---|
1439 | | -static int ath10k_core_create_board_name(struct ath10k *ar, char *name, |
---|
1440 | | - size_t name_len, bool with_variant) |
---|
1441 | | -{ |
---|
1442 | | - /* strlen(',variant=') + strlen(ar->id.bdf_ext) */ |
---|
1443 | | - char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH] = { 0 }; |
---|
1444 | | - |
---|
1445 | | - if (with_variant && ar->id.bdf_ext[0] != '\0') |
---|
1446 | | - scnprintf(variant, sizeof(variant), ",variant=%s", |
---|
1447 | | - ar->id.bdf_ext); |
---|
1448 | | - |
---|
1449 | | - if (ar->id.bmi_ids_valid) { |
---|
1450 | | - scnprintf(name, name_len, |
---|
1451 | | - "bus=%s,bmi-chip-id=%d,bmi-board-id=%d%s", |
---|
1452 | | - ath10k_bus_str(ar->hif.bus), |
---|
1453 | | - ar->id.bmi_chip_id, |
---|
1454 | | - ar->id.bmi_board_id, variant); |
---|
1455 | | - goto out; |
---|
1456 | | - } |
---|
1457 | | - |
---|
1458 | | - scnprintf(name, name_len, |
---|
1459 | | - "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s", |
---|
1460 | | - ath10k_bus_str(ar->hif.bus), |
---|
1461 | | - ar->id.vendor, ar->id.device, |
---|
1462 | | - ar->id.subsystem_vendor, ar->id.subsystem_device, variant); |
---|
1463 | | -out: |
---|
1464 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name); |
---|
1465 | | - |
---|
1466 | | - return 0; |
---|
1467 | | -} |
---|
1468 | | - |
---|
1469 | | -static int ath10k_core_fetch_board_file(struct ath10k *ar) |
---|
1470 | | -{ |
---|
1471 | | - char boardname[100], fallback_boardname[100]; |
---|
1472 | | - int ret; |
---|
1473 | | - |
---|
1474 | | - ret = ath10k_core_create_board_name(ar, boardname, |
---|
1475 | | - sizeof(boardname), true); |
---|
1476 | | - if (ret) { |
---|
1477 | | - ath10k_err(ar, "failed to create board name: %d", ret); |
---|
1478 | | - return ret; |
---|
1479 | | - } |
---|
1480 | | - |
---|
1481 | | - ret = ath10k_core_create_board_name(ar, fallback_boardname, |
---|
1482 | | - sizeof(boardname), false); |
---|
1483 | | - if (ret) { |
---|
1484 | | - ath10k_err(ar, "failed to create fallback board name: %d", ret); |
---|
1485 | | - return ret; |
---|
1486 | | - } |
---|
1487 | | - |
---|
1488 | | - ar->bd_api = 2; |
---|
1489 | | - ret = ath10k_core_fetch_board_data_api_n(ar, boardname, |
---|
1490 | | - fallback_boardname, |
---|
1491 | | - ATH10K_BOARD_API2_FILE); |
---|
1492 | | - if (!ret) |
---|
1493 | | - goto success; |
---|
1494 | | - |
---|
1495 | | - ar->bd_api = 1; |
---|
1496 | | - ret = ath10k_core_fetch_board_data_api_1(ar); |
---|
1497 | | - if (ret) { |
---|
1498 | | - ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n", |
---|
1499 | | - ar->hw_params.fw.dir); |
---|
1500 | | - return ret; |
---|
1501 | | - } |
---|
1502 | | - |
---|
1503 | | -success: |
---|
1504 | | - ath10k_dbg(ar, ATH10K_DBG_BOOT, "using board api %d\n", ar->bd_api); |
---|
1505 | | - return 0; |
---|
1506 | 1833 | } |
---|
1507 | 1834 | |
---|
1508 | 1835 | int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, |
---|
.. | .. |
---|
1849 | 2176 | return 0; |
---|
1850 | 2177 | } |
---|
1851 | 2178 | |
---|
| 2179 | +static void ath10k_core_fetch_btcoex_dt(struct ath10k *ar) |
---|
| 2180 | +{ |
---|
| 2181 | + struct device_node *node; |
---|
| 2182 | + u8 coex_support = 0; |
---|
| 2183 | + int ret; |
---|
| 2184 | + |
---|
| 2185 | + node = ar->dev->of_node; |
---|
| 2186 | + if (!node) |
---|
| 2187 | + goto out; |
---|
| 2188 | + |
---|
| 2189 | + ret = of_property_read_u8(node, "qcom,coexist-support", &coex_support); |
---|
| 2190 | + if (ret) { |
---|
| 2191 | + ar->coex_support = true; |
---|
| 2192 | + goto out; |
---|
| 2193 | + } |
---|
| 2194 | + |
---|
| 2195 | + if (coex_support) { |
---|
| 2196 | + ar->coex_support = true; |
---|
| 2197 | + } else { |
---|
| 2198 | + ar->coex_support = false; |
---|
| 2199 | + ar->coex_gpio_pin = -1; |
---|
| 2200 | + goto out; |
---|
| 2201 | + } |
---|
| 2202 | + |
---|
| 2203 | + ret = of_property_read_u32(node, "qcom,coexist-gpio-pin", |
---|
| 2204 | + &ar->coex_gpio_pin); |
---|
| 2205 | + if (ret) |
---|
| 2206 | + ar->coex_gpio_pin = -1; |
---|
| 2207 | + |
---|
| 2208 | +out: |
---|
| 2209 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot coex_support %d coex_gpio_pin %d\n", |
---|
| 2210 | + ar->coex_support, ar->coex_gpio_pin); |
---|
| 2211 | +} |
---|
| 2212 | + |
---|
1852 | 2213 | static int ath10k_init_uart(struct ath10k *ar) |
---|
1853 | 2214 | { |
---|
1854 | 2215 | int ret; |
---|
.. | .. |
---|
1863 | 2224 | return ret; |
---|
1864 | 2225 | } |
---|
1865 | 2226 | |
---|
1866 | | - if (!uart_print) |
---|
| 2227 | + if (!uart_print) { |
---|
| 2228 | + if (ar->hw_params.uart_pin_workaround) { |
---|
| 2229 | + ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, |
---|
| 2230 | + ar->hw_params.uart_pin); |
---|
| 2231 | + if (ret) { |
---|
| 2232 | + ath10k_warn(ar, "failed to set UART TX pin: %d", |
---|
| 2233 | + ret); |
---|
| 2234 | + return ret; |
---|
| 2235 | + } |
---|
| 2236 | + } |
---|
| 2237 | + |
---|
1867 | 2238 | return 0; |
---|
| 2239 | + } |
---|
1868 | 2240 | |
---|
1869 | 2241 | ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin); |
---|
1870 | 2242 | if (ret) { |
---|
.. | .. |
---|
1891 | 2263 | |
---|
1892 | 2264 | static int ath10k_init_hw_params(struct ath10k *ar) |
---|
1893 | 2265 | { |
---|
1894 | | - const struct ath10k_hw_params *uninitialized_var(hw_params); |
---|
| 2266 | + const struct ath10k_hw_params *hw_params; |
---|
1895 | 2267 | int i; |
---|
1896 | 2268 | |
---|
1897 | 2269 | for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) { |
---|
1898 | 2270 | hw_params = &ath10k_hw_params_list[i]; |
---|
1899 | 2271 | |
---|
1900 | | - if (hw_params->id == ar->target_version && |
---|
| 2272 | + if (hw_params->bus == ar->hif.bus && |
---|
| 2273 | + hw_params->id == ar->target_version && |
---|
1901 | 2274 | hw_params->dev_id == ar->dev_id) |
---|
1902 | 2275 | break; |
---|
1903 | 2276 | } |
---|
.. | .. |
---|
1936 | 2309 | complete(&ar->offchan_tx_completed); |
---|
1937 | 2310 | complete(&ar->install_key_done); |
---|
1938 | 2311 | complete(&ar->vdev_setup_done); |
---|
| 2312 | + complete(&ar->vdev_delete_done); |
---|
1939 | 2313 | complete(&ar->thermal.wmi_sync); |
---|
1940 | 2314 | complete(&ar->bss_survey_done); |
---|
1941 | 2315 | wake_up(&ar->htt.empty_tx_wq); |
---|
.. | .. |
---|
1969 | 2343 | break; |
---|
1970 | 2344 | case ATH10K_STATE_RESTARTED: |
---|
1971 | 2345 | ar->state = ATH10K_STATE_WEDGED; |
---|
1972 | | - /* fall through */ |
---|
| 2346 | + fallthrough; |
---|
1973 | 2347 | case ATH10K_STATE_WEDGED: |
---|
1974 | 2348 | ath10k_warn(ar, "device is wedged, will not restart\n"); |
---|
1975 | 2349 | break; |
---|
.. | .. |
---|
1984 | 2358 | if (ret) |
---|
1985 | 2359 | ath10k_warn(ar, "failed to send firmware crash dump via devcoredump: %d", |
---|
1986 | 2360 | ret); |
---|
| 2361 | + |
---|
| 2362 | + complete(&ar->driver_recovery); |
---|
1987 | 2363 | } |
---|
1988 | 2364 | |
---|
1989 | 2365 | static void ath10k_core_set_coverage_class_work(struct work_struct *work) |
---|
.. | .. |
---|
1998 | 2374 | static int ath10k_core_init_firmware_features(struct ath10k *ar) |
---|
1999 | 2375 | { |
---|
2000 | 2376 | struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file; |
---|
| 2377 | + int max_num_peers; |
---|
2001 | 2378 | |
---|
2002 | 2379 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, fw_file->fw_features) && |
---|
2003 | 2380 | !test_bit(ATH10K_FW_FEATURE_WMI_10X, fw_file->fw_features)) { |
---|
.. | .. |
---|
2077 | 2454 | |
---|
2078 | 2455 | switch (fw_file->wmi_op_version) { |
---|
2079 | 2456 | case ATH10K_FW_WMI_OP_VERSION_MAIN: |
---|
2080 | | - ar->max_num_peers = TARGET_NUM_PEERS; |
---|
| 2457 | + max_num_peers = TARGET_NUM_PEERS; |
---|
2081 | 2458 | ar->max_num_stations = TARGET_NUM_STATIONS; |
---|
2082 | 2459 | ar->max_num_vdevs = TARGET_NUM_VDEVS; |
---|
2083 | 2460 | ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC; |
---|
.. | .. |
---|
2089 | 2466 | case ATH10K_FW_WMI_OP_VERSION_10_2: |
---|
2090 | 2467 | case ATH10K_FW_WMI_OP_VERSION_10_2_4: |
---|
2091 | 2468 | if (ath10k_peer_stats_enabled(ar)) { |
---|
2092 | | - ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS; |
---|
| 2469 | + max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS; |
---|
2093 | 2470 | ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS; |
---|
2094 | 2471 | } else { |
---|
2095 | | - ar->max_num_peers = TARGET_10X_NUM_PEERS; |
---|
| 2472 | + max_num_peers = TARGET_10X_NUM_PEERS; |
---|
2096 | 2473 | ar->max_num_stations = TARGET_10X_NUM_STATIONS; |
---|
2097 | 2474 | } |
---|
2098 | 2475 | ar->max_num_vdevs = TARGET_10X_NUM_VDEVS; |
---|
.. | .. |
---|
2101 | 2478 | ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM; |
---|
2102 | 2479 | break; |
---|
2103 | 2480 | case ATH10K_FW_WMI_OP_VERSION_TLV: |
---|
2104 | | - ar->max_num_peers = TARGET_TLV_NUM_PEERS; |
---|
| 2481 | + max_num_peers = TARGET_TLV_NUM_PEERS; |
---|
2105 | 2482 | ar->max_num_stations = TARGET_TLV_NUM_STATIONS; |
---|
2106 | 2483 | ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS; |
---|
2107 | 2484 | ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS; |
---|
2108 | | - ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; |
---|
| 2485 | + if (ar->hif.bus == ATH10K_BUS_SDIO) |
---|
| 2486 | + ar->htt.max_num_pending_tx = |
---|
| 2487 | + TARGET_TLV_NUM_MSDU_DESC_HL; |
---|
| 2488 | + else |
---|
| 2489 | + ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; |
---|
2109 | 2490 | ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS; |
---|
2110 | | - ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV | |
---|
2111 | | - WMI_STAT_PEER; |
---|
| 2491 | + ar->fw_stats_req_mask = WMI_TLV_STAT_PDEV | WMI_TLV_STAT_VDEV | |
---|
| 2492 | + WMI_TLV_STAT_PEER | WMI_TLV_STAT_PEER_EXTD; |
---|
2112 | 2493 | ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM; |
---|
2113 | 2494 | ar->wmi.mgmt_max_num_pending_tx = TARGET_TLV_MGMT_NUM_MSDU_DESC; |
---|
2114 | 2495 | break; |
---|
2115 | 2496 | case ATH10K_FW_WMI_OP_VERSION_10_4: |
---|
2116 | | - ar->max_num_peers = TARGET_10_4_NUM_PEERS; |
---|
| 2497 | + max_num_peers = TARGET_10_4_NUM_PEERS; |
---|
2117 | 2498 | ar->max_num_stations = TARGET_10_4_NUM_STATIONS; |
---|
2118 | 2499 | ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS; |
---|
2119 | 2500 | ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; |
---|
.. | .. |
---|
2132 | 2513 | break; |
---|
2133 | 2514 | case ATH10K_FW_WMI_OP_VERSION_UNSET: |
---|
2134 | 2515 | case ATH10K_FW_WMI_OP_VERSION_MAX: |
---|
| 2516 | + default: |
---|
2135 | 2517 | WARN_ON(1); |
---|
2136 | 2518 | return -EINVAL; |
---|
2137 | 2519 | } |
---|
| 2520 | + |
---|
| 2521 | + if (ar->hw_params.num_peers) |
---|
| 2522 | + ar->max_num_peers = ar->hw_params.num_peers; |
---|
| 2523 | + else |
---|
| 2524 | + ar->max_num_peers = max_num_peers; |
---|
2138 | 2525 | |
---|
2139 | 2526 | /* Backwards compatibility for firmwares without |
---|
2140 | 2527 | * ATH10K_FW_IE_HTT_OP_VERSION. |
---|
.. | .. |
---|
2212 | 2599 | return 0; |
---|
2213 | 2600 | } |
---|
2214 | 2601 | |
---|
| 2602 | +static int ath10k_core_compat_services(struct ath10k *ar) |
---|
| 2603 | +{ |
---|
| 2604 | + struct ath10k_fw_file *fw_file = &ar->normal_mode_fw.fw_file; |
---|
| 2605 | + |
---|
| 2606 | + /* all 10.x firmware versions support thermal throttling but don't |
---|
| 2607 | + * advertise the support via service flags so we have to hardcode |
---|
| 2608 | + * it here |
---|
| 2609 | + */ |
---|
| 2610 | + switch (fw_file->wmi_op_version) { |
---|
| 2611 | + case ATH10K_FW_WMI_OP_VERSION_10_1: |
---|
| 2612 | + case ATH10K_FW_WMI_OP_VERSION_10_2: |
---|
| 2613 | + case ATH10K_FW_WMI_OP_VERSION_10_2_4: |
---|
| 2614 | + case ATH10K_FW_WMI_OP_VERSION_10_4: |
---|
| 2615 | + set_bit(WMI_SERVICE_THERM_THROT, ar->wmi.svc_map); |
---|
| 2616 | + break; |
---|
| 2617 | + default: |
---|
| 2618 | + break; |
---|
| 2619 | + } |
---|
| 2620 | + |
---|
| 2621 | + return 0; |
---|
| 2622 | +} |
---|
| 2623 | + |
---|
2215 | 2624 | int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, |
---|
2216 | 2625 | const struct ath10k_fw_components *fw) |
---|
2217 | 2626 | { |
---|
.. | .. |
---|
2227 | 2636 | if (!test_bit(ATH10K_FW_FEATURE_NON_BMI, |
---|
2228 | 2637 | ar->running_fw->fw_file.fw_features)) { |
---|
2229 | 2638 | ath10k_bmi_start(ar); |
---|
| 2639 | + |
---|
| 2640 | + /* Enable hardware clock to speed up firmware download */ |
---|
| 2641 | + if (ar->hw_params.hw_ops->enable_pll_clk) { |
---|
| 2642 | + status = ar->hw_params.hw_ops->enable_pll_clk(ar); |
---|
| 2643 | + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot enable pll ret %d\n", |
---|
| 2644 | + status); |
---|
| 2645 | + } |
---|
2230 | 2646 | |
---|
2231 | 2647 | if (ath10k_init_configure_target(ar)) { |
---|
2232 | 2648 | status = -EINVAL; |
---|
.. | .. |
---|
2262 | 2678 | if (status) |
---|
2263 | 2679 | goto err; |
---|
2264 | 2680 | |
---|
2265 | | - if (ar->hif.bus == ATH10K_BUS_SDIO) |
---|
2266 | | - ath10k_init_sdio(ar); |
---|
| 2681 | + if (ar->hif.bus == ATH10K_BUS_SDIO) { |
---|
| 2682 | + status = ath10k_init_sdio(ar, mode); |
---|
| 2683 | + if (status) { |
---|
| 2684 | + ath10k_err(ar, "failed to init SDIO: %d\n", status); |
---|
| 2685 | + goto err; |
---|
| 2686 | + } |
---|
| 2687 | + } |
---|
2267 | 2688 | } |
---|
2268 | 2689 | |
---|
2269 | 2690 | ar->htc.htc_ops.target_send_suspend_complete = |
---|
.. | .. |
---|
2324 | 2745 | goto err_hif_stop; |
---|
2325 | 2746 | } |
---|
2326 | 2747 | |
---|
| 2748 | + status = ath10k_hif_start_post(ar); |
---|
| 2749 | + if (status) { |
---|
| 2750 | + ath10k_err(ar, "failed to swap mailbox: %d\n", status); |
---|
| 2751 | + goto err_hif_stop; |
---|
| 2752 | + } |
---|
| 2753 | + |
---|
2327 | 2754 | if (mode == ATH10K_FIRMWARE_MODE_NORMAL) { |
---|
2328 | 2755 | status = ath10k_htt_connect(&ar->htt); |
---|
2329 | 2756 | if (status) { |
---|
.. | .. |
---|
2367 | 2794 | if (test_bit(WMI_SERVICE_BSS_CHANNEL_INFO_64, ar->wmi.svc_map)) |
---|
2368 | 2795 | val |= WMI_10_4_BSS_CHANNEL_INFO_64; |
---|
2369 | 2796 | |
---|
| 2797 | + ath10k_core_fetch_btcoex_dt(ar); |
---|
| 2798 | + |
---|
2370 | 2799 | /* 10.4 firmware supports BT-Coex without reloading firmware |
---|
2371 | 2800 | * via pdev param. To support Bluetooth coexistence pdev param, |
---|
2372 | 2801 | * WMI_COEX_GPIO_SUPPORT of extended resource config should be |
---|
2373 | 2802 | * enabled always. |
---|
| 2803 | + * |
---|
| 2804 | + * We can still enable BTCOEX if firmware has the support |
---|
| 2805 | + * eventhough btceox_support value is |
---|
| 2806 | + * ATH10K_DT_BTCOEX_NOT_FOUND |
---|
2374 | 2807 | */ |
---|
| 2808 | + |
---|
2375 | 2809 | if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map) && |
---|
2376 | 2810 | test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM, |
---|
2377 | | - ar->running_fw->fw_file.fw_features)) |
---|
| 2811 | + ar->running_fw->fw_file.fw_features) && |
---|
| 2812 | + ar->coex_support) |
---|
2378 | 2813 | val |= WMI_10_4_COEX_GPIO_SUPPORT; |
---|
2379 | 2814 | |
---|
2380 | 2815 | if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, |
---|
.. | .. |
---|
2384 | 2819 | if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, |
---|
2385 | 2820 | ar->wmi.svc_map)) |
---|
2386 | 2821 | val |= WMI_10_4_TDLS_UAPSD_BUFFER_STA; |
---|
| 2822 | + |
---|
| 2823 | + if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, |
---|
| 2824 | + ar->wmi.svc_map)) |
---|
| 2825 | + val |= WMI_10_4_TX_DATA_ACK_RSSI; |
---|
| 2826 | + |
---|
| 2827 | + if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map)) |
---|
| 2828 | + val |= WMI_10_4_REPORT_AIRTIME; |
---|
| 2829 | + |
---|
| 2830 | + if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT, |
---|
| 2831 | + ar->wmi.svc_map)) |
---|
| 2832 | + val |= WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT; |
---|
2387 | 2833 | |
---|
2388 | 2834 | status = ath10k_mac_ext_resource_config(ar, val); |
---|
2389 | 2835 | if (status) { |
---|
.. | .. |
---|
2404 | 2850 | status = ath10k_wmi_wait_for_unified_ready(ar); |
---|
2405 | 2851 | if (status) { |
---|
2406 | 2852 | ath10k_err(ar, "wmi unified ready event not received\n"); |
---|
| 2853 | + goto err_hif_stop; |
---|
| 2854 | + } |
---|
| 2855 | + |
---|
| 2856 | + status = ath10k_core_compat_services(ar); |
---|
| 2857 | + if (status) { |
---|
| 2858 | + ath10k_err(ar, "compat services failed: %d\n", status); |
---|
| 2859 | + goto err_hif_stop; |
---|
| 2860 | + } |
---|
| 2861 | + |
---|
| 2862 | + status = ath10k_wmi_pdev_set_base_macaddr(ar, ar->mac_addr); |
---|
| 2863 | + if (status && status != -EOPNOTSUPP) { |
---|
| 2864 | + ath10k_err(ar, |
---|
| 2865 | + "failed to set base mac address: %d\n", status); |
---|
2407 | 2866 | goto err_hif_stop; |
---|
2408 | 2867 | } |
---|
2409 | 2868 | |
---|
.. | .. |
---|
2455 | 2914 | status = ath10k_debug_start(ar); |
---|
2456 | 2915 | if (status) |
---|
2457 | 2916 | goto err_hif_stop; |
---|
| 2917 | + |
---|
| 2918 | + status = ath10k_hif_set_target_log_mode(ar, fw_diag_log); |
---|
| 2919 | + if (status && status != -EOPNOTSUPP) { |
---|
| 2920 | + ath10k_warn(ar, "set target log mode failed: %d\n", status); |
---|
| 2921 | + goto err_hif_stop; |
---|
| 2922 | + } |
---|
2458 | 2923 | |
---|
2459 | 2924 | return 0; |
---|
2460 | 2925 | |
---|
.. | .. |
---|
2508 | 2973 | ath10k_htt_tx_stop(&ar->htt); |
---|
2509 | 2974 | ath10k_htt_rx_free(&ar->htt); |
---|
2510 | 2975 | ath10k_wmi_detach(ar); |
---|
| 2976 | + |
---|
| 2977 | + ar->id.bmi_ids_valid = false; |
---|
2511 | 2978 | } |
---|
2512 | 2979 | EXPORT_SYMBOL(ath10k_core_stop); |
---|
2513 | 2980 | |
---|
.. | .. |
---|
2521 | 2988 | struct bmi_target_info target_info; |
---|
2522 | 2989 | int ret = 0; |
---|
2523 | 2990 | |
---|
2524 | | - ret = ath10k_hif_power_up(ar); |
---|
| 2991 | + ret = ath10k_hif_power_up(ar, ATH10K_FIRMWARE_MODE_NORMAL); |
---|
2525 | 2992 | if (ret) { |
---|
2526 | 2993 | ath10k_err(ar, "could not power on hif bus (%d)\n", ret); |
---|
2527 | 2994 | return ret; |
---|
.. | .. |
---|
2609 | 3076 | if (ret) |
---|
2610 | 3077 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "DT bdf variant name not set.\n"); |
---|
2611 | 3078 | |
---|
2612 | | - ret = ath10k_core_fetch_board_file(ar); |
---|
| 3079 | + ret = ath10k_core_fetch_board_file(ar, ATH10K_BD_IE_BOARD); |
---|
2613 | 3080 | if (ret) { |
---|
2614 | 3081 | ath10k_err(ar, "failed to fetch board file: %d\n", ret); |
---|
2615 | 3082 | goto err_free_firmware_files; |
---|
.. | .. |
---|
2617 | 3084 | |
---|
2618 | 3085 | ath10k_debug_print_board_info(ar); |
---|
2619 | 3086 | } |
---|
| 3087 | + |
---|
| 3088 | + device_get_mac_address(ar->dev, ar->mac_addr, sizeof(ar->mac_addr)); |
---|
2620 | 3089 | |
---|
2621 | 3090 | ret = ath10k_core_init_firmware_features(ar); |
---|
2622 | 3091 | if (ret) { |
---|
.. | .. |
---|
2730 | 3199 | return; |
---|
2731 | 3200 | } |
---|
2732 | 3201 | |
---|
2733 | | -int ath10k_core_register(struct ath10k *ar, u32 chip_id) |
---|
| 3202 | +int ath10k_core_register(struct ath10k *ar, |
---|
| 3203 | + const struct ath10k_bus_params *bus_params) |
---|
2734 | 3204 | { |
---|
2735 | | - ar->chip_id = chip_id; |
---|
| 3205 | + ar->bus_param = *bus_params; |
---|
| 3206 | + |
---|
2736 | 3207 | queue_work(ar->workqueue, &ar->register_work); |
---|
2737 | 3208 | |
---|
2738 | 3209 | return 0; |
---|
.. | .. |
---|
2832 | 3303 | init_completion(&ar->scan.completed); |
---|
2833 | 3304 | init_completion(&ar->scan.on_channel); |
---|
2834 | 3305 | init_completion(&ar->target_suspend); |
---|
| 3306 | + init_completion(&ar->driver_recovery); |
---|
2835 | 3307 | init_completion(&ar->wow.wakeup_completed); |
---|
2836 | 3308 | |
---|
2837 | 3309 | init_completion(&ar->install_key_done); |
---|
2838 | 3310 | init_completion(&ar->vdev_setup_done); |
---|
| 3311 | + init_completion(&ar->vdev_delete_done); |
---|
2839 | 3312 | init_completion(&ar->thermal.wmi_sync); |
---|
2840 | 3313 | init_completion(&ar->bss_survey_done); |
---|
| 3314 | + init_completion(&ar->peer_delete_done); |
---|
| 3315 | + init_completion(&ar->peer_stats_info_complete); |
---|
2841 | 3316 | |
---|
2842 | 3317 | INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work); |
---|
2843 | 3318 | |
---|
.. | .. |
---|
2849 | 3324 | if (!ar->workqueue_aux) |
---|
2850 | 3325 | goto err_free_wq; |
---|
2851 | 3326 | |
---|
2852 | | - mutex_init(&ar->conf_mutex); |
---|
2853 | | - spin_lock_init(&ar->data_lock); |
---|
2854 | | - spin_lock_init(&ar->txqs_lock); |
---|
| 3327 | + ar->workqueue_tx_complete = |
---|
| 3328 | + create_singlethread_workqueue("ath10k_tx_complete_wq"); |
---|
| 3329 | + if (!ar->workqueue_tx_complete) |
---|
| 3330 | + goto err_free_aux_wq; |
---|
2855 | 3331 | |
---|
2856 | | - INIT_LIST_HEAD(&ar->txqs); |
---|
| 3332 | + mutex_init(&ar->conf_mutex); |
---|
| 3333 | + mutex_init(&ar->dump_mutex); |
---|
| 3334 | + spin_lock_init(&ar->data_lock); |
---|
| 3335 | + |
---|
2857 | 3336 | INIT_LIST_HEAD(&ar->peers); |
---|
2858 | 3337 | init_waitqueue_head(&ar->peer_mapping_wq); |
---|
2859 | 3338 | init_waitqueue_head(&ar->htt.empty_tx_wq); |
---|
2860 | 3339 | init_waitqueue_head(&ar->wmi.tx_credits_wq); |
---|
| 3340 | + |
---|
| 3341 | + skb_queue_head_init(&ar->htt.rx_indication_head); |
---|
2861 | 3342 | |
---|
2862 | 3343 | init_completion(&ar->offchan_tx_completed); |
---|
2863 | 3344 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); |
---|
.. | .. |
---|
2875 | 3356 | |
---|
2876 | 3357 | ret = ath10k_coredump_create(ar); |
---|
2877 | 3358 | if (ret) |
---|
2878 | | - goto err_free_aux_wq; |
---|
| 3359 | + goto err_free_tx_complete; |
---|
2879 | 3360 | |
---|
2880 | 3361 | ret = ath10k_debug_create(ar); |
---|
2881 | 3362 | if (ret) |
---|
.. | .. |
---|
2885 | 3366 | |
---|
2886 | 3367 | err_free_coredump: |
---|
2887 | 3368 | ath10k_coredump_destroy(ar); |
---|
2888 | | - |
---|
| 3369 | +err_free_tx_complete: |
---|
| 3370 | + destroy_workqueue(ar->workqueue_tx_complete); |
---|
2889 | 3371 | err_free_aux_wq: |
---|
2890 | 3372 | destroy_workqueue(ar->workqueue_aux); |
---|
2891 | 3373 | err_free_wq: |
---|
2892 | 3374 | destroy_workqueue(ar->workqueue); |
---|
2893 | | - |
---|
2894 | 3375 | err_free_mac: |
---|
2895 | 3376 | ath10k_mac_destroy(ar); |
---|
2896 | 3377 | |
---|
.. | .. |
---|
2906 | 3387 | flush_workqueue(ar->workqueue_aux); |
---|
2907 | 3388 | destroy_workqueue(ar->workqueue_aux); |
---|
2908 | 3389 | |
---|
| 3390 | + flush_workqueue(ar->workqueue_tx_complete); |
---|
| 3391 | + destroy_workqueue(ar->workqueue_tx_complete); |
---|
| 3392 | + |
---|
2909 | 3393 | ath10k_debug_destroy(ar); |
---|
2910 | 3394 | ath10k_coredump_destroy(ar); |
---|
2911 | 3395 | ath10k_htt_tx_destroy(&ar->htt); |
---|