提交 3ae54225 编写于 作者: M Michal Kazior 提交者: Kalle Valo

ath10k: clean up set_bitrate_mask handling

The code was a bit convoluted. Clean it up and
prepare for future changes.

While at it this fixes incorrect verification of
'single nss' case when ss2 rates were missing
while ss1 and ss3 were requested resulting in
nss=3 being set:

  iw wlan1 set bitrates legacy-5 ht-mcs-5 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23 vht-mcs-5 1:0-9 3:0-9
Signed-off-by: NMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: NKalle Valo <kvalo@qca.qualcomm.com>
上级 039a0051
...@@ -348,9 +348,6 @@ struct ath10k_vif { ...@@ -348,9 +348,6 @@ struct ath10k_vif {
} ap; } ap;
} u; } u;
u8 fixed_rate;
u8 fixed_nss;
u8 force_sgi;
bool use_cts_prot; bool use_cts_prot;
int num_legacy_stations; int num_legacy_stations;
int txpower; int txpower;
......
...@@ -120,6 +120,16 @@ u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband, ...@@ -120,6 +120,16 @@ u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
return 0; return 0;
} }
static int ath10k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
{
switch ((mcs_map >> (2 * nss)) & 0x3) {
case IEEE80211_VHT_MCS_SUPPORT_0_7: return BIT(8) - 1;
case IEEE80211_VHT_MCS_SUPPORT_0_8: return BIT(9) - 1;
case IEEE80211_VHT_MCS_SUPPORT_0_9: return BIT(10) - 1;
}
return 0;
}
/**********/ /**********/
/* Crypto */ /* Crypto */
/**********/ /**********/
...@@ -5592,327 +5602,221 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx, ...@@ -5592,327 +5602,221 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx,
return ret; return ret;
} }
/* Check if only one bit set */
static int ath10k_check_single_mask(u32 mask)
{
int bit;
bit = ffs(mask);
if (!bit)
return 0;
mask &= ~BIT(bit - 1);
if (mask)
return 2;
return 1;
}
static bool static bool
ath10k_default_bitrate_mask(struct ath10k *ar, ath10k_mac_bitrate_mask_has_single_rate(struct ath10k *ar,
enum ieee80211_band band, enum ieee80211_band band,
const struct cfg80211_bitrate_mask *mask) const struct cfg80211_bitrate_mask *mask)
{ {
u32 legacy = 0x00ff; int num_rates = 0;
u8 ht = 0xff, i; int i;
u16 vht = 0x3ff;
u16 nrf = ar->num_rf_chains;
if (ar->cfg_tx_chainmask)
nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
switch (band) { num_rates += hweight32(mask->control[band].legacy);
case IEEE80211_BAND_2GHZ:
legacy = 0x00fff;
vht = 0;
break;
case IEEE80211_BAND_5GHZ:
break;
default:
return false;
}
if (mask->control[band].legacy != legacy) for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++)
return false; num_rates += hweight8(mask->control[band].ht_mcs[i]);
for (i = 0; i < nrf; i++) for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++)
if (mask->control[band].ht_mcs[i] != ht) num_rates += hweight16(mask->control[band].vht_mcs[i]);
return false;
for (i = 0; i < nrf; i++)
if (mask->control[band].vht_mcs[i] != vht)
return false;
return true; return num_rates == 1;
} }
static bool static bool
ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask, ath10k_mac_bitrate_mask_get_single_nss(struct ath10k *ar,
enum ieee80211_band band, enum ieee80211_band band,
u8 *fixed_nss) const struct cfg80211_bitrate_mask *mask,
{ int *nss)
int ht_nss = 0, vht_nss = 0, i; {
struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
u16 vht_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map);
u8 ht_nss_mask = 0;
u8 vht_nss_mask = 0;
int i;
/* check legacy */ if (mask->control[band].legacy)
if (ath10k_check_single_mask(mask->control[band].legacy))
return false; return false;
/* check HT */ for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { if (mask->control[band].ht_mcs[i] == 0)
if (mask->control[band].ht_mcs[i] == 0xff)
continue; continue;
else if (mask->control[band].ht_mcs[i] == 0x00) else if (mask->control[band].ht_mcs[i] ==
break; sband->ht_cap.mcs.rx_mask[i])
ht_nss_mask |= BIT(i);
return false; else
return false;
} }
ht_nss = i; for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
if (mask->control[band].vht_mcs[i] == 0)
/* check VHT */
for (i = 0; i < NL80211_VHT_NSS_MAX; i++) {
if (mask->control[band].vht_mcs[i] == 0x03ff)
continue; continue;
else if (mask->control[band].vht_mcs[i] == 0x0000) else if (mask->control[band].vht_mcs[i] ==
break; ath10k_mac_get_max_vht_mcs_map(vht_mcs_map, i))
vht_nss_mask |= BIT(i);
return false; else
return false;
} }
vht_nss = i; if (ht_nss_mask != vht_nss_mask)
if (ht_nss > 0 && vht_nss > 0)
return false; return false;
if (ht_nss) if (ht_nss_mask == 0)
*fixed_nss = ht_nss;
else if (vht_nss)
*fixed_nss = vht_nss;
else
return false; return false;
return true; if (BIT(fls(ht_nss_mask)) - 1 != ht_nss_mask)
}
static bool
ath10k_bitrate_mask_correct(const struct cfg80211_bitrate_mask *mask,
enum ieee80211_band band,
enum wmi_rate_preamble *preamble)
{
int legacy = 0, ht = 0, vht = 0, i;
*preamble = WMI_RATE_PREAMBLE_OFDM;
/* check legacy */
legacy = ath10k_check_single_mask(mask->control[band].legacy);
if (legacy > 1)
return false;
/* check HT */
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
ht += ath10k_check_single_mask(mask->control[band].ht_mcs[i]);
if (ht > 1)
return false;
/* check VHT */
for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
vht += ath10k_check_single_mask(mask->control[band].vht_mcs[i]);
if (vht > 1)
return false;
/* Currently we support only one fixed_rate */
if ((legacy + ht + vht) != 1)
return false; return false;
if (ht) *nss = fls(ht_nss_mask);
*preamble = WMI_RATE_PREAMBLE_HT;
else if (vht)
*preamble = WMI_RATE_PREAMBLE_VHT;
return true; return true;
} }
static bool static int
ath10k_bitrate_mask_rate(struct ath10k *ar, ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar,
const struct cfg80211_bitrate_mask *mask, enum ieee80211_band band,
enum ieee80211_band band, const struct cfg80211_bitrate_mask *mask,
u8 *fixed_rate, u8 *rate, u8 *nss)
u8 *fixed_nss)
{ {
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband = &ar->mac.sbands[band];
u8 rate = 0, pream = 0, nss = 0, i; int rate_idx;
enum wmi_rate_preamble preamble; int i;
u16 bitrate;
/* Check if single rate correct */ u8 preamble;
if (!ath10k_bitrate_mask_correct(mask, band, &preamble)) u8 hw_rate;
return false;
pream = preamble;
switch (preamble) {
case WMI_RATE_PREAMBLE_CCK:
case WMI_RATE_PREAMBLE_OFDM:
i = ffs(mask->control[band].legacy) - 1;
sband = &ar->mac.sbands[band];
if (WARN_ON(i >= sband->n_bitrates))
return false;
rate = sband->bitrates[i].hw_value; if (hweight32(mask->control[band].legacy) == 1) {
break; rate_idx = ffs(mask->control[band].legacy) - 1;
case WMI_RATE_PREAMBLE_HT:
for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++)
if (mask->control[band].ht_mcs[i])
break;
if (i == IEEE80211_HT_MCS_MASK_LEN) hw_rate = sband->bitrates[rate_idx].hw_value;
return false; bitrate = sband->bitrates[rate_idx].bitrate;
rate = ffs(mask->control[band].ht_mcs[i]) - 1; if (ath10k_mac_bitrate_is_cck(bitrate))
nss = i; preamble = WMI_RATE_PREAMBLE_CCK;
break; else
case WMI_RATE_PREAMBLE_VHT: preamble = WMI_RATE_PREAMBLE_OFDM;
for (i = 0; i < NL80211_VHT_NSS_MAX; i++)
if (mask->control[band].vht_mcs[i])
break;
if (i == NL80211_VHT_NSS_MAX) *nss = 1;
return false; *rate = preamble << 6 |
(*nss - 1) << 4 |
hw_rate << 0;
rate = ffs(mask->control[band].vht_mcs[i]) - 1; return 0;
nss = i;
break;
} }
*fixed_nss = nss + 1; for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) {
nss <<= 4; if (hweight8(mask->control[band].ht_mcs[i]) == 1) {
pream <<= 6; *nss = i + 1;
*rate = WMI_RATE_PREAMBLE_HT << 6 |
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac fixed rate pream 0x%02x nss 0x%02x rate 0x%02x\n", (*nss - 1) << 4 |
pream, nss, rate); (ffs(mask->control[band].ht_mcs[i]) - 1);
*fixed_rate = pream | nss | rate; return 0;
}
}
return true; for (i = 0; i < ARRAY_SIZE(mask->control[band].vht_mcs); i++) {
} if (hweight16(mask->control[band].vht_mcs[i]) == 1) {
*nss = i + 1;
*rate = WMI_RATE_PREAMBLE_VHT << 6 |
(*nss - 1) << 4 |
(ffs(mask->control[band].vht_mcs[i]) - 1);
static bool ath10k_get_fixed_rate_nss(struct ath10k *ar, return 0;
const struct cfg80211_bitrate_mask *mask, }
enum ieee80211_band band, }
u8 *fixed_rate,
u8 *fixed_nss)
{
/* First check full NSS mask, if we can simply limit NSS */
if (ath10k_bitrate_mask_nss(mask, band, fixed_nss))
return true;
/* Next Check single rate is set */ return -EINVAL;
return ath10k_bitrate_mask_rate(ar, mask, band, fixed_rate, fixed_nss);
} }
static int ath10k_set_fixed_rate_param(struct ath10k_vif *arvif, static int ath10k_mac_set_fixed_rate_params(struct ath10k_vif *arvif,
u8 fixed_rate, u8 rate, u8 nss, u8 sgi)
u8 fixed_nss,
u8 force_sgi)
{ {
struct ath10k *ar = arvif->ar; struct ath10k *ar = arvif->ar;
u32 vdev_param; u32 vdev_param;
int ret = 0; int ret;
mutex_lock(&ar->conf_mutex);
if (arvif->fixed_rate == fixed_rate &&
arvif->fixed_nss == fixed_nss &&
arvif->force_sgi == force_sgi)
goto exit;
if (fixed_rate == WMI_FIXED_RATE_NONE) lockdep_assert_held(&ar->conf_mutex);
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac disable fixed bitrate mask\n");
if (force_sgi) ath10k_dbg(ar, ATH10K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02hhx nss %hhu sgi %hhu\n",
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac force sgi\n"); arvif->vdev_id, rate, nss, sgi);
vdev_param = ar->wmi.vdev_param->fixed_rate; vdev_param = ar->wmi.vdev_param->fixed_rate;
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, rate);
vdev_param, fixed_rate);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to set fixed rate param 0x%02x: %d\n", ath10k_warn(ar, "failed to set fixed rate param 0x%02x: %d\n",
fixed_rate, ret); rate, ret);
ret = -EINVAL; return ret;
goto exit;
} }
arvif->fixed_rate = fixed_rate;
vdev_param = ar->wmi.vdev_param->nss; vdev_param = ar->wmi.vdev_param->nss;
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, nss);
vdev_param, fixed_nss);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to set fixed nss param %d: %d\n", ath10k_warn(ar, "failed to set nss param %d: %d\n", nss, ret);
fixed_nss, ret); return ret;
ret = -EINVAL;
goto exit;
} }
arvif->fixed_nss = fixed_nss;
vdev_param = ar->wmi.vdev_param->sgi; vdev_param = ar->wmi.vdev_param->sgi;
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, sgi);
force_sgi);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to set sgi param %d: %d\n", ath10k_warn(ar, "failed to set sgi param %d: %d\n", sgi, ret);
force_sgi, ret); return ret;
ret = -EINVAL;
goto exit;
} }
arvif->force_sgi = force_sgi; return 0;
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
} }
static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw, static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask) const struct cfg80211_bitrate_mask *mask)
{ {
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct cfg80211_chan_def def; struct cfg80211_chan_def def;
struct ath10k *ar = arvif->ar; struct ath10k *ar = arvif->ar;
enum ieee80211_band band; enum ieee80211_band band;
u8 fixed_rate = WMI_FIXED_RATE_NONE; u8 rate;
u8 fixed_nss = ar->num_rf_chains; u8 nss;
u8 force_sgi; u8 sgi;
int single_nss;
int ret;
if (ath10k_mac_vif_chan(vif, &def)) if (ath10k_mac_vif_chan(vif, &def))
return -EPERM; return -EPERM;
if (ar->cfg_tx_chainmask)
fixed_nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
band = def.chan->band; band = def.chan->band;
force_sgi = mask->control[band].gi; sgi = mask->control[band].gi;
if (force_sgi == NL80211_TXRATE_FORCE_LGI) if (sgi == NL80211_TXRATE_FORCE_LGI)
return -EINVAL; return -EINVAL;
if (!ath10k_default_bitrate_mask(ar, band, mask)) { if (ath10k_mac_bitrate_mask_has_single_rate(ar, band, mask)) {
if (!ath10k_get_fixed_rate_nss(ar, mask, band, ret = ath10k_mac_bitrate_mask_get_single_rate(ar, band, mask,
&fixed_rate, &rate, &nss);
&fixed_nss)) if (ret) {
return -EINVAL; ath10k_warn(ar, "failed to get single rate for vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
} else if (ath10k_mac_bitrate_mask_get_single_nss(ar, band, mask,
&single_nss)) {
rate = WMI_FIXED_RATE_NONE;
nss = single_nss;
} else {
rate = WMI_FIXED_RATE_NONE;
nss = ar->num_rf_chains;
} }
if (fixed_rate == WMI_FIXED_RATE_NONE && force_sgi) { mutex_lock(&ar->conf_mutex);
ath10k_warn(ar, "failed to force SGI usage for default rate settings\n");
return -EINVAL; ret = ath10k_mac_set_fixed_rate_params(arvif, rate, nss, sgi);
if (ret) {
ath10k_warn(ar, "failed to set fixed rate params on vdev %i: %d\n",
arvif->vdev_id, ret);
goto exit;
} }
return ath10k_set_fixed_rate_param(arvif, fixed_rate, exit:
fixed_nss, force_sgi); mutex_unlock(&ar->conf_mutex);
return ret;
} }
static void ath10k_sta_rc_update(struct ieee80211_hw *hw, static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
...@@ -6335,7 +6239,7 @@ static const struct ieee80211_ops ath10k_ops = { ...@@ -6335,7 +6239,7 @@ static const struct ieee80211_ops ath10k_ops = {
.get_antenna = ath10k_get_antenna, .get_antenna = ath10k_get_antenna,
.reconfig_complete = ath10k_reconfig_complete, .reconfig_complete = ath10k_reconfig_complete,
.get_survey = ath10k_get_survey, .get_survey = ath10k_get_survey,
.set_bitrate_mask = ath10k_set_bitrate_mask, .set_bitrate_mask = ath10k_mac_op_set_bitrate_mask,
.sta_rc_update = ath10k_sta_rc_update, .sta_rc_update = ath10k_sta_rc_update,
.get_tsf = ath10k_get_tsf, .get_tsf = ath10k_get_tsf,
.ampdu_action = ath10k_ampdu_action, .ampdu_action = ath10k_ampdu_action,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册