iwlwifi: acpi: support ppag table command v2

Version 2 of the PPAG table command supports more sub-bands than
previous. Change relevant command structs and the reading of the ACPI
tables.

Signed-off-by: Gil Adam <gil.adam@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20200924162106.fb29c33d2cb9.I942bfe645e9d47cd1fcf6435506061f8b2cea21a@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
Gil Adam 2020-09-24 16:23:39 +03:00 committed by Luca Coelho
parent bc9296f4a8
commit f2134f66f4
4 changed files with 102 additions and 43 deletions

View file

@ -107,10 +107,10 @@
#define ACPI_WGDS_NUM_BANDS 2
#define ACPI_WGDS_TABLE_SIZE 3
#define ACPI_PPAG_NUM_CHAINS 2
#define ACPI_PPAG_NUM_SUB_BANDS 5
#define ACPI_PPAG_WIFI_DATA_SIZE ((ACPI_PPAG_NUM_CHAINS * \
ACPI_PPAG_NUM_SUB_BANDS) + 3)
#define ACPI_PPAG_WIFI_DATA_SIZE ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS) + 3)
#define ACPI_PPAG_WIFI_DATA_SIZE_V2 ((IWL_NUM_CHAIN_LIMITS * \
IWL_NUM_SUB_BANDS_V2) + 3)
/* PPAG gain value bounds in 1/8 dBm */
#define ACPI_PPAG_MIN_LB -16

View file

@ -8,7 +8,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 - 2019 Intel Corporation
* Copyright (C) 2018 - 2020 Intel Corporation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@ -31,7 +31,7 @@
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright (C) 2018 - 2019 Intel Corporation
* Copyright (C) 2018 - 2020 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -331,6 +331,7 @@ enum iwl_dev_tx_power_cmd_mode {
#define IWL_NUM_CHAIN_LIMITS 2
#define IWL_NUM_SUB_BANDS 5
#define IWL_NUM_SUB_BANDS_V2 11
/**
* struct iwl_dev_tx_power_cmd - TX power reduction command
@ -450,16 +451,26 @@ struct iwl_geo_tx_power_profiles_resp {
} __packed; /* GEO_TX_POWER_LIMIT_RESP */
/**
* struct iwl_ppag_table_cmd - struct for PER_PLATFORM_ANT_GAIN_CMD cmd.
* union iwl_ppag_table_cmd - union for all versions of PPAG command
* @v1: version 1, table revision = 0
* @v2: version 2, table revision = 1
*
* @enabled: 1 if PPAG is enabled, 0 otherwise
* @gain: table of antenna gain values per chain and sub-band
* @reserved: reserved
*/
struct iwl_ppag_table_cmd {
__le32 enabled;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
s8 reserved[2];
} __packed; /* PER_PLATFORM_ANT_GAIN_CMD */
union iwl_ppag_table_cmd {
struct {
__le32 enabled;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS];
s8 reserved[2];
} v1;
struct {
__le32 enabled;
s8 gain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2];
s8 reserved[2];
} v2;
} __packed;
/**
* struct iwl_beacon_filter_cmd

View file

@ -207,7 +207,8 @@ struct iwl_fw_runtime {
u8 sar_chain_b_profile;
struct iwl_geo_profile geo_profiles[ACPI_NUM_GEO_PROFILES];
u32 geo_rev;
struct iwl_ppag_table_cmd ppag_table;
union iwl_ppag_table_cmd ppag_table;
u32 ppag_ver;
#endif
};

View file

@ -841,27 +841,53 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
{
union acpi_object *wifi_pkg, *data, *enabled;
int i, j, ret, tbl_rev;
union iwl_ppag_table_cmd ppag_table;
int i, j, ret, tbl_rev, num_sub_bands;
int idx = 2;
s8 *gain;
mvm->fwrt.ppag_table.enabled = cpu_to_le32(0);
/*
* The 'enabled' field is the same in v1 and v2 so we can just
* use v1 to access it.
*/
mvm->fwrt.ppag_table.v1.enabled = cpu_to_le32(0);
data = iwl_acpi_get_object(mvm->dev, ACPI_PPAG_METHOD);
if (IS_ERR(data))
return PTR_ERR(data);
/* try to read ppag table revision 1 */
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE_V2, &tbl_rev);
if (!IS_ERR(wifi_pkg)) {
if (tbl_rev != 1) {
ret = -EINVAL;
goto out_free;
}
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = mvm->fwrt.ppag_table.v2.gain[0];
mvm->fwrt.ppag_ver = 2;
IWL_DEBUG_RADIO(mvm, "Reading PPAG table v2 (tbl_rev=1)\n");
goto read_table;
}
/* try to read ppag table revision 0 */
wifi_pkg = iwl_acpi_get_wifi_pkg(mvm->dev, data,
ACPI_PPAG_WIFI_DATA_SIZE, &tbl_rev);
if (IS_ERR(wifi_pkg)) {
ret = PTR_ERR(wifi_pkg);
goto out_free;
}
if (tbl_rev != 0) {
ret = -EINVAL;
goto out_free;
if (!IS_ERR(wifi_pkg)) {
if (tbl_rev != 0) {
ret = -EINVAL;
goto out_free;
}
num_sub_bands = IWL_NUM_SUB_BANDS;
gain = mvm->fwrt.ppag_table.v1.gain[0];
mvm->fwrt.ppag_ver = 1;
IWL_DEBUG_RADIO(mvm, "Reading PPAG table v1 (tbl_rev=0)\n");
goto read_table;
}
ret = PTR_ERR(wifi_pkg);
goto out_free;
read_table:
enabled = &wifi_pkg->package.elements[1];
if (enabled->type != ACPI_TYPE_INTEGER ||
(enabled->integer.value != 0 && enabled->integer.value != 1)) {
@ -869,8 +895,8 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
goto out_free;
}
mvm->fwrt.ppag_table.enabled = cpu_to_le32(enabled->integer.value);
if (!mvm->fwrt.ppag_table.enabled) {
ppag_table.v1.enabled = cpu_to_le32(enabled->integer.value);
if (!ppag_table.v1.enabled) {
ret = 0;
goto out_free;
}
@ -880,8 +906,8 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
* first sub-band (j=0) corresponds to Low-Band (2.4GHz), and the
* following sub-bands to High-Band (5GHz).
*/
for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
for (j = 0; j < num_sub_bands; j++) {
union acpi_object *ent;
ent = &wifi_pkg->package.elements[idx++];
@ -890,11 +916,11 @@ static int iwl_mvm_get_ppag_table(struct iwl_mvm *mvm)
(j == 0 && ent->integer.value < ACPI_PPAG_MIN_LB) ||
(j != 0 && ent->integer.value > ACPI_PPAG_MAX_HB) ||
(j != 0 && ent->integer.value < ACPI_PPAG_MIN_HB)) {
mvm->fwrt.ppag_table.enabled = cpu_to_le32(0);
ppag_table.v1.enabled = cpu_to_le32(0);
ret = -EINVAL;
goto out_free;
}
mvm->fwrt.ppag_table.gain[i][j] = ent->integer.value;
gain[i * num_sub_bands + j] = ent->integer.value;
}
}
ret = 0;
@ -905,34 +931,55 @@ out_free:
int iwl_mvm_ppag_send_cmd(struct iwl_mvm *mvm)
{
int i, j, ret;
u8 cmd_ver;
int i, j, ret, num_sub_bands, cmd_size;
union iwl_ppag_table_cmd ppag_table;
s8 *gain;
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) {
IWL_DEBUG_RADIO(mvm,
"PPAG capability not supported by FW, command not sent.\n");
return 0;
}
if (!mvm->fwrt.ppag_table.enabled) {
IWL_DEBUG_RADIO(mvm,
"PPAG not enabled, command not sent.\n");
if (!mvm->fwrt.ppag_table.v1.enabled) {
IWL_DEBUG_RADIO(mvm, "PPAG not enabled, command not sent.\n");
return 0;
}
IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
for (i = 0; i < ACPI_PPAG_NUM_CHAINS; i++) {
for (j = 0; j < ACPI_PPAG_NUM_SUB_BANDS; j++) {
cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, PHY_OPS_GROUP,
PER_PLATFORM_ANT_GAIN_CMD);
if (cmd_ver == 1) {
num_sub_bands = IWL_NUM_SUB_BANDS;
gain = mvm->fwrt.ppag_table.v1.gain[0];
cmd_size = sizeof(ppag_table.v1);
if (mvm->fwrt.ppag_ver == 2) {
IWL_DEBUG_RADIO(mvm,
"PPAG table: chain[%d] band[%d]: gain = %d\n",
i, j, mvm->fwrt.ppag_table.gain[i][j]);
"PPAG table is v2 but FW supports v1, sending truncated table\n");
}
} else if (cmd_ver == 2) {
num_sub_bands = IWL_NUM_SUB_BANDS_V2;
gain = mvm->fwrt.ppag_table.v2.gain[0];
cmd_size = sizeof(ppag_table.v2);
if (mvm->fwrt.ppag_ver == 1) {
IWL_DEBUG_RADIO(mvm,
"PPAG table is v1 but FW supports v2, sending padded table\n");
}
} else {
IWL_DEBUG_RADIO(mvm, "Unsupported PPAG command version\n");
return 0;
}
for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) {
for (j = 0; j < num_sub_bands; j++) {
IWL_DEBUG_RADIO(mvm,
"PPAG table: chain[%d] band[%d]: gain = %d\n",
i, j, gain[i * num_sub_bands + j]);
}
}
IWL_DEBUG_RADIO(mvm, "Sending PER_PLATFORM_ANT_GAIN_CMD\n");
ret = iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(PHY_OPS_GROUP,
PER_PLATFORM_ANT_GAIN_CMD),
0, sizeof(mvm->fwrt.ppag_table),
&mvm->fwrt.ppag_table);
0, cmd_size, &ppag_table);
if (ret < 0)
IWL_ERR(mvm, "failed to send PER_PLATFORM_ANT_GAIN_CMD (%d)\n",
ret);