core.c 42.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (c) 2005-2011 Atheros Communications Inc.
 * Copyright (c) 2011-2013 Qualcomm Atheros, Inc.
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <linux/module.h>
#include <linux/firmware.h>
20
#include <linux/of.h>
21
22
23
24
25
26
27
28
29

#include "core.h"
#include "mac.h"
#include "htc.h"
#include "hif.h"
#include "wmi.h"
#include "bmi.h"
#include "debug.h"
#include "htt.h"
Kalle Valo's avatar
Kalle Valo committed
30
#include "testmode.h"
Michal Kazior's avatar
Michal Kazior committed
31
#include "wmi-ops.h"
32
33

unsigned int ath10k_debug_mask;
34
static unsigned int ath10k_cryptmode_param;
35
static bool uart_print;
36
37
static bool skip_otp;

38
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
39
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
40
module_param(uart_print, bool, 0644);
41
42
module_param(skip_otp, bool, 0644);

43
44
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
45
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
46
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
47
48
49
50
51
52

static const struct ath10k_hw_params ath10k_hw_params_list[] = {
	{
		.id = QCA988X_HW_2_0_VERSION,
		.name = "qca988x hw2.0",
		.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
53
		.uart_pin = 7,
54
		.has_shifted_cc_wraparound = true,
55
		.otp_exe_param = 0,
56
		.channel_counters_freq_hz = 88000,
57
58
59
60
61
		.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,
62
63
			.board_size = QCA988X_BOARD_DATA_SZ,
			.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
64
65
		},
	},
66
67
68
69
70
	{
		.id = QCA6174_HW_2_1_VERSION,
		.name = "qca6174 hw2.1",
		.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
		.uart_pin = 6,
71
		.otp_exe_param = 0,
72
		.channel_counters_freq_hz = 88000,
73
74
75
76
77
78
79
80
81
82
83
84
85
86
		.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,
		},
	},
	{
		.id = QCA6174_HW_3_0_VERSION,
		.name = "qca6174 hw3.0",
		.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
		.uart_pin = 6,
87
		.otp_exe_param = 0,
88
		.channel_counters_freq_hz = 88000,
89
90
91
92
93
94
95
96
97
		.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,
		},
	},
Michal Kazior's avatar
Michal Kazior committed
98
99
100
101
102
	{
		.id = QCA6174_HW_3_2_VERSION,
		.name = "qca6174 hw3.2",
		.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
		.uart_pin = 6,
103
		.otp_exe_param = 0,
104
		.channel_counters_freq_hz = 88000,
Michal Kazior's avatar
Michal Kazior committed
105
106
107
108
109
110
111
112
113
114
		.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,
		},
	},
115
116
117
118
119
	{
		.id = QCA99X0_HW_2_0_DEV_VERSION,
		.name = "qca99x0 hw2.0",
		.patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
		.uart_pin = 7,
120
		.otp_exe_param = 0x00000700,
121
		.continuous_frag_desc = true,
122
		.channel_counters_freq_hz = 150000,
123
124
125
126
127
128
129
130
131
		.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,
		},
	},
132
133
};

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
static const char *const ath10k_core_fw_feature_str[] = {
	[ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX] = "wmi-mgmt-rx",
	[ATH10K_FW_FEATURE_WMI_10X] = "wmi-10.x",
	[ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX] = "has-wmi-mgmt-tx",
	[ATH10K_FW_FEATURE_NO_P2P] = "no-p2p",
	[ATH10K_FW_FEATURE_WMI_10_2] = "wmi-10.2",
	[ATH10K_FW_FEATURE_MULTI_VIF_PS_SUPPORT] = "multi-vif-ps",
	[ATH10K_FW_FEATURE_WOWLAN_SUPPORT] = "wowlan",
	[ATH10K_FW_FEATURE_IGNORE_OTP_RESULT] = "ignore-otp",
	[ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING] = "no-4addr-pad",
	[ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
};

static unsigned int ath10k_core_get_fw_feature_str(char *buf,
						   size_t buf_len,
						   enum ath10k_fw_features feat)
{
	if (feat >= ARRAY_SIZE(ath10k_core_fw_feature_str) ||
	    WARN_ON(!ath10k_core_fw_feature_str[feat])) {
		return scnprintf(buf, buf_len, "bit%d", feat);
	}

	return scnprintf(buf, buf_len, "%s", ath10k_core_fw_feature_str[feat]);
}

void ath10k_core_get_fw_features_str(struct ath10k *ar,
				     char *buf,
				     size_t buf_len)
{
	unsigned int len = 0;
	int i;

	for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {
		if (test_bit(i, ar->fw_features)) {
			if (len > 0)
				len += scnprintf(buf + len, buf_len - len, ",");

			len += ath10k_core_get_fw_feature_str(buf + len,
							      buf_len - len,
							      i);
		}
	}
}

178
179
static void ath10k_send_suspend_complete(struct ath10k *ar)
{
180
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot suspend complete\n");
181

182
	complete(&ar->target_suspend);
183
184
185
186
187
188
189
190
191
192
193
}

static int ath10k_init_configure_target(struct ath10k *ar)
{
	u32 param_host;
	int ret;

	/* tell target which HTC version it is used*/
	ret = ath10k_bmi_write32(ar, hi_app_host_interest,
				 HTC_PROTOCOL_VERSION);
	if (ret) {
194
		ath10k_err(ar, "settings HTC version failed\n");
195
196
197
198
199
200
		return ret;
	}

	/* set the firmware mode to STA/IBSS/AP */
	ret = ath10k_bmi_read32(ar, hi_option_flag, &param_host);
	if (ret) {
201
		ath10k_err(ar, "setting firmware mode (1/2) failed\n");
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
		return ret;
	}

	/* TODO following parameters need to be re-visited. */
	/* num_device */
	param_host |= (1 << HI_OPTION_NUM_DEV_SHIFT);
	/* Firmware mode */
	/* FIXME: Why FW_MODE_AP ??.*/
	param_host |= (HI_OPTION_FW_MODE_AP << HI_OPTION_FW_MODE_SHIFT);
	/* mac_addr_method */
	param_host |= (1 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
	/* firmware_bridge */
	param_host |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
	/* fwsubmode */
	param_host |= (0 << HI_OPTION_FW_SUBMODE_SHIFT);

	ret = ath10k_bmi_write32(ar, hi_option_flag, param_host);
	if (ret) {
220
		ath10k_err(ar, "setting firmware mode (2/2) failed\n");
221
222
223
224
225
226
		return ret;
	}

	/* We do all byte-swapping on the host */
	ret = ath10k_bmi_write32(ar, hi_be, 0);
	if (ret) {
227
		ath10k_err(ar, "setting host CPU BE mode failed\n");
228
229
230
231
232
233
234
		return ret;
	}

	/* FW descriptor/Data swap flags */
	ret = ath10k_bmi_write32(ar, hi_fw_swap, 0);

	if (ret) {
235
		ath10k_err(ar, "setting FW data/desc swap flags failed\n");
236
237
238
		return ret;
	}

Michal Kazior's avatar
Michal Kazior committed
239
240
241
242
243
244
245
246
247
248
249
	/* Some devices have a special sanity check that verifies the PCI
	 * Device ID is written to this host interest var. It is known to be
	 * required to boot QCA6164.
	 */
	ret = ath10k_bmi_write32(ar, hi_hci_uart_pwr_mgmt_params_ext,
				 ar->dev_id);
	if (ret) {
		ath10k_err(ar, "failed to set pwr_mgmt_params: %d\n", ret);
		return ret;
	}

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
	return 0;
}

static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
						   const char *dir,
						   const char *file)
{
	char filename[100];
	const struct firmware *fw;
	int ret;

	if (file == NULL)
		return ERR_PTR(-ENOENT);

	if (dir == NULL)
		dir = ".";

	snprintf(filename, sizeof(filename), "%s/%s", dir, file);
	ret = request_firmware(&fw, filename, ar->dev);
	if (ret)
		return ERR_PTR(ret);

	return fw;
}

275
276
static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
				      size_t data_len)
277
{
278
279
	u32 board_data_size = ar->hw_params.fw.board_size;
	u32 board_ext_data_size = ar->hw_params.fw.board_ext_size;
280
281
282
283
284
	u32 board_ext_data_addr;
	int ret;

	ret = ath10k_bmi_read32(ar, hi_board_ext_data, &board_ext_data_addr);
	if (ret) {
285
286
		ath10k_err(ar, "could not read board ext data addr (%d)\n",
			   ret);
287
288
289
		return ret;
	}

290
	ath10k_dbg(ar, ATH10K_DBG_BOOT,
291
		   "boot push board extended data addr 0x%x\n",
292
293
294
295
296
		   board_ext_data_addr);

	if (board_ext_data_addr == 0)
		return 0;

297
	if (data_len != (board_data_size + board_ext_data_size)) {
298
		ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",
299
			   data_len, board_data_size, board_ext_data_size);
300
301
302
303
		return -EINVAL;
	}

	ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,
304
				      data + board_data_size,
305
306
				      board_ext_data_size);
	if (ret) {
307
		ath10k_err(ar, "could not write board ext data (%d)\n", ret);
308
309
310
311
312
313
		return ret;
	}

	ret = ath10k_bmi_write32(ar, hi_board_ext_data_config,
				 (board_ext_data_size << 16) | 1);
	if (ret) {
314
315
		ath10k_err(ar, "could not write board ext data bit (%d)\n",
			   ret);
316
317
318
319
320
321
		return ret;
	}

	return 0;
}

322
323
static int ath10k_download_board_data(struct ath10k *ar, const void *data,
				      size_t data_len)
324
{
325
	u32 board_data_size = ar->hw_params.fw.board_size;
326
327
328
	u32 address;
	int ret;

329
	ret = ath10k_push_board_ext_data(ar, data, data_len);
330
	if (ret) {
331
		ath10k_err(ar, "could not push board ext data (%d)\n", ret);
332
333
334
335
336
		goto exit;
	}

	ret = ath10k_bmi_read32(ar, hi_board_data, &address);
	if (ret) {
337
		ath10k_err(ar, "could not read board data addr (%d)\n", ret);
338
339
340
		goto exit;
	}

341
	ret = ath10k_bmi_write_memory(ar, address, data,
342
				      min_t(u32, board_data_size,
343
					    data_len));
344
	if (ret) {
345
		ath10k_err(ar, "could not write board data (%d)\n", ret);
346
347
348
349
350
		goto exit;
	}

	ret = ath10k_bmi_write32(ar, hi_board_data_initialized, 1);
	if (ret) {
351
		ath10k_err(ar, "could not write board data bit (%d)\n", ret);
352
353
354
355
356
357
358
		goto exit;
	}

exit:
	return ret;
}

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
static int ath10k_download_cal_file(struct ath10k *ar)
{
	int ret;

	if (!ar->cal_file)
		return -ENOENT;

	if (IS_ERR(ar->cal_file))
		return PTR_ERR(ar->cal_file);

	ret = ath10k_download_board_data(ar, ar->cal_file->data,
					 ar->cal_file->size);
	if (ret) {
		ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
		return ret;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");

	return 0;
}

381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
static int ath10k_download_cal_dt(struct ath10k *ar)
{
	struct device_node *node;
	int data_len;
	void *data;
	int ret;

	node = ar->dev->of_node;
	if (!node)
		/* Device Tree is optional, don't print any warnings if
		 * there's no node for ath10k.
		 */
		return -ENOENT;

	if (!of_get_property(node, "qcom,ath10k-calibration-data",
			     &data_len)) {
		/* The calibration data node is optional */
		return -ENOENT;
	}

	if (data_len != QCA988X_CAL_DATA_LEN) {
		ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
			    data_len);
		ret = -EMSGSIZE;
		goto out;
	}

	data = kmalloc(data_len, GFP_KERNEL);
	if (!data) {
		ret = -ENOMEM;
		goto out;
	}

	ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data",
					data, data_len);
	if (ret) {
		ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
			    ret);
		goto out_free;
	}

	ret = ath10k_download_board_data(ar, data, data_len);
	if (ret) {
		ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
			    ret);
		goto out_free;
	}

	ret = 0;

out_free:
	kfree(data);

out:
	return ret;
}

438
439
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
440
	u32 result, address = ar->hw_params.patch_load_addr;
441
	u32 bmi_otp_exe_param = ar->hw_params.otp_exe_param;
442
443
	int ret;

444
	ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
445
446
447
448
449
	if (ret) {
		ath10k_err(ar, "failed to download board data: %d\n", ret);
		return ret;
	}

450
451
	/* OTP is optional */

Kalle Valo's avatar
Kalle Valo committed
452
	if (!ar->otp_data || !ar->otp_len) {
453
		ath10k_warn(ar, "Not running otp, calibration will be incorrect (otp-data %p otp_len %zd)!\n",
454
			    ar->otp_data, ar->otp_len);
455
		return 0;
Kalle Valo's avatar
Kalle Valo committed
456
457
	}

458
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot upload otp to 0x%x len %zd\n",
Kalle Valo's avatar
Kalle Valo committed
459
		   address, ar->otp_len);
460

461
	ret = ath10k_bmi_fast_download(ar, address, ar->otp_data, ar->otp_len);
462
	if (ret) {
463
		ath10k_err(ar, "could not write otp (%d)\n", ret);
Kalle Valo's avatar
Kalle Valo committed
464
		return ret;
465
466
	}

467
	ret = ath10k_bmi_execute(ar, address, bmi_otp_exe_param, &result);
468
	if (ret) {
469
		ath10k_err(ar, "could not execute otp (%d)\n", ret);
Kalle Valo's avatar
Kalle Valo committed
470
		return ret;
471
472
	}

473
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
Kalle Valo's avatar
Kalle Valo committed
474

475
476
477
	if (!(skip_otp || test_bit(ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
				   ar->fw_features))
	    && result != 0) {
478
		ath10k_err(ar, "otp calibration failed: %d", result);
Kalle Valo's avatar
Kalle Valo committed
479
480
481
482
		return -EINVAL;
	}

	return 0;
483
484
}

Kalle Valo's avatar
Kalle Valo committed
485
static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
486
{
Kalle Valo's avatar
Kalle Valo committed
487
488
489
	u32 address, data_len;
	const char *mode_name;
	const void *data;
490
491
492
493
	int ret;

	address = ar->hw_params.patch_load_addr;

Kalle Valo's avatar
Kalle Valo committed
494
495
496
497
498
	switch (mode) {
	case ATH10K_FIRMWARE_MODE_NORMAL:
		data = ar->firmware_data;
		data_len = ar->firmware_len;
		mode_name = "normal";
499
500
501
502
503
504
505
		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;
		}
Kalle Valo's avatar
Kalle Valo committed
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
		break;
	case ATH10K_FIRMWARE_MODE_UTF:
		data = ar->testmode.utf->data;
		data_len = ar->testmode.utf->size;
		mode_name = "utf";
		break;
	default:
		ath10k_err(ar, "unknown firmware mode: %d\n", mode);
		return -EINVAL;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT,
		   "boot uploading firmware image %p len %d mode %s\n",
		   data, data_len, mode_name);

	ret = ath10k_bmi_fast_download(ar, address, data, data_len);
522
	if (ret) {
Kalle Valo's avatar
Kalle Valo committed
523
524
525
		ath10k_err(ar, "failed to download %s firmware: %d\n",
			   mode_name, ret);
		return ret;
526
527
	}

528
529
530
531
532
	return ret;
}

static void ath10k_core_free_firmware_files(struct ath10k *ar)
{
533
	if (!IS_ERR(ar->board))
534
		release_firmware(ar->board);
535

536
	if (!IS_ERR(ar->otp))
537
538
		release_firmware(ar->otp);

539
	if (!IS_ERR(ar->firmware))
540
541
		release_firmware(ar->firmware);

542
	if (!IS_ERR(ar->cal_file))
543
544
		release_firmware(ar->cal_file);

545
546
	ath10k_swap_code_seg_release(ar);

547
	ar->board = NULL;
548
549
550
	ar->board_data = NULL;
	ar->board_len = 0;

551
	ar->otp = NULL;
552
553
554
	ar->otp_data = NULL;
	ar->otp_len = 0;

555
	ar->firmware = NULL;
556
557
	ar->firmware_data = NULL;
	ar->firmware_len = 0;
558
559

	ar->cal_file = NULL;
560

561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
}

static int ath10k_fetch_cal_file(struct ath10k *ar)
{
	char filename[100];

	/* cal-<bus>-<id>.bin */
	scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
		  ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));

	ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
	if (IS_ERR(ar->cal_file))
		/* calibration file is optional, don't print any warnings */
		return PTR_ERR(ar->cal_file);

	ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
		   ATH10K_FW_DIR, filename);

	return 0;
580
581
}

582
static int ath10k_core_fetch_spec_board_file(struct ath10k *ar)
583
{
584
585
586
587
588
589
590
591
592
593
594
595
	char filename[100];

	scnprintf(filename, sizeof(filename), "board-%s-%s.bin",
		  ath10k_bus_str(ar->hif.bus), ar->spec_board_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->board_data = ar->board->data;
	ar->board_len = ar->board->size;
	ar->spec_board_loaded = true;
596

597
598
599
600
601
	return 0;
}

static int ath10k_core_fetch_generic_board_file(struct ath10k *ar)
{
602
603
	if (!ar->hw_params.fw.board) {
		ath10k_err(ar, "failed to find board file fw entry\n");
604
605
606
		return -EINVAL;
	}

607
608
609
	ar->board = ath10k_fetch_fw_file(ar,
					 ar->hw_params.fw.dir,
					 ar->hw_params.fw.board);
610
611
	if (IS_ERR(ar->board))
		return PTR_ERR(ar->board);
612

613
614
	ar->board_data = ar->board->data;
	ar->board_len = ar->board->size;
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
	ar->spec_board_loaded = false;

	return 0;
}

static int ath10k_core_fetch_board_file(struct ath10k *ar)
{
	int ret;

	if (strlen(ar->spec_board_id) > 0) {
		ret = ath10k_core_fetch_spec_board_file(ar);
		if (ret) {
			ath10k_info(ar, "failed to load spec board file, falling back to generic: %d\n",
				    ret);
			goto generic;
		}

		ath10k_dbg(ar, ATH10K_DBG_BOOT, "found specific board file for %s\n",
			   ar->spec_board_id);
		return 0;
	}

generic:
	ret = ath10k_core_fetch_generic_board_file(ar);
	if (ret) {
		ath10k_err(ar, "failed to fetch generic board data: %d\n", ret);
		return ret;
	}
643

644
645
646
647
648
649
650
651
652
653
654
655
	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;
	}

656
657
658
659
660
	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);
661
		ath10k_err(ar, "could not fetch firmware (%d)\n", ret);
662
663
664
		goto err;
	}

665
666
667
	ar->firmware_data = ar->firmware->data;
	ar->firmware_len = ar->firmware->size;

668
669
670
671
672
673
674
675
676
	/* 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);
677
		ath10k_err(ar, "could not fetch otp (%d)\n", ret);
678
679
680
		goto err;
	}

681
682
683
	ar->otp_data = ar->otp->data;
	ar->otp_len = ar->otp->size;

684
685
686
687
	return 0;

err:
	ath10k_core_free_firmware_files(ar);
688
689
690
	return ret;
}

691
692
693
694
695
696
static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
{
	size_t magic_len, len, ie_len;
	int ie_id, i, index, bit, ret;
	struct ath10k_fw_ie *hdr;
	const u8 *data;
697
	__le32 *timestamp, *version;
698
699
700
701

	/* 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)) {
702
		ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n",
703
			   ar->hw_params.fw.dir, name, PTR_ERR(ar->firmware));
704
705
706
707
708
709
710
711
712
713
		return PTR_ERR(ar->firmware);
	}

	data = ar->firmware->data;
	len = ar->firmware->size;

	/* magic also includes the null byte, check that as well */
	magic_len = strlen(ATH10K_FIRMWARE_MAGIC) + 1;

	if (len < magic_len) {
714
		ath10k_err(ar, "firmware file '%s/%s' too small to contain magic: %zu\n",
715
			   ar->hw_params.fw.dir, name, len);
716
717
		ret = -EINVAL;
		goto err;
718
719
720
	}

	if (memcmp(data, ATH10K_FIRMWARE_MAGIC, magic_len) != 0) {
721
		ath10k_err(ar, "invalid firmware magic\n");
722
723
		ret = -EINVAL;
		goto err;
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
	}

	/* jump over the padding */
	magic_len = ALIGN(magic_len, 4);

	len -= magic_len;
	data += magic_len;

	/* loop elements */
	while (len > sizeof(struct ath10k_fw_ie)) {
		hdr = (struct ath10k_fw_ie *)data;

		ie_id = le32_to_cpu(hdr->id);
		ie_len = le32_to_cpu(hdr->len);

		len -= sizeof(*hdr);
		data += sizeof(*hdr);

		if (len < ie_len) {
743
			ath10k_err(ar, "invalid length for FW IE %d (%zu < %zu)\n",
744
				   ie_id, len, ie_len);
745
746
			ret = -EINVAL;
			goto err;
747
748
749
750
751
752
753
754
755
756
		}

		switch (ie_id) {
		case ATH10K_FW_IE_FW_VERSION:
			if (ie_len > sizeof(ar->hw->wiphy->fw_version) - 1)
				break;

			memcpy(ar->hw->wiphy->fw_version, data, ie_len);
			ar->hw->wiphy->fw_version[ie_len] = '\0';

757
			ath10k_dbg(ar, ATH10K_DBG_BOOT,
758
759
760
761
762
763
764
765
766
				   "found fw version %s\n",
				    ar->hw->wiphy->fw_version);
			break;
		case ATH10K_FW_IE_TIMESTAMP:
			if (ie_len != sizeof(u32))
				break;

			timestamp = (__le32 *)data;

767
			ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw timestamp %d\n",
768
769
770
				   le32_to_cpup(timestamp));
			break;
		case ATH10K_FW_IE_FEATURES:
771
			ath10k_dbg(ar, ATH10K_DBG_BOOT,
772
773
774
775
776
777
778
779
780
781
				   "found firmware features ie (%zd B)\n",
				   ie_len);

			for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {
				index = i / 8;
				bit = i % 8;

				if (index == ie_len)
					break;

782
				if (data[index] & (1 << bit)) {
783
					ath10k_dbg(ar, ATH10K_DBG_BOOT,
784
785
						   "Enabling feature bit: %i\n",
						   i);
786
					__set_bit(i, ar->fw_features);
787
				}
788
789
			}

790
			ath10k_dbg_dump(ar, ATH10K_DBG_BOOT, "features", "",
791
792
793
794
					ar->fw_features,
					sizeof(ar->fw_features));
			break;
		case ATH10K_FW_IE_FW_IMAGE:
795
			ath10k_dbg(ar, ATH10K_DBG_BOOT,
796
797
798
799
800
801
802
803
				   "found fw image ie (%zd B)\n",
				   ie_len);

			ar->firmware_data = data;
			ar->firmware_len = ie_len;

			break;
		case ATH10K_FW_IE_OTP_IMAGE:
804
			ath10k_dbg(ar, ATH10K_DBG_BOOT,
805
806
807
808
809
810
811
				   "found otp image ie (%zd B)\n",
				   ie_len);

			ar->otp_data = data;
			ar->otp_len = ie_len;

			break;
812
813
814
815
816
817
818
819
820
821
822
		case ATH10K_FW_IE_WMI_OP_VERSION:
			if (ie_len != sizeof(u32))
				break;

			version = (__le32 *)data;

			ar->wmi.op_version = le32_to_cpup(version);

			ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n",
				   ar->wmi.op_version);
			break;
823
824
825
826
827
828
829
830
831
832
833
		case ATH10K_FW_IE_HTT_OP_VERSION:
			if (ie_len != sizeof(u32))
				break;

			version = (__le32 *)data;

			ar->htt.op_version = le32_to_cpup(version);

			ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie htt op version %d\n",
				   ar->htt.op_version);
			break;
834
835
836
837
838
839
840
		case ATH10K_FW_IE_FW_CODE_SWAP_IMAGE:
			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;
			break;
841
		default:
842
			ath10k_warn(ar, "Unknown FW IE: %u\n",
843
844
845
846
847
848
849
850
851
				    le32_to_cpu(hdr->id));
			break;
		}

		/* jump over the padding */
		ie_len = ALIGN(ie_len, 4);

		len -= ie_len;
		data += ie_len;
852
	}
853
854

	if (!ar->firmware_data || !ar->firmware_len) {
855
		ath10k_warn(ar, "No ATH10K_FW_IE_FW_IMAGE found from '%s/%s', skipping\n",
856
			    ar->hw_params.fw.dir, name);
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
		ret = -ENOMEDIUM;
		goto err;
	}

	return 0;

err:
	ath10k_core_free_firmware_files(ar);
	return ret;
}

static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
{
	int ret;

872
873
874
	/* calibration file is optional, don't check for any errors */
	ath10k_fetch_cal_file(ar);

875
876
877
878
879
880
	ret = ath10k_core_fetch_board_file(ar);
	if (ret) {
		ath10k_err(ar, "failed to fetch board file: %d\n", ret);
		return ret;
	}

Kalle Valo's avatar
Kalle Valo committed
881
882
883
884
885
886
887
	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);
	if (ret == 0)
		goto success;

888
889
890
891
892
893
894
	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);
	if (ret == 0)
		goto success;

895
	ar->fw_api = 3;
896
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
897
898
899
900
901

	ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE);
	if (ret == 0)
		goto success;

902
	ar->fw_api = 2;
903
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
904

905
	ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE);
906
907
908
909
	if (ret == 0)
		goto success;

	ar->fw_api = 1;
910
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
911
912
913
914
915

	ret = ath10k_core_fetch_firmware_api_1(ar);
	if (ret)
		return ret;

916
success:
917
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
918
919
920
921

	return 0;
}

922
static int ath10k_download_cal_data(struct ath10k *ar)
923
924
925
{
	int ret;

926
927
928
929
930
931
932
	ret = ath10k_download_cal_file(ar);
	if (ret == 0) {
		ar->cal_mode = ATH10K_CAL_MODE_FILE;
		goto done;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT,
933
934
935
936
937
938
939
940
941
942
943
		   "boot did not find a calibration file, try DT next: %d\n",
		   ret);

	ret = ath10k_download_cal_dt(ar);
	if (ret == 0) {
		ar->cal_mode = ATH10K_CAL_MODE_DT;
		goto done;
	}

	ath10k_dbg(ar, ATH10K_DBG_BOOT,
		   "boot did not find DT entry, try OTP next: %d\n",
944
945
		   ret);

946
	ret = ath10k_download_and_run_otp(ar);
947
	if (ret) {
948
		ath10k_err(ar, "failed to run otp: %d\n", ret);
949
		return ret;
950
	}
951

952
953
954
955
956
957
	ar->cal_mode = ATH10K_CAL_MODE_OTP;

done:
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
		   ath10k_cal_mode_str(ar->cal_mode));
	return 0;
958
959
960
961
962
963
964
965
966
967
968
969
}

static int ath10k_init_uart(struct ath10k *ar)
{
	int ret;

	/*
	 * Explicitly setting UART prints to zero as target turns it on
	 * based on scratch registers.
	 */
	ret = ath10k_bmi_write32(ar, hi_serial_enable, 0);
	if (ret) {
970
		ath10k_warn(ar, "could not disable UART prints (%d)\n", ret);
971
972
973
		return ret;
	}

974
	if (!uart_print)
975
976
		return 0;

977
	ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin);
978
	if (ret) {
979
		ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
980
981
982
983
984
		return ret;
	}

	ret = ath10k_bmi_write32(ar, hi_serial_enable, 1);
	if (ret) {
985
		ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
986
987
988
		return ret;
	}

989
990
991
	/* Set the UART baud rate to 19200. */
	ret = ath10k_bmi_write32(ar, hi_desired_baud_rate, 19200);
	if (ret) {
992
		ath10k_warn(ar, "could not set the baud rate (%d)\n", ret);
993
994
995
		return ret;
	}

996
	ath10k_info(ar, "UART prints enabled\n");
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
	return 0;
}

static int ath10k_init_hw_params(struct ath10k *ar)
{
	const struct ath10k_hw_params *uninitialized_var(hw_params);
	int i;

	for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
		hw_params = &ath10k_hw_params_list[i];

		if (hw_params->id == ar->target_version)
			break;
	}

	if (i == ARRAY_SIZE(ath10k_hw_params_list)) {
1013
		ath10k_err(ar, "Unsupported hardware version: 0x%x\n",
1014
1015
1016
1017
1018
1019
			   ar->target_version);
		return -EINVAL;
	}

	ar->hw_params = *hw_params;

1020
	ath10k_dbg(ar, ATH10K_DBG_BOOT, "Hardware name %s version 0x%x\n",
1021
		   ar->hw_params.name, ar->target_version);
1022
1023
1024
1025

	return 0;
}

1026
1027
1028
1029
static void ath10k_core_restart(struct work_struct *work)
{
	struct ath10k *ar = container_of(work, struct ath10k, restart_work);

Michal Kazior's avatar
Michal Kazior committed
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
	set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);

	/* Place a barrier to make sure the compiler doesn't reorder
	 * CRASH_FLUSH and calling other functions.
	 */
	barrier();

	ieee80211_stop_queues(ar->hw);
	ath10k_drain_tx(ar);
	complete_all(&ar->scan.started);
	complete_all(&ar->scan.completed);
	complete_all(&ar->scan.on_channel);
	complete_all(&ar->offchan_tx_completed);
	complete_all(&ar->install_key_done);
	complete_all(&ar->vdev_setup_done);
1045
	complete_all(&ar->thermal.wmi_sync);
Michal Kazior's avatar
Michal Kazior committed
1046
1047
1048
1049
	wake_up(&ar->htt.empty_tx_wq);
	wake_up(&ar->wmi.tx_credits_wq);
	wake_up(&ar->peer_mapping_wq);

1050
1051
1052
1053
1054
	mutex_lock(&ar->conf_mutex);

	switch (ar->state) {
	case ATH10K_STATE_ON:
		ar->state = ATH10K_STATE_RESTARTING;
1055
		ath10k_hif_stop(ar);
1056
		ath10k_scan_finish(ar);
1057
1058
1059
		ieee80211_restart_hw(ar->hw);
		break;
	case ATH10K_STATE_OFF:
1060
1061
		/* this can happen if driver is being unloaded
		 * or if the crash happens during FW probing */
1062
		ath10k_warn(ar, "cannot restart a device that hasn't been started\n");
1063
1064
		break;
	case ATH10K_STATE_RESTARTING:
1065
1066
		/* hw restart might be requested from multiple places */
		break;
1067
1068
1069
1070
	case ATH10K_STATE_RESTARTED:
		ar->state = ATH10K_STATE_WEDGED;
		/* fall through */
	case ATH10K_STATE_WEDGED:
1071
		ath10k_warn(ar, "device is wedged, will not restart\n");
1072
		break;
Kalle Valo's avatar
Kalle Valo committed
1073
1074
1075
	case ATH10K_STATE_UTF:
		ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
		break;
1076
1077
1078
1079
1080
	}

	mutex_unlock(&ar->conf_mutex);
}

1081
static int ath10k_core_init_firmware_features(struct ath10k *ar)
1082
{
1083
1084
1085
1086
1087
1088
	if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
	    !test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
		ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
		return -EINVAL;
	}

1089
1090
1091
1092
1093
1094
	if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {
		ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n",
			   ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version);
		return -EINVAL;
	}

1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
	ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_NATIVE_WIFI;
	switch (ath10k_cryptmode_param) {
	case ATH10K_CRYPT_MODE_HW:
		clear_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
		clear_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
		break;
	case ATH10K_CRYPT_MODE_SW:
		if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
			      ar->fw_features)) {
			ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware");
			return -EINVAL;
		}

		set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
		set_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
		break;
	default:
		ath10k_info(ar, "invalid cryptmode: %d\n",
			    ath10k_cryptmode_param);
		return -EINVAL;
	}

	ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
	ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;

	if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
		ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;

		/* Workaround:
		 *
		 * Firmware A-MSDU aggregation breaks with RAW Tx encap mode
		 * and causes enormous performance issues (malformed frames,
		 * etc).
		 *
		 * Disabling A-MSDU makes RAW mode stable with heavy traffic
		 * albeit a bit slower compared to regular operation.
		 */
		ar->htt.max_num_amsdu = 1;
	}

1135
1136
1137
1138
1139
	/* Backwards compatibility for firmwares without
	 * ATH10K_FW_IE_WMI_OP_VERSION.
	 */
	if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {
		if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
1140
1141
			if (test_bit(ATH10K_FW_FEATURE_WMI_10_2,
				     ar->fw_features))
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
				ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2;
			else
				ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
		} else {
			ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;
		}
	}

	switch (ar->wmi.op_version) {
	case ATH10K_FW_WMI_OP_VERSION_MAIN:
1152
1153
		ar->max_num_peers = TARGET_NUM_PEERS;
		ar->max_num_stations = TARGET_NUM_STATIONS;
1154
		ar->max_num_vdevs = TARGET_NUM_VDEVS;
1155
		ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
1156
1157
		ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
			WMI_STAT_PEER;
1158
		ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
1159
1160
1161
		break;
	case ATH10K_FW_WMI_OP_VERSION_10_1:
	case ATH10K_FW_WMI_OP_VERSION_10_2:
1162
	case ATH10K_FW_WMI_OP_VERSION_10_2_4:
1163
1164
		ar->max_num_peers = TARGET_10X_NUM_PEERS;
		ar->max_num_stations = TARGET_10X_NUM_STATIONS;
1165
		ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
1166
		ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
1167
		ar->fw_stats_req_mask = WMI_STAT_PEER;
1168
		ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
1169
		break;
1170
1171
1172
	case ATH10K_FW_WMI_OP_VERSION_TLV:
		ar->max_num_peers = TARGET_TLV_NUM_PEERS;
		ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
1173
		ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS;
1174
		ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS;
1175
		ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
1176
		ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS;
1177
1178
		ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV |
			WMI_STAT_PEER;
1179
		ar->max_spatial_stream = WMI_MAX_SPATIAL_STREAM;
1180
		break;
1181
	case ATH10K_FW_WMI_OP_VERSION_10_4:
1182
1183
1184
1185
1186
		ar->max_num_peers = TARGET_10_4_NUM_PEERS;
		ar->max_num_stations = TARGET_10_4_NUM_STATIONS;
		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;
1187
		ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
1188
		ar->fw_stats_req_mask = WMI_STAT_PEER;
1189
		ar->max_spatial_stream = WMI_10_4_MAX_SPATIAL_STREAM;
1190
		break;
1191
1192
1193
1194
	case ATH10K_FW_WMI_OP_VERSION_UNSET:
	case ATH10K_FW_WMI_OP_VERSION_MAX:
		WARN_ON(1);
		return -EINVAL;
1195
	}
1196

1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
	/* Backwards compatibility for firmwares without
	 * ATH10K_FW_IE_HTT_OP_VERSION.
	 */
	if (ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_UNSET) {
		switch (ar->wmi.op_version) {
		case ATH10K_FW_WMI_OP_VERSION_MAIN:
			ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_MAIN;
			break;
		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:
			ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_10_1;
			break;
		case ATH10K_FW_WMI_OP_VERSION_TLV:
			ar->htt.op_version = ATH10K_FW_HTT_OP_VERSION_TLV;
			break;
1213
		case ATH10K_FW_WMI_OP_VERSION_10_4:
1214
1215
1216
1217
1218
1219
1220
		case ATH10K_FW_WMI_OP_VERSION_UNSET:
		case ATH10K_FW_WMI_OP_VERSION_MAX:
			WARN_ON(1);
			return -EINVAL;
		}
	}

1221
	return 0;
1222
1223
}

Kalle Valo's avatar
Kalle Valo committed
1224
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
1225
1226
1227
{
	int status;

1228
1229
	lockdep_assert_held(&ar->conf_mutex);

Michal Kazior's avatar
Michal Kazior committed
1230
1231
	clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);

1232
1233
	ath10k_bmi_start(ar);

1234
1235
1236
1237
1238
	if (ath10k_init_configure_target(ar)) {
		status = -EINVAL;
		goto err;
	}

1239
1240