From: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> New API versions are coming up for this command. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@xxxxxxxxx> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@xxxxxxxxx> --- .../net/wireless/intel/iwlwifi/fw/api/power.h | 54 +++++++++++++++++++ drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 24 +++++++-- .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 37 +++++++++---- 3 files changed, 100 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index 4c9d28327efc..df0680eae30c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -441,6 +441,60 @@ struct iwl_dev_tx_power_cmd_v3_v8 { }; }; +/** + * struct iwl_dev_tx_power_cmd_v9 - TX power reduction cmd + * @reserved: reserved (padding) + * @per_chain: per chain restrictions + * @per_chain_restriction_changed: is per_chain_restriction has changed + * from last command. used if set_mode is + * IWL_TX_POWER_MODE_SET_SAR_TIMER. + * note: if not changed, the command is used for keep alive only. + * @reserved1: reserved (padding) + * @timer_period: timer in milliseconds. if expires FW will change to default + * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER + */ +struct iwl_dev_tx_power_cmd_v9 { + __le16 reserved; + __le16 per_chain[IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V1]; + u8 per_chain_restriction_changed; + u8 reserved1[3]; + __le32 timer_period; +} __packed; /* TX_REDUCED_POWER_API_S_VER_9 */ + +/** + * struct iwl_dev_tx_power_cmd_v10 - TX power reduction cmd + * @per_chain: per chain restrictions + * @per_chain_restriction_changed: is per_chain_restriction has changed + * from last command. used if set_mode is + * IWL_TX_POWER_MODE_SET_SAR_TIMER. + * note: if not changed, the command is used for keep alive only. + * @reserved: reserved (padding) + * @timer_period: timer in milliseconds. if expires FW will change to default + * BIOS values. relevant if setMode is IWL_TX_POWER_MODE_SET_SAR_TIMER + * @flags: reduce power flags. + */ +struct iwl_dev_tx_power_cmd_v10 { + __le16 per_chain[IWL_NUM_CHAIN_TABLES_V2][IWL_NUM_CHAIN_LIMITS][IWL_NUM_SUB_BANDS_V2]; + u8 per_chain_restriction_changed; + u8 reserved; + __le32 timer_period; + __le32 flags; +} __packed; /* TX_REDUCED_POWER_API_S_VER_10 */ + +/* + * struct iwl_dev_tx_power_cmd - TX power reduction command (multiversion) + * @common: common part of the command + * @v9: version 9 part of the command + * @v10: version 10 part of the command + */ +struct iwl_dev_tx_power_cmd { + struct iwl_dev_tx_power_common common; + union { + struct iwl_dev_tx_power_cmd_v9 v9; + struct iwl_dev_tx_power_cmd_v10 v10; + }; +} __packed; /* TX_REDUCED_POWER_API_S_VER_9_VER10 */ + #define IWL_NUM_GEO_PROFILES 3 #define IWL_NUM_GEO_PROFILES_V3 8 #define IWL_NUM_BANDS_PER_CHAIN_V1 2 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 4c0847446e22..e279fd409b6f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -866,13 +866,27 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) struct iwl_dev_tx_power_cmd_v3_v8 cmd = { .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS), }; + struct iwl_dev_tx_power_cmd cmd_v9_v10 = { + .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS), + }; __le16 *per_chain; int ret; u16 len = 0; u32 n_subbands; u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3); + void *cmd_data = &cmd; - if (cmd_ver >= 7) { + if (cmd_ver == 10) { + len = sizeof(cmd_v9_v10.v10); + n_subbands = IWL_NUM_SUB_BANDS_V2; + per_chain = &cmd_v9_v10.v10.per_chain[0][0][0]; + cmd_v9_v10.v10.flags = + cpu_to_le32(mvm->fwrt.reduced_power_flags); + } else if (cmd_ver == 9) { + len = sizeof(cmd_v9_v10.v9); + n_subbands = IWL_NUM_SUB_BANDS_V1; + per_chain = &cmd_v9_v10.v9.per_chain[0][0]; + } else if (cmd_ver >= 7) { len = sizeof(cmd.v7); n_subbands = IWL_NUM_SUB_BANDS_V2; per_chain = cmd.v7.per_chain[0][0]; @@ -902,8 +916,10 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) /* all structs have the same common part, add its length */ len += sizeof(cmd.common); - /* all structs have the same per_band part, add its length */ - len += sizeof(cmd.per_band); + if (cmd_ver < 9) + len += sizeof(cmd.per_band); + else + cmd_data = &cmd_v9_v10; ret = iwl_sar_fill_profile(&mvm->fwrt, per_chain, IWL_NUM_CHAIN_TABLES, @@ -916,7 +932,7 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) iwl_mei_set_power_limit(per_chain); IWL_DEBUG_RADIO(mvm, "Sending REDUCE_TX_POWER_CMD per chain\n"); - return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd); + return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, cmd_data); } int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index f0b290aa6bec..f48f445e006c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1484,15 +1484,29 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, .common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC), .common.mac_context_id = cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id), - .common.pwr_restriction = cpu_to_le16(8 * tx_power), }; - u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, - IWL_FW_CMD_VER_UNKNOWN); - - if (tx_power == IWL_DEFAULT_MAX_TX_POWER) - cmd.common.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER); - - if (cmd_ver == 8) + struct iwl_dev_tx_power_cmd cmd_v9_v10; + u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, cmd_id, 3); + u16 u_tx_power = tx_power == IWL_DEFAULT_MAX_TX_POWER ? + IWL_DEV_MAX_TX_POWER : 8 * tx_power; + void *cmd_data = &cmd; + + cmd.common.pwr_restriction = cpu_to_le16(u_tx_power); + + if (cmd_ver > 8) { + /* Those fields sit on the same place for v9 and v10 */ + cmd_v9_v10.common.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_MAC); + cmd_v9_v10.common.mac_context_id = + cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id); + cmd_v9_v10.common.pwr_restriction = cpu_to_le16(u_tx_power); + cmd_data = &cmd_v9_v10; + } + + if (cmd_ver == 10) + len = sizeof(cmd_v9_v10.v10); + else if (cmd_ver == 9) + len = sizeof(cmd_v9_v10.v9); + else if (cmd_ver == 8) len = sizeof(cmd.v8); else if (cmd_ver == 7) len = sizeof(cmd.v7); @@ -1510,10 +1524,11 @@ int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* all structs have the same common part, add its length */ len += sizeof(cmd.common); - /* all structs have the same per_band part, add its length */ - len += sizeof(cmd.per_band); + if (cmd_ver < 9) + len += sizeof(cmd.per_band); + + return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, cmd_data); - return iwl_mvm_send_cmd_pdu(mvm, cmd_id, 0, len, &cmd); } static void iwl_mvm_post_csa_tx(void *data, struct ieee80211_sta *sta) -- 2.34.1