linux/drivers/net/wireless/ath/ath11k/core.c
<<
>>
Prefs
   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
  16unsigned int ath11k_debug_mask;
  17module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
  18MODULE_PARM_DESC(debug_mask, "Debugging mask");
  19
  20static 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 */
  30u8 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}
  44EXPORT_SYMBOL(ath11k_core_get_hw_mac_id);
  45
  46static 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
  62static 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
  89void 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
  97static 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
 174out:
 175        return ret;
 176}
 177
 178static 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
 263out:
 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
 274err:
 275        ath11k_core_free_bdf(ab, bd);
 276        return ret;
 277}
 278
 279static 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
 295int 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
 319success:
 320        ath11k_dbg(ab, ATH11K_DBG_BOOT, "using board api %d\n", ab->bd_api);
 321        return 0;
 322}
 323
 324static 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
 335static 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
 359err_debugfs_reg:
 360        ath11k_debug_soc_destroy(ab);
 361err_qmi_deinit:
 362        ath11k_qmi_deinit_service(ab);
 363        return ret;
 364}
 365
 366static 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
 374static 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
 411err_thermal_unregister:
 412        ath11k_thermal_unregister(ab);
 413err_dp_pdev_free:
 414        ath11k_dp_pdev_free(ab);
 415err_mac_unregister:
 416        ath11k_mac_unregister(ab);
 417err_pdev_debug:
 418        ath11k_debug_pdev_destroy(ab);
 419
 420        return ret;
 421}
 422
 423static 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
 433static 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
 530err_reo_cleanup:
 531        ath11k_dp_pdev_reo_cleanup(ab);
 532err_mac_destroy:
 533        ath11k_mac_destroy(ab);
 534err_hif_stop:
 535        ath11k_hif_stop(ab);
 536err_wmi_detach:
 537        ath11k_wmi_detach(ab);
 538err_firmware_stop:
 539        ath11k_qmi_firmware_stop(ab);
 540
 541        return ret;
 542}
 543
 544int 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
 577err_core_stop:
 578        ath11k_core_stop(ab);
 579        ath11k_mac_destroy(ab);
 580err_dp_free:
 581        ath11k_dp_free(ab);
 582        mutex_unlock(&ab->core_lock);
 583        return ret;
 584}
 585
 586static 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
 619err_hal_srng_deinit:
 620        ath11k_hal_srng_deinit(ab);
 621        return ret;
 622}
 623
 624void 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
 644static 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
 720int 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
 749void 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
 763void ath11k_core_free(struct ath11k_base *ab)
 764{
 765        kfree(ab);
 766}
 767
 768struct 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
 795err_sc_free:
 796        kfree(ab);
 797        return NULL;
 798}
 799