ath10k: refactor firmware images to struct ath10k_fw_components
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / core.c
index c84c2d3..b2efece 100644 (file)
@@ -60,10 +60,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 2116,
                .fw = {
                        .dir = QCA988X_HW_2_0_FW_DIR,
-                       .fw = QCA988X_HW_2_0_FW_FILE,
-                       .otp = QCA988X_HW_2_0_OTP_FILE,
                        .board = QCA988X_HW_2_0_BOARD_DATA_FILE,
                        .board_size = QCA988X_BOARD_DATA_SZ,
                        .board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
@@ -78,10 +77,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA6174_HW_2_1_FW_DIR,
-                       .fw = QCA6174_HW_2_1_FW_FILE,
-                       .otp = QCA6174_HW_2_1_OTP_FILE,
                        .board = QCA6174_HW_2_1_BOARD_DATA_FILE,
                        .board_size = QCA6174_BOARD_DATA_SZ,
                        .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
@@ -97,10 +95,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA6174_HW_2_1_FW_DIR,
-                       .fw = QCA6174_HW_2_1_FW_FILE,
-                       .otp = QCA6174_HW_2_1_OTP_FILE,
                        .board = QCA6174_HW_2_1_BOARD_DATA_FILE,
                        .board_size = QCA6174_BOARD_DATA_SZ,
                        .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
@@ -116,10 +113,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA6174_HW_3_0_FW_DIR,
-                       .fw = QCA6174_HW_3_0_FW_FILE,
-                       .otp = QCA6174_HW_3_0_OTP_FILE,
                        .board = QCA6174_HW_3_0_BOARD_DATA_FILE,
                        .board_size = QCA6174_BOARD_DATA_SZ,
                        .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
@@ -135,11 +131,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
+               .cal_data_len = 8124,
                .fw = {
                        /* uses same binaries as hw3.0 */
                        .dir = QCA6174_HW_3_0_FW_DIR,
-                       .fw = QCA6174_HW_3_0_FW_FILE,
-                       .otp = QCA6174_HW_3_0_OTP_FILE,
                        .board = QCA6174_HW_3_0_BOARD_DATA_FILE,
                        .board_size = QCA6174_BOARD_DATA_SZ,
                        .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
@@ -156,15 +151,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 150000,
                .max_probe_resp_desc_thres = 24,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
-               .num_msdu_desc = 1424,
-               .qcache_active_peers = 50,
                .tx_chain_mask = 0xf,
                .rx_chain_mask = 0xf,
                .max_spatial_stream = 4,
+               .cal_data_len = 12064,
                .fw = {
                        .dir = QCA99X0_HW_2_0_FW_DIR,
-                       .fw = QCA99X0_HW_2_0_FW_FILE,
-                       .otp = QCA99X0_HW_2_0_OTP_FILE,
                        .board = QCA99X0_HW_2_0_BOARD_DATA_FILE,
                        .board_size = QCA99X0_BOARD_DATA_SZ,
                        .board_ext_size = QCA99X0_BOARD_EXT_DATA_SZ,
@@ -179,10 +171,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA9377_HW_1_0_FW_DIR,
-                       .fw = QCA9377_HW_1_0_FW_FILE,
-                       .otp = QCA9377_HW_1_0_OTP_FILE,
                        .board = QCA9377_HW_1_0_BOARD_DATA_FILE,
                        .board_size = QCA9377_BOARD_DATA_SZ,
                        .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
@@ -197,10 +188,9 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .otp_exe_param = 0,
                .channel_counters_freq_hz = 88000,
                .max_probe_resp_desc_thres = 0,
+               .cal_data_len = 8124,
                .fw = {
                        .dir = QCA9377_HW_1_0_FW_DIR,
-                       .fw = QCA9377_HW_1_0_FW_FILE,
-                       .otp = QCA9377_HW_1_0_OTP_FILE,
                        .board = QCA9377_HW_1_0_BOARD_DATA_FILE,
                        .board_size = QCA9377_BOARD_DATA_SZ,
                        .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
@@ -217,15 +207,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .channel_counters_freq_hz = 125000,
                .max_probe_resp_desc_thres = 24,
                .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
-               .num_msdu_desc = 2500,
-               .qcache_active_peers = 35,
                .tx_chain_mask = 0x3,
                .rx_chain_mask = 0x3,
                .max_spatial_stream = 2,
+               .cal_data_len = 12064,
                .fw = {
                        .dir = QCA4019_HW_1_0_FW_DIR,
-                       .fw = QCA4019_HW_1_0_FW_FILE,
-                       .otp = QCA4019_HW_1_0_OTP_FILE,
                        .board = QCA4019_HW_1_0_BOARD_DATA_FILE,
                        .board_size = QCA4019_BOARD_DATA_SZ,
                        .board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
@@ -466,18 +453,18 @@ exit:
        return ret;
 }
 
-static int ath10k_download_cal_file(struct ath10k *ar)
+static int ath10k_download_cal_file(struct ath10k *ar,
+                                   const struct firmware *file)
 {
        int ret;
 
-       if (!ar->cal_file)
+       if (!file)
                return -ENOENT;
 
-       if (IS_ERR(ar->cal_file))
-               return PTR_ERR(ar->cal_file);
+       if (IS_ERR(file))
+               return PTR_ERR(file);
 
-       ret = ath10k_download_board_data(ar, ar->cal_file->data,
-                                        ar->cal_file->size);
+       ret = ath10k_download_board_data(ar, file->data, file->size);
        if (ret) {
                ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
                return ret;
@@ -488,7 +475,7 @@ static int ath10k_download_cal_file(struct ath10k *ar)
        return 0;
 }
 
-static int ath10k_download_cal_dt(struct ath10k *ar)
+static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
 {
        struct device_node *node;
        int data_len;
@@ -502,13 +489,12 @@ static int ath10k_download_cal_dt(struct ath10k *ar)
                 */
                return -ENOENT;
 
-       if (!of_get_property(node, "qcom,ath10k-calibration-data",
-                            &data_len)) {
+       if (!of_get_property(node, dt_name, &data_len)) {
                /* The calibration data node is optional */
                return -ENOENT;
        }
 
-       if (data_len != QCA988X_CAL_DATA_LEN) {
+       if (data_len != ar->hw_params.cal_data_len) {
                ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
                            data_len);
                ret = -EMSGSIZE;
@@ -521,8 +507,7 @@ static int ath10k_download_cal_dt(struct ath10k *ar)
                goto out;
        }
 
-       ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data",
-                                       data, data_len);
+       ret = of_property_read_u8_array(node, dt_name, data, data_len);
        if (ret) {
                ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
                            ret);
@@ -553,7 +538,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
 
        address = ar->hw_params.patch_load_addr;
 
-       if (!ar->otp_data || !ar->otp_len) {
+       if (!ar->normal_mode_fw.fw_file.otp_data ||
+           !ar->normal_mode_fw.fw_file.otp_len) {
                ath10k_warn(ar,
                            "failed to retrieve board id because of invalid otp\n");
                return -ENODATA;
@@ -561,9 +547,11 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT,
                   "boot upload otp to 0x%x len %zd for board id\n",
-                  address, ar->otp_len);
+                  address, ar->normal_mode_fw.fw_file.otp_len);
 
-       ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
+       ret = ath10k_bmi_fast_download(ar, address,
+                                      ar->normal_mode_fw.fw_file.otp_data,
+                                      ar->normal_mode_fw.fw_file.otp_len);
        if (ret) {
                ath10k_err(ar, "could not write otp for board id check: %d\n",
                           ret);
@@ -601,7 +589,9 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
        u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
        int ret;
 
-       ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
+       ret = ath10k_download_board_data(ar,
+                                        ar->running_fw->board_data,
+                                        ar->running_fw->board_len);
        if (ret) {
                ath10k_err(ar, "failed to download board data: %d\n", ret);
                return ret;
@@ -609,16 +599,20 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
 
        /* OTP is optional */
 
-       if (!ar->otp_data || !ar->otp_len) {
+       if (!ar->running_fw->fw_file.otp_data ||
+           !ar->running_fw->fw_file.otp_len) {
                ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
-                           ar->otp_data, ar->otp_len);
+                           ar->running_fw->fw_file.otp_data,
+                           ar->running_fw->fw_file.otp_len);
                return 0;
        }
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
-                  address, ar->otp_len);
+                  address, ar->running_fw->fw_file.otp_len);
 
-       ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
+       ret = ath10k_bmi_fast_download(ar, address,
+                                      ar->running_fw->fw_file.otp_data,
+                                      ar->running_fw->fw_file.otp_len);
        if (ret) {
                ath10k_err(ar, "could not write otp (%d)\n", ret);
                return ret;
@@ -642,46 +636,33 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
        return 0;
 }
 
-static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
+static int ath10k_download_fw(struct ath10k *ar)
 {
        u32 address, data_len;
-       const char *mode_name;
        const void *data;
        int ret;
 
        address = ar->hw_params.patch_load_addr;
 
-       switch (mode) {
-       case ATH10K_FIRMWARE_MODE_NORMAL:
-               data = ar->firmware_data;
-               data_len = ar->firmware_len;
-               mode_name = "normal";
-               ret = ath10k_swap_code_seg_configure(ar,
-                                                    ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW);
-               if (ret) {
-                       ath10k_err(ar, "failed to configure fw code swap: %d\n",
-                                  ret);
-                       return ret;
-               }
-               break;
-       case ATH10K_FIRMWARE_MODE_UTF:
-               data = ar->testmode.utf_firmware_data;
-               data_len = ar->testmode.utf_firmware_len;
-               mode_name = "utf";
-               break;
-       default:
-               ath10k_err(ar, "unknown firmware mode: %d\n", mode);
-               return -EINVAL;
+       data = ar->running_fw->fw_file.firmware_data;
+       data_len = ar->running_fw->fw_file.firmware_len;
+
+       ret = ath10k_swap_code_seg_configure(ar,
+                                            ATH10K_SWAP_CODE_SEG_BIN_TYPE_FW);
+       if (ret) {
+               ath10k_err(ar, "failed to configure fw code swap: %d\n",
+                          ret);
+               return ret;
        }
 
        ath10k_dbg(ar, ATH10K_DBG_BOOT,
-                  "boot uploading firmware image %p len %d mode %s\n",
-                  data, data_len, mode_name);
+                  "boot uploading firmware image %p len %d\n",
+                  data, data_len);
 
        ret = ath10k_bmi_fast_download(ar, address, data, data_len);
        if (ret) {
-               ath10k_err(ar, "failed to download %s firmware: %d\n",
-                          mode_name, ret);
+               ath10k_err(ar, "failed to download firmware: %d\n",
+                          ret);
                return ret;
        }
 
@@ -690,34 +671,30 @@ static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
 
 static void ath10k_core_free_board_files(struct ath10k *ar)
 {
-       if (!IS_ERR(ar->board))
-               release_firmware(ar->board);
+       if (!IS_ERR(ar->normal_mode_fw.board))
+               release_firmware(ar->normal_mode_fw.board);
 
-       ar->board = NULL;
-       ar->board_data = NULL;
-       ar->board_len = 0;
+       ar->normal_mode_fw.board = NULL;
+       ar->normal_mode_fw.board_data = NULL;
+       ar->normal_mode_fw.board_len = 0;
 }
 
 static void ath10k_core_free_firmware_files(struct ath10k *ar)
 {
-       if (!IS_ERR(ar->otp))
-               release_firmware(ar->otp);
-
-       if (!IS_ERR(ar->firmware))
-               release_firmware(ar->firmware);
+       if (!IS_ERR(ar->normal_mode_fw.fw_file.firmware))
+               release_firmware(ar->normal_mode_fw.fw_file.firmware);
 
        if (!IS_ERR(ar->cal_file))
                release_firmware(ar->cal_file);
 
        ath10k_swap_code_seg_release(ar);
 
-       ar->otp = NULL;
-       ar->otp_data = NULL;
-       ar->otp_len = 0;
+       ar->normal_mode_fw.fw_file.otp_data = NULL;
+       ar->normal_mode_fw.fw_file.otp_len = 0;
 
-       ar->firmware = NULL;
-       ar->firmware_data = NULL;
-       ar->firmware_len = 0;
+       ar->normal_mode_fw.fw_file.firmware = NULL;
+       ar->normal_mode_fw.fw_file.firmware_data = NULL;
+       ar->normal_mode_fw.fw_file.firmware_len = 0;
 
        ar->cal_file = NULL;
 }
@@ -726,6 +703,14 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
 {
        char filename[100];
 
+       /* pre-cal-<bus>-<id>.bin */
+       scnprintf(filename, sizeof(filename), "pre-cal-%s-%s.bin",
+                 ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
+
+       ar->pre_cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
+       if (!IS_ERR(ar->pre_cal_file))
+               goto success;
+
        /* cal-<bus>-<id>.bin */
        scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
                  ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
@@ -734,7 +719,7 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
        if (IS_ERR(ar->cal_file))
                /* calibration file is optional, don't print any warnings */
                return PTR_ERR(ar->cal_file);
-
+success:
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
                   ATH10K_FW_DIR, filename);
 
@@ -748,14 +733,14 @@ static int ath10k_core_fetch_board_data_api_1(struct ath10k *ar)
                return -EINVAL;
        }
 
-       ar->board = ath10k_fetch_fw_file(ar,
-                                        ar->hw_params.fw.dir,
-                                        ar->hw_params.fw.board);
-       if (IS_ERR(ar->board))
-               return PTR_ERR(ar->board);
+       ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
+                                                       ar->hw_params.fw.dir,
+                                                       ar->hw_params.fw.board);
+       if (IS_ERR(ar->normal_mode_fw.board))
+               return PTR_ERR(ar->normal_mode_fw.board);
 
-       ar->board_data = ar->board->data;
-       ar->board_len = ar->board->size;
+       ar->normal_mode_fw.board_data = ar->normal_mode_fw.board->data;
+       ar->normal_mode_fw.board_len = ar->normal_mode_fw.board->size;
 
        return 0;
 }
@@ -815,8 +800,8 @@ static int ath10k_core_parse_bd_ie_board(struct ath10k *ar,
                                   "boot found board data for '%s'",
                                   boardname);
 
-                       ar->board_data = board_ie_data;
-                       ar->board_len = board_ie_len;
+                       ar->normal_mode_fw.board_data = board_ie_data;
+                       ar->normal_mode_fw.board_len = board_ie_len;
 
                        ret = 0;
                        goto out;
@@ -849,12 +834,14 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
        const u8 *data;
        int ret, ie_id;
 
-       ar->board = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, filename);
-       if (IS_ERR(ar->board))
-               return PTR_ERR(ar->board);
+       ar->normal_mode_fw.board = ath10k_fetch_fw_file(ar,
+                                                       ar->hw_params.fw.dir,
+                                                       filename);
+       if (IS_ERR(ar->normal_mode_fw.board))
+               return PTR_ERR(ar->normal_mode_fw.board);
 
-       data = ar->board->data;
-       len = ar->board->size;
+       data = ar->normal_mode_fw.board->data;
+       len = ar->normal_mode_fw.board->size;
 
        /* magic has extra null byte padded */
        magic_len = strlen(ATH10K_BOARD_MAGIC) + 1;
@@ -921,7 +908,7 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
        }
 
 out:
-       if (!ar->board_data || !ar->board_len) {
+       if (!ar->normal_mode_fw.board_data || !ar->normal_mode_fw.board_len) {
                ath10k_err(ar,
                           "failed to fetch board data for %s from %s/%s\n",
                           boardname, ar->hw_params.fw.dir, filename);
@@ -989,51 +976,8 @@ success:
        return 0;
 }
 
-static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
-{
-       int ret = 0;
-
-       if (ar->hw_params.fw.fw == NULL) {
-               ath10k_err(ar, "firmware file not defined\n");
-               return -EINVAL;
-       }
-
-       ar->firmware = ath10k_fetch_fw_file(ar,
-                                           ar->hw_params.fw.dir,
-                                           ar->hw_params.fw.fw);
-       if (IS_ERR(ar->firmware)) {
-               ret = PTR_ERR(ar->firmware);
-               ath10k_err(ar, "could not fetch firmware (%d)\n", ret);
-               goto err;
-       }
-
-       ar->firmware_data = ar->firmware->data;
-       ar->firmware_len = ar->firmware->size;
-
-       /* OTP may be undefined. If so, don't fetch it at all */
-       if (ar->hw_params.fw.otp == NULL)
-               return 0;
-
-       ar->otp = ath10k_fetch_fw_file(ar,
-                                      ar->hw_params.fw.dir,
-                                      ar->hw_params.fw.otp);
-       if (IS_ERR(ar->otp)) {
-               ret = PTR_ERR(ar->otp);
-               ath10k_err(ar, "could not fetch otp (%d)\n", ret);
-               goto err;
-       }
-
-       ar->otp_data = ar->otp->data;
-       ar->otp_len = ar->otp->size;
-
-       return 0;
-
-err:
-       ath10k_core_free_firmware_files(ar);
-       return ret;
-}
-
-static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
+static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
+                                           struct ath10k_fw_file *fw_file)
 {
        size_t magic_len, len, ie_len;
        int ie_id, i, index, bit, ret;
@@ -1042,15 +986,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
        __le32 *timestamp, *version;
 
        /* first fetch the firmware file (firmware-*.bin) */
-       ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
-       if (IS_ERR(ar->firmware)) {
+       fw_file->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
+                                                name);
+       if (IS_ERR(fw_file->firmware)) {
                ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n",
-                          ar->hw_params.fw.dir, name, PTR_ERR(ar->firmware));
-               return PTR_ERR(ar->firmware);
+                          ar->hw_params.fw.dir, name,
+                          PTR_ERR(fw_file->firmware));
+               return PTR_ERR(fw_file->firmware);
        }
 
-       data = ar->firmware->data;
-       len = ar->firmware->size;
+       data = fw_file->firmware->data;
+       len = fw_file->firmware->size;
 
        /* magic also includes the null byte, check that as well */
        magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;
@@ -1141,8 +1087,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                                   "found fw image ie (%zd B)\n",
                                   ie_len);
 
-                       ar->firmware_data = data;
-                       ar->firmware_len = ie_len;
+                       fw_file->firmware_data = data;
+                       fw_file->firmware_len = ie_len;
 
                        break;
                case ATH10K_FW_IE_OTP_IMAGE:
@@ -1150,8 +1096,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                                   "found otp image ie (%zd B)\n",
                                   ie_len);
 
-                       ar->otp_data = data;
-                       ar->otp_len = ie_len;
+                       fw_file->otp_data = data;
+                       fw_file->otp_len = ie_len;
 
                        break;
                case ATH10K_FW_IE_WMI_OP_VERSION:
@@ -1180,8 +1126,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                        ath10k_dbg(ar, ATH10K_DBG_BOOT,
                                   "found fw code swap image ie (%zd B)\n",
                                   ie_len);
-                       ar->swap.firmware_codeswap_data = data;
-                       ar->swap.firmware_codeswap_len = ie_len;
+                       fw_file->codeswap_data = data;
+                       fw_file->codeswap_len = ie_len;
                        break;
                default:
                        ath10k_warn(ar, "Unknown FW IE: %u\n",
@@ -1196,7 +1142,8 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
                data += ie_len;
        }
 
-       if (!ar->firmware_data || !ar->firmware_len) {
+       if (!fw_file->firmware_data ||
+           !fw_file->firmware_len) {
                ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",
                            ar->hw_params.fw.dir, name);
                ret = -ENOMEDIUM;
@@ -1220,40 +1167,95 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
        ar->fw_api = 5;
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
 
-       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE);
+       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE,
+                                              &ar->normal_mode_fw.fw_file);
        if (ret == 0)
                goto success;
 
        ar->fw_api = 4;
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
 
-       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE);
+       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE,
+                                              &ar->normal_mode_fw.fw_file);
        if (ret == 0)
                goto success;
 
        ar->fw_api = 3;
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
 
-       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE);
+       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE,
+                                              &ar->normal_mode_fw.fw_file);
        if (ret == 0)
                goto success;
 
        ar->fw_api = 2;
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
 
-       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE);
-       if (ret == 0)
+       ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE,
+                                              &ar->normal_mode_fw.fw_file);
+       if (ret)
+               return ret;
+
+success:
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
+
+       return 0;
+}
+
+static int ath10k_core_pre_cal_download(struct ath10k *ar)
+{
+       int ret;
+
+       ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
+       if (ret == 0) {
+               ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
                goto success;
+       }
 
-       ar->fw_api = 1;
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "boot did not find a pre calibration file, try DT next: %d\n",
+                  ret);
 
-       ret = ath10k_core_fetch_firmware_api_1(ar);
-       if (ret)
+       ret = ath10k_download_cal_dt(ar, "qcom,ath10k-pre-calibration-data");
+       if (ret) {
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "unable to load pre cal data from DT: %d\n", ret);
                return ret;
+       }
+       ar->cal_mode = ATH10K_PRE_CAL_MODE_DT;
 
 success:
-       ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
+       ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
+                  ath10k_cal_mode_str(ar->cal_mode));
+
+       return 0;
+}
+
+static int ath10k_core_pre_cal_config(struct ath10k *ar)
+{
+       int ret;
+
+       ret = ath10k_core_pre_cal_download(ar);
+       if (ret) {
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "failed to load pre cal data: %d\n", ret);
+               return ret;
+       }
+
+       ret = ath10k_core_get_board_id_from_otp(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to get board id: %d\n", ret);
+               return ret;
+       }
+
+       ret = ath10k_download_and_run_otp(ar);
+       if (ret) {
+               ath10k_err(ar, "failed to run otp: %d\n", ret);
+               return ret;
+       }
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "pre cal configuration done successfully\n");
 
        return 0;
 }
@@ -1262,7 +1264,15 @@ static int ath10k_download_cal_data(struct ath10k *ar)
 {
        int ret;
 
-       ret = ath10k_download_cal_file(ar);
+       ret = ath10k_core_pre_cal_config(ar);
+       if (ret == 0)
+               return 0;
+
+       ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                  "pre cal download procedure failed, try cal file: %d\n",
+                  ret);
+
+       ret = ath10k_download_cal_file(ar, ar->cal_file);
        if (ret == 0) {
                ar->cal_mode = ATH10K_CAL_MODE_FILE;
                goto done;
@@ -1272,7 +1282,7 @@ static int ath10k_download_cal_data(struct ath10k *ar)
                   "boot did not find a calibration file, try DT next: %d\n",
                   ret);
 
-       ret = ath10k_download_cal_dt(ar);
+       ret = ath10k_download_cal_dt(ar, "qcom,ath10k-calibration-data");
        if (ret == 0) {
                ar->cal_mode = ATH10K_CAL_MODE_DT;
                goto done;
@@ -1509,7 +1519,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
        case ATH10K_FW_WMI_OP_VERSION_10_1:
        case ATH10K_FW_WMI_OP_VERSION_10_2:
        case ATH10K_FW_WMI_OP_VERSION_10_2_4:
-               if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
+               if (ath10k_peer_stats_enabled(ar)) {
                        ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
                        ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
                } else {
@@ -1538,9 +1548,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
                ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
                ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
                ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
-               ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc;
-               ar->fw_stats_req_mask = WMI_STAT_PEER;
+               ar->fw_stats_req_mask = WMI_10_4_STAT_PEER |
+                                       WMI_10_4_STAT_PEER_EXTD;
                ar->max_spatial_stream = ar->hw_params.max_spatial_stream;
+
+               if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
+                            ar->fw_features))
+                       ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC;
+               else
+                       ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
                break;
        case ATH10K_FW_WMI_OP_VERSION_UNSET:
        case ATH10K_FW_WMI_OP_VERSION_MAX:
@@ -1575,14 +1591,18 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
        return 0;
 }
 
-int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
+                     const struct ath10k_fw_components *fw)
 {
        int status;
+       u32 val;
 
        lockdep_assert_held(&ar->conf_mutex);
 
        clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
 
+       ar->running_fw = fw;
+
        ath10k_bmi_start(ar);
 
        if (ath10k_init_configure_target(ar)) {
@@ -1610,7 +1630,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
                }
        }
 
-       status = ath10k_download_fw(ar, mode);
+       status = ath10k_download_fw(ar);
        if (status)
                goto err;
 
@@ -1698,6 +1718,20 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
        ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
                   ar->hw->wiphy->fw_version);
 
+       if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) {
+               val = 0;
+               if (ath10k_peer_stats_enabled(ar))
+                       val = WMI_10_4_PEER_STATS;
+
+               status = ath10k_mac_ext_resource_config(ar, val);
+               if (status) {
+                       ath10k_err(ar,
+                                  "failed to send ext resource cfg command : %d\n",
+                                  status);
+                       goto err_hif_stop;
+               }
+       }
+
        status = ath10k_wmi_cmd_init(ar);
        if (status) {
                ath10k_err(ar, "could not send WMI init command (%d)\n",
@@ -1834,11 +1868,20 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
        ath10k_debug_print_hwfw_info(ar);
 
+       ret = ath10k_core_pre_cal_download(ar);
+       if (ret) {
+               /* pre calibration data download is not necessary
+                * for all the chipsets. Ignore failures and continue.
+                */
+               ath10k_dbg(ar, ATH10K_DBG_BOOT,
+                          "could not load pre cal data: %d\n", ret);
+       }
+
        ret = ath10k_core_get_board_id_from_otp(ar);
        if (ret && ret != -EOPNOTSUPP) {
                ath10k_err(ar, "failed to get board id from otp: %d\n",
                           ret);
-               return ret;
+               goto err_free_firmware_files;
        }
 
        ret = ath10k_core_fetch_board_file(ar);
@@ -1865,7 +1908,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
 
        mutex_lock(&ar->conf_mutex);
 
-       ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
+       ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL,
+                               &ar->normal_mode_fw);
        if (ret) {
                ath10k_err(ar, "could not init core (%d)\n", ret);
                goto err_unlock;
@@ -2048,7 +2092,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
 
        mutex_init(&ar->conf_mutex);
        spin_lock_init(&ar->data_lock);
+       spin_lock_init(&ar->txqs_lock);
 
+       INIT_LIST_HEAD(&ar->txqs);
        INIT_LIST_HEAD(&ar->peers);
        init_waitqueue_head(&ar->peer_mapping_wq);
        init_waitqueue_head(&ar->htt.empty_tx_wq);