Commit 7fe90e0e authored by Haim Dreyfuss's avatar Haim Dreyfuss Committed by Luca Coelho

iwlwifi: mvm: refactor geo init

We are going to add debugfs entry to retrieve the current geographic
profile being used in the FW. Currently the driver reads those tables
from the BIOS and passes them to the FW.
To prepare for this retrieving we want to store those
tables in the driver.
Signed-off-by: default avatarHaim Dreyfuss <haim.dreyfuss@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent fdcbe65d
...@@ -363,6 +363,7 @@ struct iwl_dev_tx_power_cmd { ...@@ -363,6 +363,7 @@ struct iwl_dev_tx_power_cmd {
} __packed; /* TX_REDUCED_POWER_API_S_VER_4 */ } __packed; /* TX_REDUCED_POWER_API_S_VER_4 */
#define IWL_NUM_GEO_PROFILES 3 #define IWL_NUM_GEO_PROFILES 3
#define IWL_GEO_PER_CHAIN_SIZE 3
/** /**
* enum iwl_geo_per_chain_offset_operation - type of operation * enum iwl_geo_per_chain_offset_operation - type of operation
...@@ -401,6 +402,14 @@ struct iwl_geo_tx_power_profiles_cmd { ...@@ -401,6 +402,14 @@ struct iwl_geo_tx_power_profiles_cmd {
struct iwl_per_chain_offset_group table[IWL_NUM_GEO_PROFILES]; struct iwl_per_chain_offset_group table[IWL_NUM_GEO_PROFILES];
} __packed; /* GEO_TX_POWER_LIMIT */ } __packed; /* GEO_TX_POWER_LIMIT */
/**
* struct iwl_geo_tx_power_profiles_resp - response to GEO_TX_POWER_LIMIT cmd
* @profile_idx: current geo profile in use
*/
struct iwl_geo_tx_power_profiles_resp {
__le32 profile_idx;
} __packed; /* GEO_TX_POWER_LIMIT_RESP */
/** /**
* struct iwl_beacon_filter_cmd * struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command) * REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
......
...@@ -1243,15 +1243,15 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm) ...@@ -1243,15 +1243,15 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)
return ret; return ret;
} }
static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm, static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm)
struct iwl_mvm_geo_table *geo_table)
{ {
union acpi_object *wifi_pkg; union acpi_object *wifi_pkg;
acpi_handle root_handle; acpi_handle root_handle;
acpi_handle handle; acpi_handle handle;
struct acpi_buffer wgds = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_buffer wgds = {ACPI_ALLOCATE_BUFFER, NULL};
acpi_status status; acpi_status status;
int i, ret; int i, j, ret;
int idx = 1;
root_handle = ACPI_HANDLE(mvm->dev); root_handle = ACPI_HANDLE(mvm->dev);
if (!root_handle) { if (!root_handle) {
...@@ -1282,15 +1282,17 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm, ...@@ -1282,15 +1282,17 @@ static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm,
goto out_free; goto out_free;
} }
for (i = 0; i < ACPI_WGDS_WIFI_DATA_SIZE; i++) { for (i = 0; i < IWL_NUM_GEO_PROFILES; i++) {
for (j = 0; j < IWL_MVM_GEO_TABLE_SIZE; j++) {
union acpi_object *entry; union acpi_object *entry;
entry = &wifi_pkg->package.elements[i + 1]; entry = &wifi_pkg->package.elements[idx++];
if ((entry->type != ACPI_TYPE_INTEGER) || if ((entry->type != ACPI_TYPE_INTEGER) ||
(entry->integer.value > U8_MAX)) (entry->integer.value > U8_MAX))
return -EINVAL; return -EINVAL;
geo_table->values[i] = entry->integer.value; mvm->geo_profiles[i].values[j] = entry->integer.value;
}
} }
ret = 0; ret = 0;
out_free: out_free:
...@@ -1351,16 +1353,47 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) ...@@ -1351,16 +1353,47 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd); return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0, len, &cmd);
} }
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
{
struct iwl_geo_tx_power_profiles_resp *resp;
int ret;
struct iwl_geo_tx_power_profiles_cmd geo_cmd = {
.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_GET_CURRENT_TABLE),
};
struct iwl_host_cmd cmd = {
.id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT),
.len = { sizeof(geo_cmd), },
.flags = CMD_WANT_SKB,
.data = { &geo_cmd },
};
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret) {
IWL_ERR(mvm, "Failed to get geographic profile info %d\n", ret);
return ret;
}
resp = (void *)cmd.resp_pkt->data;
ret = le32_to_cpu(resp->profile_idx);
if (WARN_ON(ret > IWL_NUM_GEO_PROFILES)) {
ret = -EIO;
IWL_WARN(mvm, "Invalid geographic profile idx (%d)\n", ret);
}
iwl_free_resp(&cmd);
return ret;
}
static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
{ {
struct iwl_mvm_geo_table geo_table;
struct iwl_geo_tx_power_profiles_cmd cmd = { struct iwl_geo_tx_power_profiles_cmd cmd = {
.ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES), .ops = cpu_to_le32(IWL_PER_CHAIN_OFFSET_SET_TABLES),
}; };
int ret, i, j, idx; int ret, i, j;
u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT); u16 cmd_wide_id = WIDE_ID(PHY_OPS_GROUP, GEO_TX_POWER_LIMIT);
ret = iwl_mvm_sar_get_wgds_table(mvm, &geo_table); ret = iwl_mvm_sar_get_wgds_table(mvm);
if (ret < 0) { if (ret < 0) {
IWL_DEBUG_RADIO(mvm, IWL_DEBUG_RADIO(mvm,
"Geo SAR BIOS table invalid or unavailable. (%d)\n", "Geo SAR BIOS table invalid or unavailable. (%d)\n",
...@@ -1381,9 +1414,8 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm) ...@@ -1381,9 +1414,8 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)
for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) { for (j = 0; j < ACPI_WGDS_NUM_BANDS; j++) {
u8 *value; u8 *value;
idx = i * ACPI_WGDS_NUM_BANDS * ACPI_WGDS_TABLE_SIZE + value = &mvm->geo_profiles[i].values[j *
j * ACPI_WGDS_TABLE_SIZE; IWL_GEO_PER_CHAIN_SIZE];
value = &geo_table.values[idx];
chain[j].max_tx_power = cpu_to_le16(value[0]); chain[j].max_tx_power = cpu_to_le16(value[0]);
chain[j].chain_a = value[1]; chain[j].chain_a = value[1];
chain[j].chain_b = value[2]; chain[j].chain_b = value[2];
......
...@@ -724,14 +724,14 @@ enum iwl_mvm_queue_status { ...@@ -724,14 +724,14 @@ enum iwl_mvm_queue_status {
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
#define IWL_MVM_SAR_TABLE_SIZE 10 #define IWL_MVM_SAR_TABLE_SIZE 10
#define IWL_MVM_SAR_PROFILE_NUM 4 #define IWL_MVM_SAR_PROFILE_NUM 4
#define IWL_MVM_GEO_TABLE_SIZE 18 #define IWL_MVM_GEO_TABLE_SIZE 6
struct iwl_mvm_sar_profile { struct iwl_mvm_sar_profile {
bool enabled; bool enabled;
u8 table[IWL_MVM_SAR_TABLE_SIZE]; u8 table[IWL_MVM_SAR_TABLE_SIZE];
}; };
struct iwl_mvm_geo_table { struct iwl_mvm_geo_profile {
u8 values[IWL_MVM_GEO_TABLE_SIZE]; u8 values[IWL_MVM_GEO_TABLE_SIZE];
}; };
#endif #endif
...@@ -1071,6 +1071,7 @@ struct iwl_mvm { ...@@ -1071,6 +1071,7 @@ struct iwl_mvm {
struct delayed_work cs_tx_unblock_dwork; struct delayed_work cs_tx_unblock_dwork;
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
struct iwl_mvm_sar_profile sar_profiles[IWL_MVM_SAR_PROFILE_NUM]; struct iwl_mvm_sar_profile sar_profiles[IWL_MVM_SAR_PROFILE_NUM];
struct iwl_mvm_geo_profile geo_profiles[IWL_NUM_GEO_PROFILES];
#endif #endif
}; };
...@@ -1889,12 +1890,19 @@ bool iwl_mvm_lqm_active(struct iwl_mvm *mvm); ...@@ -1889,12 +1890,19 @@ bool iwl_mvm_lqm_active(struct iwl_mvm *mvm);
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b); int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b);
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm);
#else #else
static inline static inline
int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b)
{ {
return -ENOENT; return -ENOENT;
} }
static inline
int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
{
return -ENOENT;
}
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
#endif /* __IWL_MVM_H__ */ #endif /* __IWL_MVM_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment