ath10k: add recalc RTS/CTS protection method

Add recalculation of RTS/CTS protection when one or more legacy
stations are connected to ath10k. In this case enable RTS/CTS
protection and set sw retry profile are needed in the FW.
Without this change legacy station is starved and has very low
throughput.

Signed-off-by: Marek Kwaczynski <marek.kwaczynski@tieto.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
Marek Kwaczynski
2014-03-11 12:58:00 +02:00
committed by Kalle Valo
parent 44d6fa90a8
commit e81bd10482
3 changed files with 59 additions and 11 deletions

View File

@@ -739,6 +739,26 @@ static int ath10k_monitor_destroy(struct ath10k *ar)
return ret;
}
static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
u32 vdev_param, rts_cts = 0;
lockdep_assert_held(&ar->conf_mutex);
vdev_param = ar->wmi.vdev_param->enable_rtscts;
if (arvif->use_cts_prot || arvif->num_legacy_stations > 0)
rts_cts |= SM(WMI_RTSCTS_ENABLED, WMI_RTSCTS_SET);
if (arvif->num_legacy_stations > 0)
rts_cts |= SM(WMI_RTSCTS_ACROSS_SW_RETRIES,
WMI_RTSCTS_PROFILE);
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
rts_cts);
}
static int ath10k_start_cac(struct ath10k *ar)
{
int ret;
@@ -1552,6 +1572,16 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
return ret;
}
if (!sta->wme) {
arvif->num_legacy_stations++;
ret = ath10k_recalc_rtscts_prot(arvif);
if (ret) {
ath10k_warn("failed to recalculate rts/cts prot for vdev %d: %d\n",
arvif->vdev_id, ret);
return ret;
}
}
ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
if (ret) {
ath10k_warn("could not install peer wep keys for vdev %i: %d\n",
@@ -1576,6 +1606,16 @@ static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
lockdep_assert_held(&ar->conf_mutex);
if (!sta->wme) {
arvif->num_legacy_stations--;
ret = ath10k_recalc_rtscts_prot(arvif);
if (ret) {
ath10k_warn("failed to recalculate rts/cts prot for vdev %d: %d\n",
arvif->vdev_id, ret);
return ret;
}
}
ret = ath10k_clear_peer_keys(arvif, sta->addr);
if (ret) {
ath10k_warn("could not clear all peer wep keys for vdev %i: %d\n",
@@ -2869,20 +2909,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
ath10k_control_beaconing(arvif, info);
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
u32 cts_prot;
if (info->use_cts_prot)
cts_prot = 1;
else
cts_prot = 0;
arvif->use_cts_prot = info->use_cts_prot;
ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n",
arvif->vdev_id, cts_prot);
arvif->vdev_id, info->use_cts_prot);
vdev_param = ar->wmi.vdev_param->enable_rtscts;
ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
cts_prot);
ret = ath10k_recalc_rtscts_prot(arvif);
if (ret)
ath10k_warn("Failed to set CTS prot for vdev %d: %d\n",
ath10k_warn("Failed to recalculate rts/cts prot for vdev %d: %d\n",
arvif->vdev_id, ret);
}