Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
[linux-2.6-microblaze.git] / drivers / net / wireless / ath / ath11k / core.c
1 // SPDX-License-Identifier: BSD-3-Clause-Clear
2 /*
3  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4  */
5
6 #include <linux/module.h>
7 #include <linux/slab.h>
8 #include <linux/remoteproc.h>
9 #include <linux/firmware.h>
10 #include "core.h"
11 #include "dp_tx.h"
12 #include "dp_rx.h"
13 #include "debug.h"
14 #include "hif.h"
15
16 unsigned int ath11k_debug_mask;
17 module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
18 MODULE_PARM_DESC(debug_mask, "Debugging mask");
19
20 static const struct ath11k_hw_params ath11k_hw_params = {
21         .name = "ipq8074",
22         .fw = {
23                 .dir = IPQ8074_FW_DIR,
24                 .board_size = IPQ8074_MAX_BOARD_DATA_SZ,
25                 .cal_size =  IPQ8074_MAX_CAL_DATA_SZ,
26         },
27 };
28
29 /* Map from pdev index to hw mac index */
30 u8 ath11k_core_get_hw_mac_id(struct ath11k_base *ab, int pdev_idx)
31 {
32         switch (pdev_idx) {
33         case 0:
34                 return 0;
35         case 1:
36                 return 2;
37         case 2:
38                 return 1;
39         default:
40                 ath11k_warn(ab, "Invalid pdev idx %d\n", pdev_idx);
41                 return ATH11K_INVALID_HW_MAC_ID;
42         }
43 }
44 EXPORT_SYMBOL(ath11k_core_get_hw_mac_id);
45
46 static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
47                                          size_t name_len)
48 {
49         /* Note: bus is fixed to ahb. When other bus type supported,
50          * make it to dynamic.
51          */
52         scnprintf(name, name_len,
53                   "bus=ahb,qmi-chip-id=%d,qmi-board-id=%d",
54                   ab->qmi.target.chip_id,
55                   ab->qmi.target.board_id);
56
57         ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot using board name '%s'\n", name);
58
59         return 0;
60 }
61
62 static const struct firmware *ath11k_fetch_fw_file(struct ath11k_base *ab,
63                                                    const char *dir,
64                                                    const char *file)
65 {
66         char filename[100];
67         const struct firmware *fw;
68         int ret;
69
70         if (file == NULL)
71                 return ERR_PTR(-ENOENT);
72
73         if (dir == NULL)
74                 dir = ".";
75
76         snprintf(filename, sizeof(filename), "%s/%s", dir, file);
77         ret = firmware_request_nowarn(&fw, filename, ab->dev);
78         ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot fw request '%s': %d\n",
79                    filename, ret);
80
81         if (ret)
82                 return ERR_PTR(ret);
83         ath11k_warn(ab, "Downloading BDF: %s, size: %zu\n",
84                     filename, fw->size);
85
86         return fw;
87 }
88
89 void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
90 {
91         if (!IS_ERR(bd->fw))
92                 release_firmware(bd->fw);
93
94         memset(bd, 0, sizeof(*bd));
95 }
96
97 static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab,
98                                          struct ath11k_board_data *bd,
99                                          const void *buf, size_t buf_len,
100                                          const char *boardname,
101                                          int bd_ie_type)
102 {
103         const struct ath11k_fw_ie *hdr;
104         bool name_match_found;
105         int ret, board_ie_id;
106         size_t board_ie_len;
107         const void *board_ie_data;
108
109         name_match_found = false;
110
111         /* go through ATH11K_BD_IE_BOARD_ elements */
112         while (buf_len > sizeof(struct ath11k_fw_ie)) {
113                 hdr = buf;
114                 board_ie_id = le32_to_cpu(hdr->id);
115                 board_ie_len = le32_to_cpu(hdr->len);
116                 board_ie_data = hdr->data;
117
118                 buf_len -= sizeof(*hdr);
119                 buf += sizeof(*hdr);
120
121                 if (buf_len < ALIGN(board_ie_len, 4)) {
122                         ath11k_err(ab, "invalid ATH11K_BD_IE_BOARD length: %zu < %zu\n",
123                                    buf_len, ALIGN(board_ie_len, 4));
124                         ret = -EINVAL;
125                         goto out;
126                 }
127
128                 switch (board_ie_id) {
129                 case ATH11K_BD_IE_BOARD_NAME:
130                         ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "",
131                                         board_ie_data, board_ie_len);
132
133                         if (board_ie_len != strlen(boardname))
134                                 break;
135
136                         ret = memcmp(board_ie_data, boardname, strlen(boardname));
137                         if (ret)
138                                 break;
139
140                         name_match_found = true;
141                         ath11k_dbg(ab, ATH11K_DBG_BOOT,
142                                    "boot found match for name '%s'",
143                                    boardname);
144                         break;
145                 case ATH11K_BD_IE_BOARD_DATA:
146                         if (!name_match_found)
147                                 /* no match found */
148                                 break;
149
150                         ath11k_dbg(ab, ATH11K_DBG_BOOT,
151                                    "boot found board data for '%s'", boardname);
152
153                         bd->data = board_ie_data;
154                         bd->len = board_ie_len;
155
156                         ret = 0;
157                         goto out;
158                 default:
159                         ath11k_warn(ab, "unknown ATH11K_BD_IE_BOARD found: %d\n",
160                                     board_ie_id);
161                         break;
162                 }
163
164                 /* jump over the padding */
165                 board_ie_len = ALIGN(board_ie_len, 4);
166
167                 buf_len -= board_ie_len;
168                 buf += board_ie_len;
169         }
170
171         /* no match found */
172         ret = -ENOENT;
173
174 out:
175         return ret;
176 }
177
178 static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
179                                               struct ath11k_board_data *bd,
180                                               const char *boardname)
181 {
182         size_t len, magic_len;
183         const u8 *data;
184         char *filename = ATH11K_BOARD_API2_FILE;
185         size_t ie_len;
186         struct ath11k_fw_ie *hdr;
187         int ret, ie_id;
188
189         if (!bd->fw)
190                 bd->fw = ath11k_fetch_fw_file(ab,
191                                               ab->hw_params.fw.dir,
192                                               filename);
193         if (IS_ERR(bd->fw))
194                 return PTR_ERR(bd->fw);
195
196         data = bd->fw->data;
197         len = bd->fw->size;
198
199         /* magic has extra null byte padded */
200         magic_len = strlen(ATH11K_BOARD_MAGIC) + 1;
201         if (len < magic_len) {
202                 ath11k_err(ab, "failed to find magic value in %s/%s, file too short: %zu\n",
203                            ab->hw_params.fw.dir, filename, len);
204                 ret = -EINVAL;
205                 goto err;
206         }
207
208         if (memcmp(data, ATH11K_BOARD_MAGIC, magic_len)) {
209                 ath11k_err(ab, "found invalid board magic\n");
210                 ret = -EINVAL;
211                 goto err;
212         }
213
214         /* magic is padded to 4 bytes */
215         magic_len = ALIGN(magic_len, 4);
216         if (len < magic_len) {
217                 ath11k_err(ab, "failed: %s/%s too small to contain board data, len: %zu\n",
218                            ab->hw_params.fw.dir, filename, len);
219                 ret = -EINVAL;
220                 goto err;
221         }
222
223         data += magic_len;
224         len -= magic_len;
225
226         while (len > sizeof(struct ath11k_fw_ie)) {
227                 hdr = (struct ath11k_fw_ie *)data;
228                 ie_id = le32_to_cpu(hdr->id);
229                 ie_len = le32_to_cpu(hdr->len);
230
231                 len -= sizeof(*hdr);
232                 data = hdr->data;
233
234                 if (len < ALIGN(ie_len, 4)) {
235                         ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n",
236                                    ie_id, ie_len, len);
237                         return -EINVAL;
238                 }
239
240                 switch (ie_id) {
241                 case ATH11K_BD_IE_BOARD:
242                         ret = ath11k_core_parse_bd_ie_board(ab, bd, data,
243                                                             ie_len,
244                                                             boardname,
245                                                             ATH11K_BD_IE_BOARD);
246                         if (ret == -ENOENT)
247                                 /* no match found, continue */
248                                 break;
249                         else if (ret)
250                                 /* there was an error, bail out */
251                                 goto err;
252                         /* either found or error, so stop searching */
253                         goto out;
254                 }
255
256                 /* jump over the padding */
257                 ie_len = ALIGN(ie_len, 4);
258
259                 len -= ie_len;
260                 data += ie_len;
261         }
262
263 out:
264         if (!bd->data || !bd->len) {
265                 ath11k_err(ab,
266                            "failed to fetch board data for %s from %s/%s\n",
267                            boardname, ab->hw_params.fw.dir, filename);
268                 ret = -ENODATA;
269                 goto err;
270         }
271
272         return 0;
273
274 err:
275         ath11k_core_free_bdf(ab, bd);
276         return ret;
277 }
278
279 static int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
280                                               struct ath11k_board_data *bd)
281 {
282         bd->fw = ath11k_fetch_fw_file(ab,
283                                       ab->hw_params.fw.dir,
284                                       ATH11K_DEFAULT_BOARD_FILE);
285         if (IS_ERR(bd->fw))
286                 return PTR_ERR(bd->fw);
287
288         bd->data = bd->fw->data;
289         bd->len = bd->fw->size;
290
291         return 0;
292 }
293
294 #define BOARD_NAME_SIZE 100
295 int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd)
296 {
297         char boardname[BOARD_NAME_SIZE];
298         int ret;
299
300         ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
301         if (ret) {
302                 ath11k_err(ab, "failed to create board name: %d", ret);
303                 return ret;
304         }
305
306         ab->bd_api = 2;
307         ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname);
308         if (!ret)
309                 goto success;
310
311         ab->bd_api = 1;
312         ret = ath11k_core_fetch_board_data_api_1(ab, bd);
313         if (ret) {
314                 ath11k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n",
315                            ab->hw_params.fw.dir);
316                 return ret;
317         }
318
319 success:
320         ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api);
321         return 0;
322 }
323
324 static void ath11k_core_stop(struct ath11k_base *ab)
325 {
326         if (!test_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags))
327                 ath11k_qmi_firmware_stop(ab);
328         ath11k_hif_stop(ab);
329         ath11k_wmi_detach(ab);
330         ath11k_dp_pdev_reo_cleanup(ab);
331
332         /* De-Init of components as needed */
333 }
334
335 static int ath11k_core_soc_create(struct ath11k_base *ab)
336 {
337         int ret;
338
339         ret = ath11k_qmi_init_service(ab);
340         if (ret) {
341                 ath11k_err(ab, "failed to initialize qmi :%d\n", ret);
342                 return ret;
343         }
344
345         ret = ath11k_debug_soc_create(ab);
346         if (ret) {
347                 ath11k_err(ab, "failed to create ath11k debugfs\n");
348                 goto err_qmi_deinit;
349         }
350
351         ret = ath11k_hif_power_up(ab);
352         if (ret) {
353                 ath11k_err(ab, "failed to power up :%d\n", ret);
354                 goto err_debugfs_reg;
355         }
356
357         return 0;
358
359 err_debugfs_reg:
360         ath11k_debug_soc_destroy(ab);
361 err_qmi_deinit:
362         ath11k_qmi_deinit_service(ab);
363         return ret;
364 }
365
366 static void ath11k_core_soc_destroy(struct ath11k_base *ab)
367 {
368         ath11k_debug_soc_destroy(ab);
369         ath11k_dp_free(ab);
370         ath11k_reg_free(ab);
371         ath11k_qmi_deinit_service(ab);
372 }
373
374 static int ath11k_core_pdev_create(struct ath11k_base *ab)
375 {
376         int ret;
377
378         ret = ath11k_debug_pdev_create(ab);
379         if (ret) {
380                 ath11k_err(ab, "failed to create core pdev debugfs: %d\n", ret);
381                 return ret;
382         }
383
384         ret = ath11k_mac_register(ab);
385         if (ret) {
386                 ath11k_err(ab, "failed register the radio with mac80211: %d\n", ret);
387                 goto err_pdev_debug;
388         }
389
390         ret = ath11k_dp_pdev_alloc(ab);
391         if (ret) {
392                 ath11k_err(ab, "failed to attach DP pdev: %d\n", ret);
393                 goto err_mac_unregister;
394         }
395
396         ret = ath11k_thermal_register(ab);
397         if (ret) {
398                 ath11k_err(ab, "could not register thermal device: %d\n",
399                            ret);
400                 goto err_dp_pdev_free;
401         }
402
403         ret = ath11k_spectral_init(ab);
404         if (ret) {
405                 ath11k_err(ab, "failed to init spectral %d\n", ret);
406                 goto err_thermal_unregister;
407         }
408
409         return 0;
410
411 err_thermal_unregister:
412         ath11k_thermal_unregister(ab);
413 err_dp_pdev_free:
414         ath11k_dp_pdev_free(ab);
415 err_mac_unregister:
416         ath11k_mac_unregister(ab);
417 err_pdev_debug:
418         ath11k_debug_pdev_destroy(ab);
419
420         return ret;
421 }
422
423 static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
424 {
425         ath11k_spectral_deinit(ab);
426         ath11k_thermal_unregister(ab);
427         ath11k_mac_unregister(ab);
428         ath11k_hif_irq_disable(ab);
429         ath11k_dp_pdev_free(ab);
430         ath11k_debug_pdev_destroy(ab);
431 }
432
433 static int ath11k_core_start(struct ath11k_base *ab,
434                              enum ath11k_firmware_mode mode)
435 {
436         int ret;
437
438         ret = ath11k_qmi_firmware_start(ab, mode);
439         if (ret) {
440                 ath11k_err(ab, "failed to attach wmi: %d\n", ret);
441                 return ret;
442         }
443
444         ret = ath11k_wmi_attach(ab);
445         if (ret) {
446                 ath11k_err(ab, "failed to attach wmi: %d\n", ret);
447                 goto err_firmware_stop;
448         }
449
450         ret = ath11k_htc_init(ab);
451         if (ret) {
452                 ath11k_err(ab, "failed to init htc: %d\n", ret);
453                 goto err_wmi_detach;
454         }
455
456         ret = ath11k_hif_start(ab);
457         if (ret) {
458                 ath11k_err(ab, "failed to start HIF: %d\n", ret);
459                 goto err_wmi_detach;
460         }
461
462         ret = ath11k_htc_wait_target(&ab->htc);
463         if (ret) {
464                 ath11k_err(ab, "failed to connect to HTC: %d\n", ret);
465                 goto err_hif_stop;
466         }
467
468         ret = ath11k_dp_htt_connect(&ab->dp);
469         if (ret) {
470                 ath11k_err(ab, "failed to connect to HTT: %d\n", ret);
471                 goto err_hif_stop;
472         }
473
474         ret = ath11k_wmi_connect(ab);
475         if (ret) {
476                 ath11k_err(ab, "failed to connect wmi: %d\n", ret);
477                 goto err_hif_stop;
478         }
479
480         ret = ath11k_htc_start(&ab->htc);
481         if (ret) {
482                 ath11k_err(ab, "failed to start HTC: %d\n", ret);
483                 goto err_hif_stop;
484         }
485
486         ret = ath11k_wmi_wait_for_service_ready(ab);
487         if (ret) {
488                 ath11k_err(ab, "failed to receive wmi service ready event: %d\n",
489                            ret);
490                 goto err_hif_stop;
491         }
492
493         ret = ath11k_mac_allocate(ab);
494         if (ret) {
495                 ath11k_err(ab, "failed to create new hw device with mac80211 :%d\n",
496                            ret);
497                 goto err_hif_stop;
498         }
499
500         ath11k_dp_pdev_pre_alloc(ab);
501
502         ret = ath11k_dp_pdev_reo_setup(ab);
503         if (ret) {
504                 ath11k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
505                 goto err_mac_destroy;
506         }
507
508         ret = ath11k_wmi_cmd_init(ab);
509         if (ret) {
510                 ath11k_err(ab, "failed to send wmi init cmd: %d\n", ret);
511                 goto err_reo_cleanup;
512         }
513
514         ret = ath11k_wmi_wait_for_unified_ready(ab);
515         if (ret) {
516                 ath11k_err(ab, "failed to receive wmi unified ready event: %d\n",
517                            ret);
518                 goto err_reo_cleanup;
519         }
520
521         ret = ath11k_dp_tx_htt_h2t_ver_req_msg(ab);
522         if (ret) {
523                 ath11k_err(ab, "failed to send htt version request message: %d\n",
524                            ret);
525                 goto err_reo_cleanup;
526         }
527
528         return 0;
529
530 err_reo_cleanup:
531         ath11k_dp_pdev_reo_cleanup(ab);
532 err_mac_destroy:
533         ath11k_mac_destroy(ab);
534 err_hif_stop:
535         ath11k_hif_stop(ab);
536 err_wmi_detach:
537         ath11k_wmi_detach(ab);
538 err_firmware_stop:
539         ath11k_qmi_firmware_stop(ab);
540
541         return ret;
542 }
543
544 int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
545 {
546         int ret;
547
548         ret = ath11k_ce_init_pipes(ab);
549         if (ret) {
550                 ath11k_err(ab, "failed to initialize CE: %d\n", ret);
551                 return ret;
552         }
553
554         ret = ath11k_dp_alloc(ab);
555         if (ret) {
556                 ath11k_err(ab, "failed to init DP: %d\n", ret);
557                 return ret;
558         }
559
560         mutex_lock(&ab->core_lock);
561         ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL);
562         if (ret) {
563                 ath11k_err(ab, "failed to start core: %d\n", ret);
564                 goto err_dp_free;
565         }
566
567         ret = ath11k_core_pdev_create(ab);
568         if (ret) {
569                 ath11k_err(ab, "failed to create pdev core: %d\n", ret);
570                 goto err_core_stop;
571         }
572         ath11k_hif_irq_enable(ab);
573         mutex_unlock(&ab->core_lock);
574
575         return 0;
576
577 err_core_stop:
578         ath11k_core_stop(ab);
579         ath11k_mac_destroy(ab);
580 err_dp_free:
581         ath11k_dp_free(ab);
582         mutex_unlock(&ab->core_lock);
583         return ret;
584 }
585
586 static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab)
587 {
588         int ret;
589
590         mutex_lock(&ab->core_lock);
591         ath11k_thermal_unregister(ab);
592         ath11k_hif_irq_disable(ab);
593         ath11k_dp_pdev_free(ab);
594         ath11k_spectral_deinit(ab);
595         ath11k_hif_stop(ab);
596         ath11k_wmi_detach(ab);
597         ath11k_dp_pdev_reo_cleanup(ab);
598         mutex_unlock(&ab->core_lock);
599
600         ath11k_dp_free(ab);
601         ath11k_hal_srng_deinit(ab);
602
603         ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
604
605         ret = ath11k_hal_srng_init(ab);
606         if (ret)
607                 return ret;
608
609         clear_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags);
610
611         ret = ath11k_core_qmi_firmware_ready(ab);
612         if (ret)
613                 goto err_hal_srng_deinit;
614
615         clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
616
617         return 0;
618
619 err_hal_srng_deinit:
620         ath11k_hal_srng_deinit(ab);
621         return ret;
622 }
623
624 void ath11k_core_halt(struct ath11k *ar)
625 {
626         struct ath11k_base *ab = ar->ab;
627
628         lockdep_assert_held(&ar->conf_mutex);
629
630         ar->num_created_vdevs = 0;
631         ar->allocated_vdev_map = 0;
632
633         ath11k_mac_scan_finish(ar);
634         ath11k_mac_peer_cleanup_all(ar);
635         cancel_delayed_work_sync(&ar->scan.timeout);
636         cancel_work_sync(&ar->regd_update_work);
637
638         rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
639         synchronize_rcu();
640         INIT_LIST_HEAD(&ar->arvifs);
641         idr_init(&ar->txmgmt_idr);
642 }
643
644 static void ath11k_core_restart(struct work_struct *work)
645 {
646         struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work);
647         struct ath11k *ar;
648         struct ath11k_pdev *pdev;
649         int i, ret = 0;
650
651         spin_lock_bh(&ab->base_lock);
652         ab->stats.fw_crash_counter++;
653         spin_unlock_bh(&ab->base_lock);
654
655         for (i = 0; i < ab->num_radios; i++) {
656                 pdev = &ab->pdevs[i];
657                 ar = pdev->ar;
658                 if (!ar || ar->state == ATH11K_STATE_OFF)
659                         continue;
660
661                 ieee80211_stop_queues(ar->hw);
662                 ath11k_mac_drain_tx(ar);
663                 complete(&ar->scan.started);
664                 complete(&ar->scan.completed);
665                 complete(&ar->peer_assoc_done);
666                 complete(&ar->install_key_done);
667                 complete(&ar->vdev_setup_done);
668                 complete(&ar->bss_survey_done);
669                 complete(&ar->thermal.wmi_sync);
670
671                 wake_up(&ar->dp.tx_empty_waitq);
672                 idr_for_each(&ar->txmgmt_idr,
673                              ath11k_mac_tx_mgmt_pending_free, ar);
674                 idr_destroy(&ar->txmgmt_idr);
675         }
676
677         wake_up(&ab->wmi_ab.tx_credits_wq);
678         wake_up(&ab->peer_mapping_wq);
679
680         ret = ath11k_core_reconfigure_on_crash(ab);
681         if (ret) {
682                 ath11k_err(ab, "failed to reconfigure driver on crash recovery\n");
683                 return;
684         }
685
686         for (i = 0; i < ab->num_radios; i++) {
687                 pdev = &ab->pdevs[i];
688                 ar = pdev->ar;
689                 if (!ar || ar->state == ATH11K_STATE_OFF)
690                         continue;
691
692                 mutex_lock(&ar->conf_mutex);
693
694                 switch (ar->state) {
695                 case ATH11K_STATE_ON:
696                         ar->state = ATH11K_STATE_RESTARTING;
697                         ath11k_core_halt(ar);
698                         ieee80211_restart_hw(ar->hw);
699                         break;
700                 case ATH11K_STATE_OFF:
701                         ath11k_warn(ab,
702                                     "cannot restart radio %d that hasn't been started\n",
703                                     i);
704                         break;
705                 case ATH11K_STATE_RESTARTING:
706                         break;
707                 case ATH11K_STATE_RESTARTED:
708                         ar->state = ATH11K_STATE_WEDGED;
709                         /* fall through */
710                 case ATH11K_STATE_WEDGED:
711                         ath11k_warn(ab,
712                                     "device is wedged, will not restart radio %d\n", i);
713                         break;
714                 }
715                 mutex_unlock(&ar->conf_mutex);
716         }
717         complete(&ab->driver_recovery);
718 }
719
720 int ath11k_core_init(struct ath11k_base *ab)
721 {
722         struct device *dev = ab->dev;
723         struct rproc *prproc;
724         phandle rproc_phandle;
725         int ret;
726
727         if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) {
728                 ath11k_err(ab, "failed to get q6_rproc handle\n");
729                 return -ENOENT;
730         }
731
732         prproc = rproc_get_by_phandle(rproc_phandle);
733         if (!prproc) {
734                 ath11k_err(ab, "failed to get rproc\n");
735                 return -EINVAL;
736         }
737         ab->tgt_rproc = prproc;
738         ab->hw_params = ath11k_hw_params;
739
740         ret = ath11k_core_soc_create(ab);
741         if (ret) {
742                 ath11k_err(ab, "failed to create soc core: %d\n", ret);
743                 return ret;
744         }
745
746         return 0;
747 }
748
749 void ath11k_core_deinit(struct ath11k_base *ab)
750 {
751         mutex_lock(&ab->core_lock);
752
753         ath11k_core_pdev_destroy(ab);
754         ath11k_core_stop(ab);
755
756         mutex_unlock(&ab->core_lock);
757
758         ath11k_hif_power_down(ab);
759         ath11k_mac_destroy(ab);
760         ath11k_core_soc_destroy(ab);
761 }
762
763 void ath11k_core_free(struct ath11k_base *ab)
764 {
765         kfree(ab);
766 }
767
768 struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
769                                       enum ath11k_bus bus)
770 {
771         struct ath11k_base *ab;
772
773         ab = kzalloc(sizeof(*ab) + priv_size, GFP_KERNEL);
774         if (!ab)
775                 return NULL;
776
777         init_completion(&ab->driver_recovery);
778
779         ab->workqueue = create_singlethread_workqueue("ath11k_wq");
780         if (!ab->workqueue)
781                 goto err_sc_free;
782
783         mutex_init(&ab->core_lock);
784         spin_lock_init(&ab->base_lock);
785
786         INIT_LIST_HEAD(&ab->peers);
787         init_waitqueue_head(&ab->peer_mapping_wq);
788         init_waitqueue_head(&ab->wmi_ab.tx_credits_wq);
789         INIT_WORK(&ab->restart_work, ath11k_core_restart);
790         timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
791         ab->dev = dev;
792
793         return ab;
794
795 err_sc_free:
796         kfree(ab);
797         return NULL;
798 }