iwlwifi: mvm: Support new TX_RSP and COMPRESSED_BA_RES versions
As part of the new rate_n_flags, a new version of this structures was added in the FW. Add support for this new version and for the new rate_n_flags in this API. Both these APIs were updated in one patch since they are using the same functions. Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/iwlwifi.20211017162352.a28e7a92f558.I19f72735c674f815c6e7c11cecfad6230b4510ef@changeid Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
This commit is contained in:
parent
cd2c46a7eb
commit
dc52fac37c
5 changed files with 99 additions and 24 deletions
|
@ -593,7 +593,8 @@ struct iwl_mvm_tx_resp {
|
||||||
__le16 tx_queue;
|
__le16 tx_queue;
|
||||||
__le16 reserved2;
|
__le16 reserved2;
|
||||||
struct agg_tx_status status;
|
struct agg_tx_status status;
|
||||||
} __packed; /* TX_RSP_API_S_VER_6 */
|
} __packed; /* TX_RSP_API_S_VER_6,
|
||||||
|
TX_RSP_API_S_VER_7 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_mvm_ba_notif - notifies about reception of BA
|
* struct iwl_mvm_ba_notif - notifies about reception of BA
|
||||||
|
@ -717,7 +718,8 @@ struct iwl_mvm_compressed_ba_notif {
|
||||||
__le16 ra_tid_cnt;
|
__le16 ra_tid_cnt;
|
||||||
struct iwl_mvm_compressed_ba_ratid ra_tid[0];
|
struct iwl_mvm_compressed_ba_ratid ra_tid[0];
|
||||||
struct iwl_mvm_compressed_ba_tfd tfd[];
|
struct iwl_mvm_compressed_ba_tfd tfd[];
|
||||||
} __packed; /* COMPRESSED_BA_RES_API_S_VER_4 */
|
} __packed; /* COMPRESSED_BA_RES_API_S_VER_4,
|
||||||
|
COMPRESSED_BA_RES_API_S_VER_5 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct iwl_mac_beacon_cmd_v6 - beacon template command
|
* struct iwl_mac_beacon_cmd_v6 - beacon template command
|
||||||
|
|
|
@ -1443,11 +1443,16 @@ int __iwl_mvm_mac_start(struct iwl_mvm *mvm);
|
||||||
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm);
|
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm);
|
||||||
|
|
||||||
/* Utils */
|
/* Utils */
|
||||||
|
int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags,
|
||||||
|
enum nl80211_band band);
|
||||||
int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
||||||
enum nl80211_band band);
|
enum nl80211_band band);
|
||||||
void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
|
void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
|
||||||
enum nl80211_band band,
|
enum nl80211_band band,
|
||||||
struct ieee80211_tx_rate *r);
|
struct ieee80211_tx_rate *r);
|
||||||
|
void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
|
||||||
|
enum nl80211_band band,
|
||||||
|
struct ieee80211_tx_rate *r);
|
||||||
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx);
|
u8 iwl_mvm_mac80211_idx_to_hwrate(const struct iwl_fw *fw, int rate_idx);
|
||||||
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);
|
u8 iwl_mvm_mac80211_ac_to_ucode_ac(enum ieee80211_ac_numbers ac);
|
||||||
|
|
||||||
|
|
|
@ -2692,8 +2692,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lq_sta = mvm_sta;
|
lq_sta = mvm_sta;
|
||||||
iwl_mvm_hwrate_to_tx_rate(lq_sta->last_rate_n_flags,
|
iwl_mvm_hwrate_to_tx_rate_v1(lq_sta->last_rate_n_flags,
|
||||||
info->band, &info->control.rates[0]);
|
info->band, &info->control.rates[0]);
|
||||||
info->control.rates[0].count = 1;
|
info->control.rates[0].count = 1;
|
||||||
|
|
||||||
/* Report the optimal rate based on rssi and STA caps if we haven't
|
/* Report the optimal rate based on rssi and STA caps if we haven't
|
||||||
|
@ -2703,8 +2703,8 @@ static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
|
||||||
optimal_rate = rs_get_optimal_rate(mvm, lq_sta);
|
optimal_rate = rs_get_optimal_rate(mvm, lq_sta);
|
||||||
last_ucode_rate = ucode_rate_from_rs_rate(mvm,
|
last_ucode_rate = ucode_rate_from_rs_rate(mvm,
|
||||||
optimal_rate);
|
optimal_rate);
|
||||||
iwl_mvm_hwrate_to_tx_rate(last_ucode_rate, info->band,
|
iwl_mvm_hwrate_to_tx_rate_v1(last_ucode_rate, info->band,
|
||||||
&txrc->reported_rate);
|
&txrc->reported_rate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1292,25 +1292,66 @@ const char *iwl_mvm_get_tx_fail_reason(u32 status)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||||
|
|
||||||
|
static int iwl_mvm_get_hwrate_chan_width(u32 chan_width)
|
||||||
|
{
|
||||||
|
switch (chan_width) {
|
||||||
|
case RATE_MCS_CHAN_WIDTH_20:
|
||||||
|
return 0;
|
||||||
|
case RATE_MCS_CHAN_WIDTH_40:
|
||||||
|
return IEEE80211_TX_RC_40_MHZ_WIDTH;
|
||||||
|
case RATE_MCS_CHAN_WIDTH_80:
|
||||||
|
return IEEE80211_TX_RC_80_MHZ_WIDTH;
|
||||||
|
case RATE_MCS_CHAN_WIDTH_160:
|
||||||
|
return IEEE80211_TX_RC_160_MHZ_WIDTH;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
|
void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
|
||||||
enum nl80211_band band,
|
enum nl80211_band band,
|
||||||
struct ieee80211_tx_rate *r)
|
struct ieee80211_tx_rate *r)
|
||||||
|
{
|
||||||
|
u32 format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
|
||||||
|
u32 rate = format == RATE_MCS_HT_MSK ?
|
||||||
|
RATE_HT_MCS_INDEX(rate_n_flags) :
|
||||||
|
rate_n_flags & RATE_MCS_CODE_MSK;
|
||||||
|
|
||||||
|
r->flags |=
|
||||||
|
iwl_mvm_get_hwrate_chan_width(rate_n_flags &
|
||||||
|
RATE_MCS_CHAN_WIDTH_MSK);
|
||||||
|
|
||||||
|
if (rate_n_flags & RATE_MCS_SGI_MSK)
|
||||||
|
r->flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||||
|
if (format == RATE_MCS_HT_MSK) {
|
||||||
|
r->flags |= IEEE80211_TX_RC_MCS;
|
||||||
|
r->idx = rate;
|
||||||
|
} else if (format == RATE_MCS_VHT_MSK) {
|
||||||
|
ieee80211_rate_set_vht(r, rate,
|
||||||
|
((rate_n_flags & RATE_MCS_NSS_MSK) >>
|
||||||
|
RATE_MCS_NSS_POS) + 1);
|
||||||
|
r->flags |= IEEE80211_TX_RC_VHT_MCS;
|
||||||
|
} else if (format == RATE_MCS_HE_MSK) {
|
||||||
|
/* mac80211 cannot do this without ieee80211_tx_status_ext()
|
||||||
|
* but it only matters for radiotap */
|
||||||
|
r->idx = 0;
|
||||||
|
} else {
|
||||||
|
r->idx = iwl_mvm_legacy_hw_idx_to_mac80211_idx(rate_n_flags,
|
||||||
|
band);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void iwl_mvm_hwrate_to_tx_rate_v1(u32 rate_n_flags,
|
||||||
|
enum nl80211_band band,
|
||||||
|
struct ieee80211_tx_rate *r)
|
||||||
{
|
{
|
||||||
if (rate_n_flags & RATE_HT_MCS_GF_MSK)
|
if (rate_n_flags & RATE_HT_MCS_GF_MSK)
|
||||||
r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
|
r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
|
||||||
switch (rate_n_flags & RATE_MCS_CHAN_WIDTH_MSK_V1) {
|
|
||||||
case RATE_MCS_CHAN_WIDTH_20:
|
r->flags |=
|
||||||
break;
|
iwl_mvm_get_hwrate_chan_width(rate_n_flags &
|
||||||
case RATE_MCS_CHAN_WIDTH_40:
|
RATE_MCS_CHAN_WIDTH_MSK_V1);
|
||||||
r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
|
|
||||||
break;
|
|
||||||
case RATE_MCS_CHAN_WIDTH_80:
|
|
||||||
r->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH;
|
|
||||||
break;
|
|
||||||
case RATE_MCS_CHAN_WIDTH_160:
|
|
||||||
r->flags |= IEEE80211_TX_RC_160_MHZ_WIDTH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (rate_n_flags & RATE_MCS_SGI_MSK_V1)
|
if (rate_n_flags & RATE_MCS_SGI_MSK_V1)
|
||||||
r->flags |= IEEE80211_TX_RC_SHORT_GI;
|
r->flags |= IEEE80211_TX_RC_SHORT_GI;
|
||||||
if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
|
if (rate_n_flags & RATE_MCS_HT_MSK_V1) {
|
||||||
|
@ -1331,14 +1372,20 @@ void iwl_mvm_hwrate_to_tx_rate(u32 rate_n_flags,
|
||||||
/*
|
/*
|
||||||
* translate ucode response to mac80211 tx status control values
|
* translate ucode response to mac80211 tx status control values
|
||||||
*/
|
*/
|
||||||
static void iwl_mvm_hwrate_to_tx_status(u32 rate_n_flags,
|
static void iwl_mvm_hwrate_to_tx_status(const struct iwl_fw *fw,
|
||||||
|
u32 rate_n_flags,
|
||||||
struct ieee80211_tx_info *info)
|
struct ieee80211_tx_info *info)
|
||||||
{
|
{
|
||||||
struct ieee80211_tx_rate *r = &info->status.rates[0];
|
struct ieee80211_tx_rate *r = &info->status.rates[0];
|
||||||
|
|
||||||
|
if (iwl_fw_lookup_notif_ver(fw, LONG_GROUP,
|
||||||
|
TX_CMD, 0) > 6)
|
||||||
|
rate_n_flags = iwl_new_rate_from_v1(rate_n_flags);
|
||||||
|
|
||||||
info->status.antenna =
|
info->status.antenna =
|
||||||
((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
|
((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS);
|
||||||
iwl_mvm_hwrate_to_tx_rate(rate_n_flags, info->band, r);
|
iwl_mvm_hwrate_to_tx_rate(rate_n_flags,
|
||||||
|
info->band, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
|
static void iwl_mvm_tx_status_check_trigger(struct iwl_mvm *mvm,
|
||||||
|
@ -1480,8 +1527,14 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
|
||||||
iwl_mvm_tx_status_check_trigger(mvm, status, hdr->frame_control);
|
iwl_mvm_tx_status_check_trigger(mvm, status, hdr->frame_control);
|
||||||
|
|
||||||
info->status.rates[0].count = tx_resp->failure_frame + 1;
|
info->status.rates[0].count = tx_resp->failure_frame + 1;
|
||||||
iwl_mvm_hwrate_to_tx_status(le32_to_cpu(tx_resp->initial_rate),
|
|
||||||
|
iwl_mvm_hwrate_to_tx_status(mvm->fw,
|
||||||
|
le32_to_cpu(tx_resp->initial_rate),
|
||||||
info);
|
info);
|
||||||
|
|
||||||
|
/* Don't assign the converted initial_rate, because driver
|
||||||
|
* TLC uses this and doesn't support the new FW rate
|
||||||
|
*/
|
||||||
info->status.status_driver_data[1] =
|
info->status.status_driver_data[1] =
|
||||||
(void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate);
|
(void *)(uintptr_t)le32_to_cpu(tx_resp->initial_rate);
|
||||||
|
|
||||||
|
@ -1843,7 +1896,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
|
||||||
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||||
memcpy(&info->status, &tx_info->status,
|
memcpy(&info->status, &tx_info->status,
|
||||||
sizeof(tx_info->status));
|
sizeof(tx_info->status));
|
||||||
iwl_mvm_hwrate_to_tx_status(rate, info);
|
iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1864,7 +1917,7 @@ static void iwl_mvm_tx_reclaim(struct iwl_mvm *mvm, int sta_id, int tid,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
tx_info->band = chanctx_conf->def.chan->band;
|
tx_info->band = chanctx_conf->def.chan->band;
|
||||||
iwl_mvm_hwrate_to_tx_status(rate, tx_info);
|
iwl_mvm_hwrate_to_tx_status(mvm->fw, rate, tx_info);
|
||||||
|
|
||||||
if (!iwl_mvm_has_tlc_offload(mvm)) {
|
if (!iwl_mvm_has_tlc_offload(mvm)) {
|
||||||
IWL_DEBUG_TX_REPLY(mvm,
|
IWL_DEBUG_TX_REPLY(mvm,
|
||||||
|
|
|
@ -135,6 +135,21 @@ int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id, u16 len,
|
||||||
return iwl_mvm_send_cmd_status(mvm, &cmd, status);
|
return iwl_mvm_send_cmd_status(mvm, &cmd, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int iwl_mvm_legacy_hw_idx_to_mac80211_idx(u32 rate_n_flags,
|
||||||
|
enum nl80211_band band)
|
||||||
|
{
|
||||||
|
int format = rate_n_flags & RATE_MCS_MOD_TYPE_MSK;
|
||||||
|
int rate = rate_n_flags & RATE_LEGACY_RATE_MSK;
|
||||||
|
bool is_LB = band == NL80211_BAND_2GHZ;
|
||||||
|
|
||||||
|
if (format == RATE_MCS_LEGACY_OFDM_MSK)
|
||||||
|
return is_LB ? rate + IWL_FIRST_OFDM_RATE :
|
||||||
|
rate;
|
||||||
|
|
||||||
|
/* CCK is not allowed in HB */
|
||||||
|
return is_LB ? rate : -1;
|
||||||
|
}
|
||||||
|
|
||||||
int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
int iwl_mvm_legacy_rate_to_mac80211_idx(u32 rate_n_flags,
|
||||||
enum nl80211_band band)
|
enum nl80211_band band)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue