View | Details | Raw Unified | Return to bug 203709 | Differences between
and this patch

Collapse All | Expand All

(-)a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c (-287 lines)
Lines 61-67 Link Here
61
#include "iwl-drv.h"
61
#include "iwl-drv.h"
62
#include "iwl-debug.h"
62
#include "iwl-debug.h"
63
#include "acpi.h"
63
#include "acpi.h"
64
#include "fw/runtime.h"
65
64
66
void *iwl_acpi_get_object(struct device *dev, acpi_string method)
65
void *iwl_acpi_get_object(struct device *dev, acpi_string method)
67
{
66
{
Lines 246-534 int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) Link Here
246
	return ret;
245
	return ret;
247
}
246
}
248
IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);
247
IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);
249
250
int iwl_sar_set_profile(union acpi_object *table,
251
			struct iwl_sar_profile *profile,
252
			bool enabled)
253
{
254
	int i;
255
256
	profile->enabled = enabled;
257
258
	for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
259
		if (table[i].type != ACPI_TYPE_INTEGER ||
260
		    table[i].integer.value > U8_MAX)
261
			return -EINVAL;
262
263
		profile->table[i] = table[i].integer.value;
264
	}
265
266
	return 0;
267
}
268
IWL_EXPORT_SYMBOL(iwl_sar_set_profile);
269
270
int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
271
			   __le16 per_chain_restriction[][IWL_NUM_SUB_BANDS],
272
			   int prof_a, int prof_b)
273
{
274
	int i, j, idx;
275
	int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
276
277
	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2);
278
	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS !=
279
		     ACPI_SAR_TABLE_SIZE);
280
281
	for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
282
		struct iwl_sar_profile *prof;
283
284
		/* don't allow SAR to be disabled (profile 0 means disable) */
285
		if (profs[i] == 0)
286
			return -EPERM;
287
288
		/* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
289
		if (profs[i] > ACPI_SAR_PROFILE_NUM)
290
			return -EINVAL;
291
292
		/* profiles go from 1 to 4, so decrement to access the array */
293
		prof = &fwrt->sar_profiles[profs[i] - 1];
294
295
		/* if the profile is disabled, do nothing */
296
		if (!prof->enabled) {
297
			IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n",
298
					profs[i]);
299
			/* if one of the profiles is disabled, we fail all */
300
			return -ENOENT;
301
		}
302
		IWL_DEBUG_INFO(fwrt,
303
			       "SAR EWRD: chain %d profile index %d\n",
304
			       i, profs[i]);
305
		IWL_DEBUG_RADIO(fwrt, "  Chain[%d]:\n", i);
306
		for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
307
			idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
308
			per_chain_restriction[i][j] =
309
				cpu_to_le16(prof->table[idx]);
310
			IWL_DEBUG_RADIO(fwrt, "    Band[%d] = %d * .125dBm\n",
311
					j, prof->table[idx]);
312
		}
313
	}
314
315
	return 0;
316
}
317
IWL_EXPORT_SYMBOL(iwl_sar_select_profile);
318
319
int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
320
{
321
	union acpi_object *wifi_pkg, *table, *data;
322
	bool enabled;
323
	int ret, tbl_rev;
324
325
	data = iwl_acpi_get_object(fwrt->dev, ACPI_WRDS_METHOD);
326
	if (IS_ERR(data))
327
		return PTR_ERR(data);
328
329
	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
330
					 ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev);
331
	if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
332
		ret = PTR_ERR(wifi_pkg);
333
		goto out_free;
334
	}
335
336
	if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) {
337
		ret = -EINVAL;
338
		goto out_free;
339
	}
340
341
	enabled = !!(wifi_pkg->package.elements[1].integer.value);
342
343
	/* position of the actual table */
344
	table = &wifi_pkg->package.elements[2];
345
346
	/* The profile from WRDS is officially profile 1, but goes
347
	 * into sar_profiles[0] (because we don't have a profile 0).
348
	 */
349
	ret = iwl_sar_set_profile(table, &fwrt->sar_profiles[0], enabled);
350
out_free:
351
	kfree(data);
352
	return ret;
353
}
354
IWL_EXPORT_SYMBOL(iwl_sar_get_wrds_table);
355
356
int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
357
{
358
	union acpi_object *wifi_pkg, *data;
359
	bool enabled;
360
	int i, n_profiles, tbl_rev, pos;
361
	int ret = 0;
362
363
	data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD);
364
	if (IS_ERR(data))
365
		return PTR_ERR(data);
366
367
	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
368
					 ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev);
369
	if (IS_ERR(wifi_pkg) || tbl_rev != 0) {
370
		ret = PTR_ERR(wifi_pkg);
371
		goto out_free;
372
	}
373
374
	if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
375
	    wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) {
376
		ret = -EINVAL;
377
		goto out_free;
378
	}
379
380
	enabled = !!(wifi_pkg->package.elements[1].integer.value);
381
	n_profiles = wifi_pkg->package.elements[2].integer.value;
382
383
	/*
384
	 * Check the validity of n_profiles.  The EWRD profiles start
385
	 * from index 1, so the maximum value allowed here is
386
	 * ACPI_SAR_PROFILES_NUM - 1.
387
	 */
388
	if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
389
		ret = -EINVAL;
390
		goto out_free;
391
	}
392
393
	/* the tables start at element 3 */
394
	pos = 3;
395
396
	for (i = 0; i < n_profiles; i++) {
397
		/* The EWRD profiles officially go from 2 to 4, but we
398
		 * save them in sar_profiles[1-3] (because we don't
399
		 * have profile 0).  So in the array we start from 1.
400
		 */
401
		ret = iwl_sar_set_profile(&wifi_pkg->package.elements[pos],
402
					  &fwrt->sar_profiles[i + 1],
403
					  enabled);
404
		if (ret < 0)
405
			break;
406
407
		/* go to the next table */
408
		pos += ACPI_SAR_TABLE_SIZE;
409
	}
410
411
out_free:
412
	kfree(data);
413
	return ret;
414
}
415
IWL_EXPORT_SYMBOL(iwl_sar_get_ewrd_table);
416
417
int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
418
{
419
	union acpi_object *wifi_pkg, *data;
420
	int i, j, ret, tbl_rev;
421
	int idx = 1;
422
423
	data = iwl_acpi_get_object(fwrt->dev, ACPI_WGDS_METHOD);
424
	if (IS_ERR(data))
425
		return PTR_ERR(data);
426
427
	wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data,
428
					 ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev);
429
	if (IS_ERR(wifi_pkg) || tbl_rev > 1) {
430
		ret = PTR_ERR(wifi_pkg);
431
		goto out_free;
432
	}
433
434
	fwrt->geo_rev = tbl_rev;
435
	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
436
		for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
437
			union acpi_object *entry;
438
439
			entry = &wifi_pkg->package.elements[idx++];
440
			if (entry->type != ACPI_TYPE_INTEGER ||
441
			    entry->integer.value > U8_MAX) {
442
				ret = -EINVAL;
443
				goto out_free;
444
			}
445
446
			fwrt->geo_profiles[i].values[j] = entry->integer.value;
447
		}
448
	}
449
	ret = 0;
450
out_free:
451
	kfree(data);
452
	return ret;
453
}
454
IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table);
455
456
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
457
{
458
	/*
459
	 * The GEO_TX_POWER_LIMIT command is not supported on earlier
460
	 * firmware versions.  Unfortunately, we don't have a TLV API
461
	 * flag to rely on, so rely on the major version which is in
462
	 * the first byte of ucode_ver.  This was implemented
463
	 * initially on version 38 and then backported to 17.  It was
464
	 * also backported to 29, but only for 7265D devices.  The
465
	 * intention was to have it in 36 as well, but not all 8000
466
	 * family got this feature enabled.  The 8000 family is the
467
	 * only one using version 36, so skip this version entirely.
468
	 */
469
	return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 ||
470
	       IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 ||
471
	       (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 &&
472
		((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
473
		 CSR_HW_REV_TYPE_7265D));
474
}
475
IWL_EXPORT_SYMBOL(iwl_sar_geo_support);
476
477
int iwl_validate_sar_geo_profile(struct iwl_fw_runtime *fwrt,
478
				 struct iwl_host_cmd *cmd)
479
{
480
	struct iwl_geo_tx_power_profiles_resp *resp;
481
	int ret;
482
483
	resp = (void *)cmd->resp_pkt->data;
484
	ret = le32_to_cpu(resp->profile_idx);
485
	if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) {
486
		ret = -EIO;
487
		IWL_WARN(fwrt, "Invalid geographic profile idx (%d)\n", ret);
488
	}
489
490
	return ret;
491
}
492
IWL_EXPORT_SYMBOL(iwl_validate_sar_geo_profile);
493
494
void iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
495
		      struct iwl_per_chain_offset_group *table)
496
{
497
	int ret, i, j;
498
499
	if (!iwl_sar_geo_support(fwrt))
500
		return;
501
502
	ret = iwl_sar_get_wgds_table(fwrt);
503
	if (ret < 0) {
504
		IWL_DEBUG_RADIO(fwrt,
505
				"Geo SAR BIOS table invalid or unavailable. (%d)\n",
506
				ret);
507
		/* we don't fail if the table is not available */
508
		return;
509
	}
510
511
	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
512
		     ACPI_WGDS_TABLE_SIZE + 1 !=  ACPI_WGDS_WIFI_DATA_SIZE);
513
514
	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
515
516
	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
517
		struct iwl_per_chain_offset *chain =
518
			(struct iwl_per_chain_offset *)&table[i];
519
520
		for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
521
			u8 *value;
522
523
			value = &fwrt->geo_profiles[i].values[j *
524
				ACPI_GEO_PER_CHAIN_SIZE];
525
			chain[j].max_tx_power = cpu_to_le16(value[0]);
526
			chain[j].chain_a = value[1];
527
			chain[j].chain_b = value[2];
528
			IWL_DEBUG_RADIO(fwrt,
529
					"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
530
					i, j, value[1], value[2], value[0]);
531
		}
532
	}
533
}
534
IWL_EXPORT_SYMBOL(iwl_sar_geo_init);
(-)a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h (-84 lines)
Lines 61-72 Link Here
61
#define __iwl_fw_acpi__
61
#define __iwl_fw_acpi__
62
62
63
#include <linux/acpi.h>
63
#include <linux/acpi.h>
64
#include "fw/api/commands.h"
65
#include "fw/api/power.h"
66
#include "fw/api/phy.h"
67
#include "fw/img.h"
68
#include "iwl-trans.h"
69
70
64
71
#define ACPI_WRDS_METHOD	"WRDS"
65
#define ACPI_WRDS_METHOD	"WRDS"
72
#define ACPI_EWRD_METHOD	"EWRD"
66
#define ACPI_EWRD_METHOD	"EWRD"
Lines 110-130 Link Here
110
#define ACPI_PPAG_MIN_HB -16
104
#define ACPI_PPAG_MIN_HB -16
111
#define ACPI_PPAG_MAX_HB 40
105
#define ACPI_PPAG_MAX_HB 40
112
106
113
struct iwl_sar_profile {
114
	bool enabled;
115
	u8 table[ACPI_SAR_TABLE_SIZE];
116
};
117
118
struct iwl_geo_profile {
119
	u8 values[ACPI_GEO_TABLE_SIZE];
120
};
121
122
#ifdef CONFIG_ACPI
107
#ifdef CONFIG_ACPI
123
108
124
struct iwl_fw_runtime;
125
126
void *iwl_acpi_get_object(struct device *dev, acpi_string method);
109
void *iwl_acpi_get_object(struct device *dev, acpi_string method);
127
128
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
110
union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
129
					 union acpi_object *data,
111
					 union acpi_object *data,
130
					 int data_size, int *tbl_rev);
112
					 int data_size, int *tbl_rev);
Lines 152-178 u64 iwl_acpi_get_pwr_limit(struct device *dev); Link Here
152
 */
134
 */
153
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk);
135
int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk);
154
136
155
int iwl_sar_set_profile(union acpi_object *table,
156
			struct iwl_sar_profile *profile,
157
			bool enabled);
158
159
int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
160
			   __le16 per_chain_restriction[][IWL_NUM_SUB_BANDS],
161
			   int prof_a, int prof_b);
162
163
int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt);
164
165
int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt);
166
167
int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt);
168
169
bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt);
170
171
int iwl_validate_sar_geo_profile(struct iwl_fw_runtime *fwrt,
172
				 struct iwl_host_cmd *cmd);
173
174
void iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
175
		      struct iwl_per_chain_offset_group *table);
176
#else /* CONFIG_ACPI */
137
#else /* CONFIG_ACPI */
177
138
178
static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
139
static inline void *iwl_acpi_get_object(struct device *dev, acpi_string method)
Lines 203-252 static inline int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) Link Here
203
	return -ENOENT;
164
	return -ENOENT;
204
}
165
}
205
166
206
static inline int iwl_sar_set_profile(union acpi_object *table,
207
				      struct iwl_sar_profile *profile,
208
				      bool enabled)
209
{
210
	return -ENOENT;
211
}
212
213
static inline int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt,
214
			   __le16 per_chain_restriction[][IWL_NUM_SUB_BANDS],
215
			   int prof_a, int prof_b)
216
{
217
	return -ENOENT;
218
}
219
220
static inline int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt)
221
{
222
	return -ENOENT;
223
}
224
225
static inline int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt)
226
{
227
	return -ENOENT;
228
}
229
230
static inline int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt)
231
{
232
	return -ENOENT;
233
}
234
235
static inline bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt)
236
{
237
	return false;
238
}
239
240
static inline int iwl_validate_sar_geo_profile(struct iwl_fw_runtime *fwrt,
241
					       struct iwl_host_cmd *cmd)
242
{
243
	return -ENOENT;
244
}
245
246
static inline void iwl_sar_geo_init(struct iwl_fw_runtime *fwrt,
247
				    struct iwl_per_chain_offset_group *table)
248
{
249
}
250
251
#endif /* CONFIG_ACPI */
167
#endif /* CONFIG_ACPI */
252
#endif /* __iwl_fw_acpi__ */
168
#endif /* __iwl_fw_acpi__ */
(-)a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h (-11 lines)
Lines 65-73 Link Here
65
#include "img.h"
65
#include "img.h"
66
#include "fw/api/debug.h"
66
#include "fw/api/debug.h"
67
#include "fw/api/paging.h"
67
#include "fw/api/paging.h"
68
#include "fw/api/power.h"
69
#include "iwl-eeprom-parse.h"
68
#include "iwl-eeprom-parse.h"
70
#include "fw/acpi.h"
71
69
72
#define IWL_FW_DBG_DOMAIN		IWL_FW_INI_DOMAIN_ALWAYS_ON
70
#define IWL_FW_DBG_DOMAIN		IWL_FW_INI_DOMAIN_ALWAYS_ON
73
71
Lines 205-220 struct iwl_fw_runtime { Link Here
205
		u32 delay;
203
		u32 delay;
206
		u64 seq;
204
		u64 seq;
207
	} timestamp;
205
	} timestamp;
208
	bool tpc_enabled;
209
#endif /* CONFIG_IWLWIFI_DEBUGFS */
206
#endif /* CONFIG_IWLWIFI_DEBUGFS */
210
#ifdef CONFIG_ACPI
211
	struct iwl_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
212
	u8 sar_chain_a_profile;
213
	u8 sar_chain_b_profile;
214
	struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
215
	u32 geo_rev;
216
	struct iwl_ppag_table_cmd ppag_table;
217
#endif
218
};
207
};
219
208
220
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
209
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
(-)a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c (-1 / +1 lines)
Lines 378-384 static ssize_t iwl_dbgfs_sar_geo_profile_read(struct file *file, Link Here
378
		pos = scnprintf(buf, bufsz,
378
		pos = scnprintf(buf, bufsz,
379
				"SAR geographic profile disabled\n");
379
				"SAR geographic profile disabled\n");
380
	} else {
380
	} else {
381
		value = &mvm->fwrt.geo_profiles[tbl_idx - 1].values[0];
381
		value = &mvm->geo_profiles[tbl_idx - 1].values[0];
382
382
383
		pos += scnprintf(buf + pos, bufsz - pos,
383
		pos += scnprintf(buf + pos, bufsz - pos,
384
				 "Use geographic profile %d\n", tbl_idx);
384
				 "Use geographic profile %d\n", tbl_idx);
(-)a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c (-45 / +326 lines)
Lines 678-691 static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) Link Here
678
}
678
}
679
679
680
#ifdef CONFIG_ACPI
680
#ifdef CONFIG_ACPI
681
static inline int iwl_mvm_sar_set_profile(struct iwl_mvm *mvm,
682
					  union acpi_object *table,
683
					  struct iwl_mvm_sar_profile *profile,
684
					  bool enabled)
685
{
686
	int i;
687
688
	profile->enabled = enabled;
689
690
	for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) {
691
		if ((table[i].type != ACPI_TYPE_INTEGER) ||
692
		    (table[i].integer.value > U8_MAX))
693
			return -EINVAL;
694
695
		profile->table[i] = table[i].integer.value;
696
	}
697
698
	return 0;
699
}
700
701
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
702
{
703
	union acpi_object *wifi_pkg, *table, *data;
704
	bool enabled;
705
	int ret, tbl_rev;
706
707
	data = iwl_acpi_get_object(mvm->dev, ACPI_WRDS_METHOD);
708
	if (IS_ERR(data))
709
		return PTR_ERR(data);
710
711
	wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
712
					 ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev);
713
	if (IS_ERR(wifi_pkg)) {
714
		ret = PTR_ERR(wifi_pkg);
715
		goto out_free;
716
	}
717
718
	if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
719
	    tbl_rev != 0) {
720
		ret = -EINVAL;
721
		goto out_free;
722
	}
723
724
	enabled = !!(wifi_pkg->package.elements[1].integer.value);
725
726
	/* position of the actual table */
727
	table = &wifi_pkg->package.elements[2];
728
729
	/* The profile from WRDS is officially profile 1, but goes
730
	 * into sar_profiles[0] (because we don't have a profile 0).
731
	 */
732
	ret = iwl_mvm_sar_set_profile(mvm, table, &mvm->sar_profiles[0],
733
				      enabled);
734
out_free:
735
	kfree(data);
736
	return ret;
737
}
738
739
static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
740
{
741
	union acpi_object *wifi_pkg, *data;
742
	bool enabled;
743
	int i, n_profiles, ret, tbl_rev;
744
745
	data = iwl_acpi_get_object(mvm->dev, ACPI_EWRD_METHOD);
746
	if (IS_ERR(data))
747
		return PTR_ERR(data);
748
749
	wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
750
					 ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev);
751
	if (IS_ERR(wifi_pkg)) {
752
		ret = PTR_ERR(wifi_pkg);
753
		goto out_free;
754
	}
755
756
	if ((wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) ||
757
	    (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) ||
758
	    tbl_rev != 0) {
759
		ret = -EINVAL;
760
		goto out_free;
761
	}
762
763
	enabled = !!(wifi_pkg->package.elements[1].integer.value);
764
	n_profiles = wifi_pkg->package.elements[2].integer.value;
765
766
	/*
767
	 * Check the validity of n_profiles.  The EWRD profiles start
768
	 * from index 1, so the maximum value allowed here is
769
	 * ACPI_SAR_PROFILES_NUM - 1.
770
	 */
771
	if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) {
772
		ret = -EINVAL;
773
		goto out_free;
774
	}
775
776
	for (i = 0; i < n_profiles; i++) {
777
		/* the tables start at element 3 */
778
		int pos = 3;
779
780
		/* The EWRD profiles officially go from 2 to 4, but we
781
		 * save them in sar_profiles[1-3] (because we don't
782
		 * have profile 0).  So in the array we start from 1.
783
		 */
784
		ret = iwl_mvm_sar_set_profile(mvm,
785
					      &wifi_pkg->package.elements[pos],
786
					      &mvm->sar_profiles[i + 1],
787
					      enabled);
788
		if (ret < 0)
789
			break;
790
791
		/* go to the next table */
792
		pos += ACPI_SAR_TABLE_SIZE;
793
	}
794
795
out_free:
796
	kfree(data);
797
	return ret;
798
}
799
800
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
801
{
802
	union acpi_object *wifi_pkg, *data;
803
	int i, j, ret, tbl_rev;
804
	int idx = 1;
805
806
	data = iwl_acpi_get_object(mvm->dev, ACPI_WGDS_METHOD);
807
	if (IS_ERR(data))
808
		return PTR_ERR(data);
809
810
	wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
811
					 ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev);
812
	if (IS_ERR(wifi_pkg)) {
813
		ret = PTR_ERR(wifi_pkg);
814
		goto out_free;
815
	}
816
817
	if (tbl_rev != 0) {
818
		ret = -EINVAL;
819
		goto out_free;
820
	}
821
822
	mvm->geo_rev = tbl_rev;
823
	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
824
		for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) {
825
			union acpi_object *entry;
826
827
			entry = &wifi_pkg->package.elements[idx++];
828
			if ((entry->type != ACPI_TYPE_INTEGER) ||
829
			    (entry->integer.value > U8_MAX)) {
830
				ret = -EINVAL;
831
				goto out_free;
832
			}
833
834
			mvm->geo_profiles[i].values[j] = entry->integer.value;
835
		}
836
	}
837
	ret = 0;
838
out_free:
839
	kfree(data);
840
	return ret;
841
}
842
681
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
843
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
682
{
844
{
683
	union {
845
	union {
684
		struct iwl_dev_tx_power_cmd v5;
846
		struct iwl_dev_tx_power_cmd v5;
685
		struct iwl_dev_tx_power_cmd_v4 v4;
847
		struct iwl_dev_tx_power_cmd_v4 v4;
686
	} cmd;
848
	} cmd;
849
	int i, j, idx;
850
	int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b };
851
	int len;
687
852
688
	u16 len = 0;
853
	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS < 2);
854
	BUILD_BUG_ON(ACPI_SAR_NUM_CHAIN_LIMITS * ACPI_SAR_NUM_SUB_BANDS !=
855
		     ACPI_SAR_TABLE_SIZE);
689
856
690
	cmd.v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS);
857
	cmd.v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS);
691
858
Lines 694-769 int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) Link Here
694
		len = sizeof(cmd.v5);
861
		len = sizeof(cmd.v5);
695
	else if (fw_has_capa(&mvm->fw->ucode_capa,
862
	else if (fw_has_capa(&mvm->fw->ucode_capa,
696
			     IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
863
			     IWL_UCODE_TLV_CAPA_TX_POWER_ACK))
697
		len = sizeof(struct iwl_dev_tx_power_cmd_v4);
864
		len = sizeof(cmd.v4);
698
	else
865
	else
699
		len = sizeof(cmd.v4.v3);
866
		len = sizeof(cmd.v4.v3);
700
867
868
	for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) {
869
		struct iwl_mvm_sar_profile *prof;
870
871
		/* don't allow SAR to be disabled (profile 0 means disable) */
872
		if (profs[i] == 0)
873
			return -EPERM;
874
875
		/* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */
876
		if (profs[i] > ACPI_SAR_PROFILE_NUM)
877
			return -EINVAL;
878
879
		/* profiles go from 1 to 4, so decrement to access the array */
880
		prof = &mvm->sar_profiles[profs[i] - 1];
881
882
		/* if the profile is disabled, do nothing */
883
		if (!prof->enabled) {
884
			IWL_DEBUG_RADIO(mvm, "SAR profile %d is disabled.\n",
885
					profs[i]);
886
			/* if one of the profiles is disabled, we fail all */
887
			return -ENOENT;
888
		}
889
890
		IWL_DEBUG_INFO(mvm,
891
			       "SAR EWRD: chain %d profile index %d\n",
892
			       i, profs[i]);
893
		IWL_DEBUG_RADIO(mvm, "  Chain[%d]:\n", i);
894
		for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS; j++) {
895
			idx = (i * ACPI_SAR_NUM_SUB_BANDS) + j;
896
			cmd.v5.v3.per_chain_restriction[i][j] =
897
				cpu_to_le16(prof->table[idx]);
898
			IWL_DEBUG_RADIO(mvm, "    Band[%d] = %d * .125dBm\n",
899
					j, prof->table[idx]);
900
		}
901
	}
701
902
702
	if (iwl_sar_select_profile(&mvm->fwrt, cmd.v5.v3.per_chain_restriction,
703
				   prof_a, prof_b))
704
		return -ENOENT;
705
	IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
903
	IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n");
904
706
	return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
905
	return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
707
}
906
}
708
907
908
static bool iwl_mvm_sar_geo_support(struct iwl_mvm *mvm)
909
{
910
	/*
911
	 * The GEO_TX_POWER_LIMIT command is not supported on earlier
912
	 * firmware versions.  Unfortunately, we don't have a TLV API
913
	 * flag to rely on, so rely on the major version which is in
914
	 * the first byte of ucode_ver.  This was implemented
915
	 * initially on version 38 and then backported to 17.  It was
916
	 * also backported to 29, but only for 7265D devices.  The
917
	 * intention was to have it in 36 as well, but not all 8000
918
	 * family got this feature enabled.  The 8000 family is the
919
	 * only one using version 36, so skip this version entirely.
920
	 */
921
	return IWL_UCODE_SERIAL(mvm->fw->ucode_ver) >= 38 ||
922
	       IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 17 ||
923
	       (IWL_UCODE_SERIAL(mvm->fw->ucode_ver) == 29 &&
924
		((mvm->trans->hw_rev & CSR_HW_REV_TYPE_MSK) ==
925
		 CSR_HW_REV_TYPE_7265D));
926
}
927
709
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
928
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
710
{
929
{
711
	union geo_tx_power_profiles_cmd geo_tx_cmd;
930
	struct iwl_geo_tx_power_profiles_resp *resp;
712
	u16 len;
713
	int ret;
931
	int ret;
932
	u16 len;
933
	void *data;
934
	struct iwl_geo_tx_power_profiles_cmd geo_cmd;
935
	struct iwl_geo_tx_power_profiles_cmd_v1 geo_cmd_v1;
714
	struct iwl_host_cmd cmd;
936
	struct iwl_host_cmd cmd;
715
937
716
	if (fw_has_api(&mvm->fwrt.fw->ucode_capa,
938
	if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
717
		       IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
939
		geo_cmd.ops =
718
		geo_tx_cmd.geo_cmd.ops =
719
			cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
940
			cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
720
		len = sizeof(geo_tx_cmd.geo_cmd);
941
		len = sizeof(geo_cmd);
942
		data = &geo_cmd;
721
	} else {
943
	} else {
722
		geo_tx_cmd.geo_cmd_v1.ops =
944
		geo_cmd_v1.ops =
723
			cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
945
			cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE);
724
		len = sizeof(geo_tx_cmd.geo_cmd_v1);
946
		len = sizeof(geo_cmd_v1);
947
		data = &geo_cmd_v1;
725
	}
948
	}
726
949
727
	if (!iwl_sar_geo_support(&mvm->fwrt))
728
		return -EOPNOTSUPP;
729
730
	cmd = (struct iwl_host_cmd){
950
	cmd = (struct iwl_host_cmd){
731
		.id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
951
		.id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
732
		.len = { len, },
952
		.len = { len, },
733
		.flags = CMD_WANT_SKB,
953
		.flags = CMD_WANT_SKB,
734
		.data = { &geo_tx_cmd },
954
		.data = { data },
735
	};
955
	};
736
956
957
	if (!iwl_mvm_sar_geo_support(mvm))
958
		return -EOPNOTSUPP;
959
737
	ret = iwl_mvm_send_cmd(mvm, &cmd);
960
	ret = iwl_mvm_send_cmd(mvm, &cmd);
738
	if (ret) {
961
	if (ret) {
739
		IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
962
		IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
740
		return ret;
963
		return ret;
741
	}
964
	}
742
	ret = iwl_validate_sar_geo_profile(&mvm->fwrt, &cmd);
965
966
	resp = (void *)cmd.resp_pkt->data;
967
	ret = le32_to_cpu(resp->profile_idx);
968
	if (WARN_ON(ret > ACPI_NUM_GEO_PROFILES)) {
969
		ret = -EIO;
970
		IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
971
	}
972
743
	iwl_free_resp(&cmd);
973
	iwl_free_resp(&cmd);
744
	return ret;
974
	return ret;
745
}
975
}
746
976
747
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
977
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
748
{
978
{
979
	struct iwl_geo_tx_power_profiles_cmd cmd = {
980
		.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
981
	};
982
	int ret, i, j;
749
	u16 cmd_wide_id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
983
	u16 cmd_wide_id =  WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
750
	union geo_tx_power_profiles_cmd cmd;
751
	u16 len;
752
984
753
	cmd.geo_cmd.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES);
985
	if (!iwl_mvm_sar_geo_support(mvm))
986
		return 0;
754
987
755
	iwl_sar_geo_init(&mvm->fwrt, cmd.geo_cmd.table);
988
	ret = iwl_mvm_sar_get_wgds_table(mvm);
989
	if (ret < 0) {
990
		IWL_DEBUG_RADIO(mvm,
991
				"Geo SAR BIOS table invalid or unavailable. (%d)\n",
992
				ret);
993
		/* we don't fail if the table is not available */
994
		return 0;
995
	}
756
996
757
	cmd.geo_cmd.table_revision = cpu_to_le32(mvm->fwrt.geo_rev);
997
	IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n");
758
998
759
	if (!fw_has_api(&mvm->fwrt.fw->ucode_capa,
999
	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS *
760
			IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
1000
		     ACPI_WGDS_TABLE_SIZE + 1 !=  ACPI_WGDS_WIFI_DATA_SIZE);
761
		len = sizeof(struct iwl_geo_tx_power_profiles_cmd_v1);
1001
762
	} else {
1002
	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES);
763
		len =  sizeof(cmd.geo_cmd);
1003
1004
	for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) {
1005
		struct iwl_per_chain_offset *chain =
1006
			(struct iwl_per_chain_offset *)&cmd.table[i];
1007
1008
		for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
1009
			u8 *value;
1010
1011
			value = &mvm->geo_profiles[i].values[j *
1012
				ACPI_GEO_PER_CHAIN_SIZE];
1013
			chain[j].max_tx_power = cpu_to_le16(value[0]);
1014
			chain[j].chain_a = value[1];
1015
			chain[j].chain_b = value[2];
1016
			IWL_DEBUG_RADIO(mvm,
1017
					"SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n",
1018
					i, j, value[1], value[2], value[0]);
1019
		}
764
	}
1020
	}
765
1021
766
	return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, len, &cmd);
1022
	cmd.table_revision = cpu_to_le32(mvm->geo_rev);
1023
1024
	if (!fw_has_api(&mvm->fw->ucode_capa,
1025
		       IWL_UCODE_TLV_API_SAR_TABLE_VER)) {
1026
		return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0,
1027
				sizeof(struct iwl_geo_tx_power_profiles_cmd_v1),
1028
				&cmd);
1029
	}
1030
1031
	return iwl_mvm_send_cmd_pdu(mvm, cmd_wide_id, 0, sizeof(cmd), &cmd);
767
}
1032
}
768
1033
769
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
1034
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
Lines 772-778 static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) Link Here
772
	int i, j, ret, tbl_rev;
1037
	int i, j, ret, tbl_rev;
773
	int idx = 2;
1038
	int idx = 2;
774
1039
775
	mvm->fwrt.ppag_table.enabled = cpu_to_le32(0);
1040
	mvm->ppag_table.enabled = cpu_to_le32(0);
776
	data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
1041
	data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
777
	if (IS_ERR(data))
1042
	if (IS_ERR(data))
778
		return PTR_ERR(data);
1043
		return PTR_ERR(data);
Lines 797-804 static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) Link Here
797
		goto out_free;
1062
		goto out_free;
798
	}
1063
	}
799
1064
800
	mvm->fwrt.ppag_table.enabled = cpu_to_le32(enabled->integer.value);
1065
	mvm->ppag_table.enabled = cpu_to_le32(enabled->integer.value);
801
	if (!mvm->fwrt.ppag_table.enabled) {
1066
	if (!mvm->ppag_table.enabled) {
802
		ret = 0;
1067
		ret = 0;
803
		goto out_free;
1068
		goto out_free;
804
	}
1069
	}
Lines 818-828 static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm) Link Here
818
			    (j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) ||
1083
			    (j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) ||
819
			    (j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) ||
1084
			    (j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) ||
820
			    (j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) {
1085
			    (j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) {
821
				mvm->fwrt.ppag_table.enabled = cpu_to_le32(0);
1086
				mvm->ppag_table.enabled = cpu_to_le32(0);
822
				ret = -EINVAL;
1087
				ret = -EINVAL;
823
				goto out_free;
1088
				goto out_free;
824
			}
1089
			}
825
			mvm->fwrt.ppag_table.gain[i][j] = ent->integer.value;
1090
			mvm->ppag_table.gain[i][j] = ent->integer.value;
826
		}
1091
		}
827
	}
1092
	}
828
	ret = 0;
1093
	ret = 0;
Lines 841-847 int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) Link Here
841
		return 0;
1106
		return 0;
842
	}
1107
	}
843
1108
844
	if (!mvm->fwrt.ppag_table.enabled) {
1109
	if (!mvm->ppag_table.enabled) {
845
		IWL_DEBUG_RADIO(mvm,
1110
		IWL_DEBUG_RADIO(mvm,
846
				"PPAG not enabled, command not sent.\n");
1111
				"PPAG not enabled, command not sent.\n");
847
		return 0;
1112
		return 0;
Lines 853-866 int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) Link Here
853
		for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
1118
		for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
854
			IWL_DEBUG_RADIO(mvm,
1119
			IWL_DEBUG_RADIO(mvm,
855
					"PPAG table: chain[%d] band[%d]: gain = %d\n",
1120
					"PPAG table: chain[%d] band[%d]: gain = %d\n",
856
					i, j, mvm->fwrt.ppag_table.gain[i][j]);
1121
					i, j, mvm->ppag_table.gain[i][j]);
857
		}
1122
		}
858
	}
1123
	}
859
1124
860
	ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP,
1125
	ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP,
861
						PER_PLATFORM_ANT_GAIN_CMD),
1126
						PER_PLATFORM_ANT_GAIN_CMD),
862
				   0, sizeof(mvm->fwrt.ppag_table),
1127
				   0, sizeof(mvm->ppag_table),
863
				   &mvm->fwrt.ppag_table);
1128
				   &mvm->ppag_table);
864
	if (ret < 0)
1129
	if (ret < 0)
865
		IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
1130
		IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
866
			ret);
1131
			ret);
Lines 883-896 static int iwl_mvm_ppag_init(struct iwl_mvm *mvm) Link Here
883
}
1148
}
884
1149
885
#else /* CONFIG_ACPI */
1150
#else /* CONFIG_ACPI */
1151
static int iwl_mvm_sar_get_wrds_table(struct iwl_mvm *mvm)
1152
{
1153
	return -ENOENT;
1154
}
886
1155
887
inline int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm,
1156
static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
888
				      int prof_a, int prof_b)
889
{
1157
{
890
	return -ENOENT;
1158
	return -ENOENT;
891
}
1159
}
892
1160
893
inline int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
1161
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
894
{
1162
{
895
	return -ENOENT;
1163
	return -ENOENT;
896
}
1164
}
Lines 900-905 static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) Link Here
900
	return 0;
1168
	return 0;
901
}
1169
}
902
1170
1171
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a,
1172
			       int prof_b)
1173
{
1174
	return -ENOENT;
1175
}
1176
1177
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
1178
{
1179
	return -ENOENT;
1180
}
1181
903
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
1182
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
904
{
1183
{
905
	return -ENOENT;
1184
	return -ENOENT;
Lines 907-913 int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm) Link Here
907
1186
908
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
1187
static int iwl_mvm_ppag_init(struct iwl_mvm *mvm)
909
{
1188
{
910
	return 0;
1189
	return -ENOENT;
911
}
1190
}
912
#endif /* CONFIG_ACPI */
1191
#endif /* CONFIG_ACPI */
913
1192
Lines 966-972 static int iwl_mvm_sar_init(struct iwl_mvm *mvm) Link Here
966
{
1245
{
967
	int ret;
1246
	int ret;
968
1247
969
	ret = iwl_sar_get_wrds_table(&mvm->fwrt);
1248
	ret = iwl_mvm_sar_get_wrds_table(mvm);
970
	if (ret < 0) {
1249
	if (ret < 0) {
971
		IWL_DEBUG_RADIO(mvm,
1250
		IWL_DEBUG_RADIO(mvm,
972
				"WRDS SAR BIOS table invalid or unavailable. (%d)\n",
1251
				"WRDS SAR BIOS table invalid or unavailable. (%d)\n",
Lines 978-991 static int iwl_mvm_sar_init(struct iwl_mvm *mvm) Link Here
978
		return 1;
1257
		return 1;
979
	}
1258
	}
980
1259
981
	ret = iwl_sar_get_ewrd_table(&mvm->fwrt);
1260
	ret = iwl_mvm_sar_get_ewrd_table(mvm);
982
	/* if EWRD is not available, we can still use WRDS, so don't fail */
1261
	/* if EWRD is not available, we can still use WRDS, so don't fail */
983
	if (ret < 0)
1262
	if (ret < 0)
984
		IWL_DEBUG_RADIO(mvm,
1263
		IWL_DEBUG_RADIO(mvm,
985
				"EWRD SAR BIOS table invalid or unavailable. (%d)\n",
1264
				"EWRD SAR BIOS table invalid or unavailable. (%d)\n",
986
				ret);
1265
				ret);
987
1266
1267
	/* choose profile 1 (WRDS) as default for both chains */
988
	ret = iwl_mvm_sar_select_profile(mvm, 1, 1);
1268
	ret = iwl_mvm_sar_select_profile(mvm, 1, 1);
1269
989
	/*
1270
	/*
990
	 * If we don't have profile 0 from BIOS, just skip it.  This
1271
	 * If we don't have profile 0 from BIOS, just skip it.  This
991
	 * means that SAR Geo will not be enabled either, even if we
1272
	 * means that SAR Geo will not be enabled either, even if we
Lines 1216-1222 int iwl_mvm_up(struct iwl_mvm *mvm) Link Here
1216
	ret = iwl_mvm_sar_init(mvm);
1497
	ret = iwl_mvm_sar_init(mvm);
1217
	if (ret == 0) {
1498
	if (ret == 0) {
1218
		ret = iwl_mvm_sar_geo_init(mvm);
1499
		ret = iwl_mvm_sar_geo_init(mvm);
1219
	} else if (ret > 0 && !iwl_sar_get_wgds_table(&mvm->fwrt)) {
1500
	} else if (ret > 0 && !iwl_mvm_sar_get_wgds_table(mvm)) {
1220
		/*
1501
		/*
1221
		 * If basic SAR is not available, we check for WGDS,
1502
		 * If basic SAR is not available, we check for WGDS,
1222
		 * which should *not* be available either.  If it is
1503
		 * which should *not* be available either.  If it is
(-)a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h (-6 / +16 lines)
Lines 188-198 enum iwl_power_scheme { Link Here
188
	IWL_POWER_SCHEME_LP
188
	IWL_POWER_SCHEME_LP
189
};
189
};
190
190
191
union geo_tx_power_profiles_cmd {
192
	struct iwl_geo_tx_power_profiles_cmd geo_cmd;
193
	struct iwl_geo_tx_power_profiles_cmd_v1 geo_cmd_v1;
194
};
195
196
#define IWL_CONN_MAX_LISTEN_INTERVAL	10
191
#define IWL_CONN_MAX_LISTEN_INTERVAL	10
197
#define IWL_UAPSD_MAX_SP		IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
192
#define IWL_UAPSD_MAX_SP		IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
198
193
Lines 779-784 enum iwl_mvm_queue_status { Link Here
779
774
780
#define IWL_MVM_NUM_CIPHERS             10
775
#define IWL_MVM_NUM_CIPHERS             10
781
776
777
struct iwl_mvm_sar_profile {
778
	bool enabled;
779
	u8 table[ACPI_SAR_TABLE_SIZE];
780
};
781
782
struct iwl_mvm_geo_profile {
783
	u8 values[ACPI_GEO_TABLE_SIZE];
784
};
782
785
783
struct iwl_mvm_txq {
786
struct iwl_mvm_txq {
784
	struct list_head list;
787
	struct list_head list;
Lines 1141-1146 struct iwl_mvm { Link Here
1141
	/* sniffer data to include in radiotap */
1144
	/* sniffer data to include in radiotap */
1142
	__le16 cur_aid;
1145
	__le16 cur_aid;
1143
	u8 cur_bssid[ETH_ALEN];
1146
	u8 cur_bssid[ETH_ALEN];
1147
1148
#ifdef CONFIG_ACPI
1149
	struct iwl_mvm_sar_profile sar_profiles[ACPI_SAR_PROFILE_NUM];
1150
	struct iwl_mvm_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
1151
	u32 geo_rev;
1152
	struct iwl_ppag_table_cmd ppag_table;
1153
	u32 ppag_rev;
1154
#endif
1144
};
1155
};
1145
1156
1146
/* Extract MVM priv from op_mode and _hw */
1157
/* Extract MVM priv from op_mode and _hw */
1147
- 

Return to bug 203709