Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath12k/core.c
48378 views
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
/*
3
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
4
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
5
*/
6
7
#if defined(__FreeBSD__)
8
#define LINUXKPI_PARAM_PREFIX ath12k_core_
9
#endif
10
11
#include <linux/module.h>
12
#include <linux/slab.h>
13
#include <linux/remoteproc.h>
14
#include <linux/firmware.h>
15
#include <linux/of.h>
16
#if defined(__FreeBSD__)
17
#include <linux/delay.h>
18
#endif
19
#include "core.h"
20
#include "dp_tx.h"
21
#include "dp_rx.h"
22
#include "debug.h"
23
#include "hif.h"
24
25
unsigned int ath12k_debug_mask;
26
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
27
MODULE_PARM_DESC(debug_mask, "Debugging mask");
28
29
int ath12k_core_suspend(struct ath12k_base *ab)
30
{
31
int ret;
32
33
if (!ab->hw_params->supports_suspend)
34
return -EOPNOTSUPP;
35
36
/* TODO: there can frames in queues so for now add delay as a hack.
37
* Need to implement to handle and remove this delay.
38
*/
39
#if defined(__linux__)
40
msleep(500);
41
#elif defined(__FreeBSD__)
42
linux_msleep(500);
43
#endif
44
45
ret = ath12k_dp_rx_pktlog_stop(ab, true);
46
if (ret) {
47
ath12k_warn(ab, "failed to stop dp rx (and timer) pktlog during suspend: %d\n",
48
ret);
49
return ret;
50
}
51
52
ret = ath12k_dp_rx_pktlog_stop(ab, false);
53
if (ret) {
54
ath12k_warn(ab, "failed to stop dp rx pktlog during suspend: %d\n",
55
ret);
56
return ret;
57
}
58
59
ath12k_hif_irq_disable(ab);
60
ath12k_hif_ce_irq_disable(ab);
61
62
ret = ath12k_hif_suspend(ab);
63
if (ret) {
64
ath12k_warn(ab, "failed to suspend hif: %d\n", ret);
65
return ret;
66
}
67
68
return 0;
69
}
70
71
int ath12k_core_resume(struct ath12k_base *ab)
72
{
73
int ret;
74
75
if (!ab->hw_params->supports_suspend)
76
return -EOPNOTSUPP;
77
78
ret = ath12k_hif_resume(ab);
79
if (ret) {
80
ath12k_warn(ab, "failed to resume hif during resume: %d\n", ret);
81
return ret;
82
}
83
84
ath12k_hif_ce_irq_enable(ab);
85
ath12k_hif_irq_enable(ab);
86
87
ret = ath12k_dp_rx_pktlog_start(ab);
88
if (ret) {
89
ath12k_warn(ab, "failed to start rx pktlog during resume: %d\n",
90
ret);
91
return ret;
92
}
93
94
return 0;
95
}
96
97
static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
98
size_t name_len)
99
{
100
/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
101
char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
102
103
if (ab->qmi.target.bdf_ext[0] != '\0')
104
scnprintf(variant, sizeof(variant), ",variant=%s",
105
ab->qmi.target.bdf_ext);
106
107
scnprintf(name, name_len,
108
"bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
109
ath12k_bus_str(ab->hif.bus),
110
ab->qmi.target.chip_id,
111
ab->qmi.target.board_id, variant);
112
113
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot using board name '%s'\n", name);
114
115
return 0;
116
}
117
118
const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab,
119
const char *file)
120
{
121
const struct firmware *fw;
122
char path[100];
123
int ret;
124
125
if (!file)
126
return ERR_PTR(-ENOENT);
127
128
ath12k_core_create_firmware_path(ab, file, path, sizeof(path));
129
130
ret = firmware_request_nowarn(&fw, path, ab->dev);
131
if (ret)
132
return ERR_PTR(ret);
133
134
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot firmware request %s size %zu\n",
135
path, fw->size);
136
137
return fw;
138
}
139
140
void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
141
{
142
if (!IS_ERR(bd->fw))
143
release_firmware(bd->fw);
144
145
memset(bd, 0, sizeof(*bd));
146
}
147
148
static int ath12k_core_parse_bd_ie_board(struct ath12k_base *ab,
149
struct ath12k_board_data *bd,
150
#if defined(__linux__)
151
const void *buf, size_t buf_len,
152
#elif defined(__FreeBSD__)
153
const u8 *buf, size_t buf_len,
154
#endif
155
const char *boardname,
156
int bd_ie_type)
157
{
158
const struct ath12k_fw_ie *hdr;
159
bool name_match_found;
160
int ret, board_ie_id;
161
size_t board_ie_len;
162
const void *board_ie_data;
163
164
name_match_found = false;
165
166
/* go through ATH12K_BD_IE_BOARD_ elements */
167
while (buf_len > sizeof(struct ath12k_fw_ie)) {
168
#if defined(__linux__)
169
hdr = buf;
170
#elif defined(__FreeBSD__)
171
hdr = (const struct ath12k_fw_ie *)buf;
172
#endif
173
board_ie_id = le32_to_cpu(hdr->id);
174
board_ie_len = le32_to_cpu(hdr->len);
175
board_ie_data = hdr->data;
176
177
buf_len -= sizeof(*hdr);
178
buf += sizeof(*hdr);
179
180
if (buf_len < ALIGN(board_ie_len, 4)) {
181
ath12k_err(ab, "invalid ATH12K_BD_IE_BOARD length: %zu < %zu\n",
182
buf_len, ALIGN(board_ie_len, 4));
183
ret = -EINVAL;
184
goto out;
185
}
186
187
switch (board_ie_id) {
188
case ATH12K_BD_IE_BOARD_NAME:
189
ath12k_dbg_dump(ab, ATH12K_DBG_BOOT, "board name", "",
190
board_ie_data, board_ie_len);
191
192
if (board_ie_len != strlen(boardname))
193
break;
194
195
ret = memcmp(board_ie_data, boardname, strlen(boardname));
196
if (ret)
197
break;
198
199
name_match_found = true;
200
ath12k_dbg(ab, ATH12K_DBG_BOOT,
201
"boot found match for name '%s'",
202
boardname);
203
break;
204
case ATH12K_BD_IE_BOARD_DATA:
205
if (!name_match_found)
206
/* no match found */
207
break;
208
209
ath12k_dbg(ab, ATH12K_DBG_BOOT,
210
"boot found board data for '%s'", boardname);
211
212
bd->data = board_ie_data;
213
bd->len = board_ie_len;
214
215
ret = 0;
216
goto out;
217
default:
218
ath12k_warn(ab, "unknown ATH12K_BD_IE_BOARD found: %d\n",
219
board_ie_id);
220
break;
221
}
222
223
/* jump over the padding */
224
board_ie_len = ALIGN(board_ie_len, 4);
225
226
buf_len -= board_ie_len;
227
buf += board_ie_len;
228
}
229
230
/* no match found */
231
ret = -ENOENT;
232
233
out:
234
return ret;
235
}
236
237
static int ath12k_core_fetch_board_data_api_n(struct ath12k_base *ab,
238
struct ath12k_board_data *bd,
239
const char *boardname)
240
{
241
size_t len, magic_len;
242
const u8 *data;
243
char *filename, filepath[100];
244
size_t ie_len;
245
#if defined(__linux__)
246
struct ath12k_fw_ie *hdr;
247
#elif defined(__FreeBSD__)
248
const struct ath12k_fw_ie *hdr;
249
#endif
250
int ret, ie_id;
251
252
filename = ATH12K_BOARD_API2_FILE;
253
254
if (!bd->fw)
255
bd->fw = ath12k_core_firmware_request(ab, filename);
256
257
if (IS_ERR(bd->fw))
258
return PTR_ERR(bd->fw);
259
260
data = bd->fw->data;
261
len = bd->fw->size;
262
263
ath12k_core_create_firmware_path(ab, filename,
264
filepath, sizeof(filepath));
265
266
/* magic has extra null byte padded */
267
magic_len = strlen(ATH12K_BOARD_MAGIC) + 1;
268
if (len < magic_len) {
269
ath12k_err(ab, "failed to find magic value in %s, file too short: %zu\n",
270
filepath, len);
271
ret = -EINVAL;
272
goto err;
273
}
274
275
if (memcmp(data, ATH12K_BOARD_MAGIC, magic_len)) {
276
ath12k_err(ab, "found invalid board magic\n");
277
ret = -EINVAL;
278
goto err;
279
}
280
281
/* magic is padded to 4 bytes */
282
magic_len = ALIGN(magic_len, 4);
283
if (len < magic_len) {
284
ath12k_err(ab, "failed: %s too small to contain board data, len: %zu\n",
285
filepath, len);
286
ret = -EINVAL;
287
goto err;
288
}
289
290
data += magic_len;
291
len -= magic_len;
292
293
while (len > sizeof(struct ath12k_fw_ie)) {
294
#if defined(__linux__)
295
hdr = (struct ath12k_fw_ie *)data;
296
#elif defined(__FreeBSD__)
297
hdr = (const struct ath12k_fw_ie *)data;
298
#endif
299
ie_id = le32_to_cpu(hdr->id);
300
ie_len = le32_to_cpu(hdr->len);
301
302
len -= sizeof(*hdr);
303
data = hdr->data;
304
305
if (len < ALIGN(ie_len, 4)) {
306
ath12k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",
307
ie_id, ie_len, len);
308
ret = -EINVAL;
309
goto err;
310
}
311
312
switch (ie_id) {
313
case ATH12K_BD_IE_BOARD:
314
ret = ath12k_core_parse_bd_ie_board(ab, bd, data,
315
ie_len,
316
boardname,
317
ATH12K_BD_IE_BOARD);
318
if (ret == -ENOENT)
319
/* no match found, continue */
320
break;
321
else if (ret)
322
/* there was an error, bail out */
323
goto err;
324
/* either found or error, so stop searching */
325
goto out;
326
}
327
328
/* jump over the padding */
329
ie_len = ALIGN(ie_len, 4);
330
331
len -= ie_len;
332
data += ie_len;
333
}
334
335
out:
336
if (!bd->data || !bd->len) {
337
ath12k_err(ab,
338
"failed to fetch board data for %s from %s\n",
339
boardname, filepath);
340
ret = -ENODATA;
341
goto err;
342
}
343
344
return 0;
345
346
err:
347
ath12k_core_free_bdf(ab, bd);
348
return ret;
349
}
350
351
int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
352
struct ath12k_board_data *bd,
353
char *filename)
354
{
355
bd->fw = ath12k_core_firmware_request(ab, filename);
356
if (IS_ERR(bd->fw))
357
return PTR_ERR(bd->fw);
358
359
bd->data = bd->fw->data;
360
bd->len = bd->fw->size;
361
362
return 0;
363
}
364
365
#define BOARD_NAME_SIZE 100
366
int ath12k_core_fetch_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
367
{
368
char boardname[BOARD_NAME_SIZE];
369
int ret;
370
371
ret = ath12k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
372
if (ret) {
373
ath12k_err(ab, "failed to create board name: %d", ret);
374
return ret;
375
}
376
377
ab->bd_api = 2;
378
ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname);
379
if (!ret)
380
goto success;
381
382
ab->bd_api = 1;
383
ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_DEFAULT_BOARD_FILE);
384
if (ret) {
385
ath12k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n",
386
ab->hw_params->fw.dir);
387
return ret;
388
}
389
390
success:
391
ath12k_dbg(ab, ATH12K_DBG_BOOT, "using board api %d\n", ab->bd_api);
392
return 0;
393
}
394
395
static void ath12k_core_stop(struct ath12k_base *ab)
396
{
397
if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
398
ath12k_qmi_firmware_stop(ab);
399
400
ath12k_hif_stop(ab);
401
ath12k_wmi_detach(ab);
402
ath12k_dp_rx_pdev_reo_cleanup(ab);
403
404
/* De-Init of components as needed */
405
}
406
407
static int ath12k_core_soc_create(struct ath12k_base *ab)
408
{
409
int ret;
410
411
ret = ath12k_qmi_init_service(ab);
412
if (ret) {
413
ath12k_err(ab, "failed to initialize qmi :%d\n", ret);
414
return ret;
415
}
416
417
ret = ath12k_hif_power_up(ab);
418
if (ret) {
419
ath12k_err(ab, "failed to power up :%d\n", ret);
420
goto err_qmi_deinit;
421
}
422
423
return 0;
424
425
err_qmi_deinit:
426
ath12k_qmi_deinit_service(ab);
427
return ret;
428
}
429
430
static void ath12k_core_soc_destroy(struct ath12k_base *ab)
431
{
432
ath12k_dp_free(ab);
433
ath12k_reg_free(ab);
434
ath12k_qmi_deinit_service(ab);
435
}
436
437
static int ath12k_core_pdev_create(struct ath12k_base *ab)
438
{
439
int ret;
440
441
ret = ath12k_mac_register(ab);
442
if (ret) {
443
ath12k_err(ab, "failed register the radio with mac80211: %d\n", ret);
444
return ret;
445
}
446
447
ret = ath12k_dp_pdev_alloc(ab);
448
if (ret) {
449
ath12k_err(ab, "failed to attach DP pdev: %d\n", ret);
450
goto err_mac_unregister;
451
}
452
453
return 0;
454
455
err_mac_unregister:
456
ath12k_mac_unregister(ab);
457
458
return ret;
459
}
460
461
static void ath12k_core_pdev_destroy(struct ath12k_base *ab)
462
{
463
ath12k_mac_unregister(ab);
464
ath12k_hif_irq_disable(ab);
465
ath12k_dp_pdev_free(ab);
466
}
467
468
static int ath12k_core_start(struct ath12k_base *ab,
469
enum ath12k_firmware_mode mode)
470
{
471
int ret;
472
473
ret = ath12k_wmi_attach(ab);
474
if (ret) {
475
ath12k_err(ab, "failed to attach wmi: %d\n", ret);
476
return ret;
477
}
478
479
ret = ath12k_htc_init(ab);
480
if (ret) {
481
ath12k_err(ab, "failed to init htc: %d\n", ret);
482
goto err_wmi_detach;
483
}
484
485
ret = ath12k_hif_start(ab);
486
if (ret) {
487
ath12k_err(ab, "failed to start HIF: %d\n", ret);
488
goto err_wmi_detach;
489
}
490
491
ret = ath12k_htc_wait_target(&ab->htc);
492
if (ret) {
493
ath12k_err(ab, "failed to connect to HTC: %d\n", ret);
494
goto err_hif_stop;
495
}
496
497
ret = ath12k_dp_htt_connect(&ab->dp);
498
if (ret) {
499
ath12k_err(ab, "failed to connect to HTT: %d\n", ret);
500
goto err_hif_stop;
501
}
502
503
ret = ath12k_wmi_connect(ab);
504
if (ret) {
505
ath12k_err(ab, "failed to connect wmi: %d\n", ret);
506
goto err_hif_stop;
507
}
508
509
ret = ath12k_htc_start(&ab->htc);
510
if (ret) {
511
ath12k_err(ab, "failed to start HTC: %d\n", ret);
512
goto err_hif_stop;
513
}
514
515
ret = ath12k_wmi_wait_for_service_ready(ab);
516
if (ret) {
517
ath12k_err(ab, "failed to receive wmi service ready event: %d\n",
518
ret);
519
goto err_hif_stop;
520
}
521
522
ret = ath12k_mac_allocate(ab);
523
if (ret) {
524
ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n",
525
ret);
526
goto err_hif_stop;
527
}
528
529
ath12k_dp_cc_config(ab);
530
531
ath12k_dp_pdev_pre_alloc(ab);
532
533
ret = ath12k_dp_rx_pdev_reo_setup(ab);
534
if (ret) {
535
ath12k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
536
goto err_mac_destroy;
537
}
538
539
ret = ath12k_wmi_cmd_init(ab);
540
if (ret) {
541
ath12k_err(ab, "failed to send wmi init cmd: %d\n", ret);
542
goto err_reo_cleanup;
543
}
544
545
ret = ath12k_wmi_wait_for_unified_ready(ab);
546
if (ret) {
547
ath12k_err(ab, "failed to receive wmi unified ready event: %d\n",
548
ret);
549
goto err_reo_cleanup;
550
}
551
552
/* put hardware to DBS mode */
553
if (ab->hw_params->single_pdev_only) {
554
ret = ath12k_wmi_set_hw_mode(ab, WMI_HOST_HW_MODE_DBS);
555
if (ret) {
556
ath12k_err(ab, "failed to send dbs mode: %d\n", ret);
557
goto err_reo_cleanup;
558
}
559
}
560
561
ret = ath12k_dp_tx_htt_h2t_ver_req_msg(ab);
562
if (ret) {
563
ath12k_err(ab, "failed to send htt version request message: %d\n",
564
ret);
565
goto err_reo_cleanup;
566
}
567
568
return 0;
569
570
err_reo_cleanup:
571
ath12k_dp_rx_pdev_reo_cleanup(ab);
572
err_mac_destroy:
573
ath12k_mac_destroy(ab);
574
err_hif_stop:
575
ath12k_hif_stop(ab);
576
err_wmi_detach:
577
ath12k_wmi_detach(ab);
578
return ret;
579
}
580
581
static int ath12k_core_start_firmware(struct ath12k_base *ab,
582
enum ath12k_firmware_mode mode)
583
{
584
int ret;
585
586
ath12k_ce_get_shadow_config(ab, &ab->qmi.ce_cfg.shadow_reg_v3,
587
&ab->qmi.ce_cfg.shadow_reg_v3_len);
588
589
ret = ath12k_qmi_firmware_start(ab, mode);
590
if (ret) {
591
ath12k_err(ab, "failed to send firmware start: %d\n", ret);
592
return ret;
593
}
594
595
return ret;
596
}
597
598
int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
599
{
600
int ret;
601
602
ret = ath12k_core_start_firmware(ab, ATH12K_FIRMWARE_MODE_NORMAL);
603
if (ret) {
604
ath12k_err(ab, "failed to start firmware: %d\n", ret);
605
return ret;
606
}
607
608
ret = ath12k_ce_init_pipes(ab);
609
if (ret) {
610
ath12k_err(ab, "failed to initialize CE: %d\n", ret);
611
goto err_firmware_stop;
612
}
613
614
ret = ath12k_dp_alloc(ab);
615
if (ret) {
616
ath12k_err(ab, "failed to init DP: %d\n", ret);
617
goto err_firmware_stop;
618
}
619
620
mutex_lock(&ab->core_lock);
621
ret = ath12k_core_start(ab, ATH12K_FIRMWARE_MODE_NORMAL);
622
if (ret) {
623
ath12k_err(ab, "failed to start core: %d\n", ret);
624
goto err_dp_free;
625
}
626
627
ret = ath12k_core_pdev_create(ab);
628
if (ret) {
629
ath12k_err(ab, "failed to create pdev core: %d\n", ret);
630
goto err_core_stop;
631
}
632
ath12k_hif_irq_enable(ab);
633
mutex_unlock(&ab->core_lock);
634
635
return 0;
636
637
err_core_stop:
638
ath12k_core_stop(ab);
639
ath12k_mac_destroy(ab);
640
err_dp_free:
641
ath12k_dp_free(ab);
642
mutex_unlock(&ab->core_lock);
643
err_firmware_stop:
644
ath12k_qmi_firmware_stop(ab);
645
646
return ret;
647
}
648
649
static int ath12k_core_reconfigure_on_crash(struct ath12k_base *ab)
650
{
651
int ret;
652
653
mutex_lock(&ab->core_lock);
654
ath12k_hif_irq_disable(ab);
655
ath12k_dp_pdev_free(ab);
656
ath12k_hif_stop(ab);
657
ath12k_wmi_detach(ab);
658
ath12k_dp_rx_pdev_reo_cleanup(ab);
659
mutex_unlock(&ab->core_lock);
660
661
ath12k_dp_free(ab);
662
ath12k_hal_srng_deinit(ab);
663
664
ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
665
666
ret = ath12k_hal_srng_init(ab);
667
if (ret)
668
return ret;
669
670
clear_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags);
671
672
ret = ath12k_core_qmi_firmware_ready(ab);
673
if (ret)
674
goto err_hal_srng_deinit;
675
676
clear_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags);
677
678
return 0;
679
680
err_hal_srng_deinit:
681
ath12k_hal_srng_deinit(ab);
682
return ret;
683
}
684
685
void ath12k_core_halt(struct ath12k *ar)
686
{
687
struct ath12k_base *ab = ar->ab;
688
689
lockdep_assert_held(&ar->conf_mutex);
690
691
ar->num_created_vdevs = 0;
692
ar->allocated_vdev_map = 0;
693
694
ath12k_mac_scan_finish(ar);
695
ath12k_mac_peer_cleanup_all(ar);
696
cancel_delayed_work_sync(&ar->scan.timeout);
697
cancel_work_sync(&ar->regd_update_work);
698
699
rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
700
synchronize_rcu();
701
INIT_LIST_HEAD(&ar->arvifs);
702
idr_init(&ar->txmgmt_idr);
703
}
704
705
static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
706
{
707
struct ath12k *ar;
708
struct ath12k_pdev *pdev;
709
int i;
710
711
spin_lock_bh(&ab->base_lock);
712
ab->stats.fw_crash_counter++;
713
spin_unlock_bh(&ab->base_lock);
714
715
for (i = 0; i < ab->num_radios; i++) {
716
pdev = &ab->pdevs[i];
717
ar = pdev->ar;
718
if (!ar || ar->state == ATH12K_STATE_OFF)
719
continue;
720
721
ieee80211_stop_queues(ar->hw);
722
ath12k_mac_drain_tx(ar);
723
complete(&ar->scan.started);
724
complete(&ar->scan.completed);
725
complete(&ar->peer_assoc_done);
726
complete(&ar->peer_delete_done);
727
complete(&ar->install_key_done);
728
complete(&ar->vdev_setup_done);
729
complete(&ar->vdev_delete_done);
730
complete(&ar->bss_survey_done);
731
732
wake_up(&ar->dp.tx_empty_waitq);
733
idr_for_each(&ar->txmgmt_idr,
734
ath12k_mac_tx_mgmt_pending_free, ar);
735
idr_destroy(&ar->txmgmt_idr);
736
wake_up(&ar->txmgmt_empty_waitq);
737
}
738
739
wake_up(&ab->wmi_ab.tx_credits_wq);
740
wake_up(&ab->peer_mapping_wq);
741
}
742
743
static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
744
{
745
struct ath12k *ar;
746
struct ath12k_pdev *pdev;
747
int i;
748
749
for (i = 0; i < ab->num_radios; i++) {
750
pdev = &ab->pdevs[i];
751
ar = pdev->ar;
752
if (!ar || ar->state == ATH12K_STATE_OFF)
753
continue;
754
755
mutex_lock(&ar->conf_mutex);
756
757
switch (ar->state) {
758
case ATH12K_STATE_ON:
759
ar->state = ATH12K_STATE_RESTARTING;
760
ath12k_core_halt(ar);
761
ieee80211_restart_hw(ar->hw);
762
break;
763
case ATH12K_STATE_OFF:
764
ath12k_warn(ab,
765
"cannot restart radio %d that hasn't been started\n",
766
i);
767
break;
768
case ATH12K_STATE_RESTARTING:
769
break;
770
case ATH12K_STATE_RESTARTED:
771
ar->state = ATH12K_STATE_WEDGED;
772
fallthrough;
773
case ATH12K_STATE_WEDGED:
774
ath12k_warn(ab,
775
"device is wedged, will not restart radio %d\n", i);
776
break;
777
}
778
mutex_unlock(&ar->conf_mutex);
779
}
780
complete(&ab->driver_recovery);
781
}
782
783
static void ath12k_core_restart(struct work_struct *work)
784
{
785
struct ath12k_base *ab = container_of(work, struct ath12k_base, restart_work);
786
int ret;
787
788
if (!ab->is_reset)
789
ath12k_core_pre_reconfigure_recovery(ab);
790
791
ret = ath12k_core_reconfigure_on_crash(ab);
792
if (ret) {
793
ath12k_err(ab, "failed to reconfigure driver on crash recovery\n");
794
return;
795
}
796
797
if (ab->is_reset)
798
complete_all(&ab->reconfigure_complete);
799
800
if (!ab->is_reset)
801
ath12k_core_post_reconfigure_recovery(ab);
802
}
803
804
static void ath12k_core_reset(struct work_struct *work)
805
{
806
struct ath12k_base *ab = container_of(work, struct ath12k_base, reset_work);
807
int reset_count, fail_cont_count;
808
long time_left;
809
810
if (!(test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))) {
811
ath12k_warn(ab, "ignore reset dev flags 0x%lx\n", ab->dev_flags);
812
return;
813
}
814
815
/* Sometimes the recovery will fail and then the next all recovery fail,
816
* this is to avoid infinite recovery since it can not recovery success
817
*/
818
fail_cont_count = atomic_read(&ab->fail_cont_count);
819
820
if (fail_cont_count >= ATH12K_RESET_MAX_FAIL_COUNT_FINAL)
821
return;
822
823
if (fail_cont_count >= ATH12K_RESET_MAX_FAIL_COUNT_FIRST &&
824
time_before(jiffies, ab->reset_fail_timeout))
825
return;
826
827
reset_count = atomic_inc_return(&ab->reset_count);
828
829
if (reset_count > 1) {
830
/* Sometimes it happened another reset worker before the previous one
831
* completed, then the second reset worker will destroy the previous one,
832
* thus below is to avoid that.
833
*/
834
ath12k_warn(ab, "already resetting count %d\n", reset_count);
835
836
reinit_completion(&ab->reset_complete);
837
time_left = wait_for_completion_timeout(&ab->reset_complete,
838
ATH12K_RESET_TIMEOUT_HZ);
839
if (time_left) {
840
ath12k_dbg(ab, ATH12K_DBG_BOOT, "to skip reset\n");
841
atomic_dec(&ab->reset_count);
842
return;
843
}
844
845
ab->reset_fail_timeout = jiffies + ATH12K_RESET_FAIL_TIMEOUT_HZ;
846
/* Record the continuous recovery fail count when recovery failed*/
847
fail_cont_count = atomic_inc_return(&ab->fail_cont_count);
848
}
849
850
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset starting\n");
851
852
ab->is_reset = true;
853
atomic_set(&ab->recovery_count, 0);
854
855
ath12k_core_pre_reconfigure_recovery(ab);
856
857
reinit_completion(&ab->reconfigure_complete);
858
ath12k_core_post_reconfigure_recovery(ab);
859
860
reinit_completion(&ab->recovery_start);
861
atomic_set(&ab->recovery_start_count, 0);
862
863
ath12k_dbg(ab, ATH12K_DBG_BOOT, "waiting recovery start...\n");
864
865
time_left = wait_for_completion_timeout(&ab->recovery_start,
866
ATH12K_RECOVER_START_TIMEOUT_HZ);
867
868
ath12k_hif_power_down(ab);
869
ath12k_hif_power_up(ab);
870
871
ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset started\n");
872
}
873
874
int ath12k_core_pre_init(struct ath12k_base *ab)
875
{
876
int ret;
877
878
ret = ath12k_hw_init(ab);
879
if (ret) {
880
ath12k_err(ab, "failed to init hw params: %d\n", ret);
881
return ret;
882
}
883
884
return 0;
885
}
886
887
int ath12k_core_init(struct ath12k_base *ab)
888
{
889
int ret;
890
891
ret = ath12k_core_soc_create(ab);
892
if (ret) {
893
ath12k_err(ab, "failed to create soc core: %d\n", ret);
894
return ret;
895
}
896
897
return 0;
898
}
899
900
void ath12k_core_deinit(struct ath12k_base *ab)
901
{
902
mutex_lock(&ab->core_lock);
903
904
ath12k_core_pdev_destroy(ab);
905
ath12k_core_stop(ab);
906
907
mutex_unlock(&ab->core_lock);
908
909
ath12k_hif_power_down(ab);
910
ath12k_mac_destroy(ab);
911
ath12k_core_soc_destroy(ab);
912
}
913
914
void ath12k_core_free(struct ath12k_base *ab)
915
{
916
timer_delete_sync(&ab->rx_replenish_retry);
917
destroy_workqueue(ab->workqueue_aux);
918
destroy_workqueue(ab->workqueue);
919
kfree(ab);
920
}
921
922
struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
923
enum ath12k_bus bus)
924
{
925
struct ath12k_base *ab;
926
927
ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL);
928
if (!ab)
929
return NULL;
930
931
init_completion(&ab->driver_recovery);
932
933
ab->workqueue = create_singlethread_workqueue("ath12k_wq");
934
if (!ab->workqueue)
935
goto err_sc_free;
936
937
ab->workqueue_aux = create_singlethread_workqueue("ath12k_aux_wq");
938
if (!ab->workqueue_aux)
939
goto err_free_wq;
940
941
mutex_init(&ab->core_lock);
942
spin_lock_init(&ab->base_lock);
943
init_completion(&ab->reset_complete);
944
init_completion(&ab->reconfigure_complete);
945
init_completion(&ab->recovery_start);
946
947
INIT_LIST_HEAD(&ab->peers);
948
init_waitqueue_head(&ab->peer_mapping_wq);
949
init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
950
INIT_WORK(&ab->restart_work, ath12k_core_restart);
951
INIT_WORK(&ab->reset_work, ath12k_core_reset);
952
timer_setup(&ab->rx_replenish_retry, ath12k_ce_rx_replenish_retry, 0);
953
init_completion(&ab->htc_suspend);
954
955
ab->dev = dev;
956
ab->hif.bus = bus;
957
958
return ab;
959
960
err_free_wq:
961
destroy_workqueue(ab->workqueue);
962
err_sc_free:
963
kfree(ab);
964
return NULL;
965
}
966
967
MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11be wireless LAN cards.");
968
MODULE_LICENSE("Dual BSD/GPL");
969
970