From: Sven Eckelmann Date: Fri, 8 Feb 2019 21:20:20 +0100 Subject: ath10k-ct: support for multicast and management rate control Drivers with software rate control can directly use the selected multicast rate for multicast/broadcast frames and the minimal basic rate for management frames. But drivers with offloaded rate control algorithms must be informed about such upper layer decisions to configure the hardware/firmware. A new BSS_CHANGED_MCAST_RATE is introduced in mac80211 to automatically inform all drivers. ath10k-ct can detect this event and forward it via WMI to the driver. The already existing BSS_CHANGED_BASIC_RATES can be used to select the management rate. Without the WMI commands, a low rate (not necessarily one from the basic rates) is used for bcast/mcast/management frames. This means that the /etc/config/wireless settings basic_rate and mcast_rate would have no effect on the rates selected by this driver for the mentioned frames. Signed-off-by: Sven Eckelmann diff --git a/package/kernel/ath10k-ct/patches/976-ath10k-support-for-multicast-rate-control.patch b/package/kernel/ath10k-ct/patches/976-ath10k-support-for-multicast-rate-control.patch new file mode 100644 index 0000000000000000000000000000000000000000..bd60bf317dec3a2eec1fd9263037acc30d272e39 --- /dev/null +++ b/package/kernel/ath10k-ct/patches/976-ath10k-support-for-multicast-rate-control.patch @@ -0,0 +1,112 @@ +From: Pradeep Kumar Chitrapu +Date: Wed, 25 Jul 2018 10:59:39 +0300 +Subject: [PATCH] ath10k: support for multicast rate control + +Issues a wmi command to firmware when multicast rate change is received with the +new BSS_CHANGED_MCAST_RATE flag. Also fixes the incorrect fixed_rate setting +for CCK rates which got introduced with addition of ath10k_rates_rev2 enum. + +Tested on QCA9984 with firmware ver 10.4-3.6-00104 + +Signed-off-by: Pradeep Kumar Chitrapu +Signed-off-by: Kalle Valo + +Origin: backport, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=cd93b83ad927b2c7979e0add0343ace59328b461 +--- + ath10k-4.13/mac.c | 54 +++++++++++++++++++++++++-- + 1 file changed, 50 insertions(+), 4 deletions(-) + +diff --git a/ath10k-4.13/mac.c b/ath10k-4.13/mac.c +index 5683f1a5330eedae677aad5bf2621a6232781346..1937526c8c18da85f7730429759391d47e12cf81 100644 +--- a/ath10k-4.13/mac.c ++++ b/ath10k-4.13/mac.c +@@ -100,6 +100,8 @@ static struct ieee80211_rate ath10k_rates_rev2[] = { + #define ath10k_g_rates_rev2 (ath10k_rates_rev2 + 0) + #define ath10k_g_rates_rev2_size (ARRAY_SIZE(ath10k_rates_rev2)) + ++#define ath10k_wmi_legacy_rates ath10k_rates ++ + static bool ath10k_mac_bitrate_is_cck(int bitrate) + { + switch (bitrate) { +@@ -5389,8 +5391,12 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, + { + struct ath10k *ar = hw->priv; + struct ath10k_vif *arvif = (void *)vif->drv_priv; +- int ret = 0; ++ struct cfg80211_chan_def def; + u32 vdev_param, pdev_param, slottime, preamble; ++ u16 bitrate, hw_value; ++ u8 rate; ++ int rateidx, ret = 0; ++ enum nl80211_band band; + + mutex_lock(&ar->conf_mutex); + +@@ -5558,6 +5564,44 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, + arvif->vdev_id, ret); + } + ++ if (changed & BSS_CHANGED_MCAST_RATE && ++ !WARN_ON(ath10k_mac_vif_chan(arvif->vif, &def))) { ++ band = def.chan->band; ++ rateidx = vif->bss_conf.mcast_rate[band] - 1; ++ ++ if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) ++ rateidx += ATH10K_MAC_FIRST_OFDM_RATE_IDX; ++ ++ bitrate = ath10k_wmi_legacy_rates[rateidx].bitrate; ++ hw_value = ath10k_wmi_legacy_rates[rateidx].hw_value; ++ if (ath10k_mac_bitrate_is_cck(bitrate)) ++ preamble = WMI_RATE_PREAMBLE_CCK; ++ else ++ preamble = WMI_RATE_PREAMBLE_OFDM; ++ ++ rate = ATH10K_HW_RATECODE(hw_value, 0, preamble); ++ ++ ath10k_dbg(ar, ATH10K_DBG_MAC, ++ "mac vdev %d mcast_rate %x\n", ++ arvif->vdev_id, rate); ++ ++ vdev_param = ar->wmi.vdev_param->mcast_data_rate; ++ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, ++ vdev_param, rate); ++ if (ret) ++ ath10k_warn(ar, ++ "failed to set mcast rate on vdev %i: %d\n", ++ arvif->vdev_id, ret); ++ ++ vdev_param = ar->wmi.vdev_param->bcast_data_rate; ++ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, ++ vdev_param, rate); ++ if (ret) ++ ath10k_warn(ar, ++ "failed to set bcast rate on vdev %i: %d\n", ++ arvif->vdev_id, ret); ++ } ++ + mutex_unlock(&ar->conf_mutex); + } + +@@ -6826,7 +6870,6 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, + const struct cfg80211_bitrate_mask *mask, + u8 *rate, u8 *nss) + { +- struct ieee80211_supported_band *sband = &ar->mac.sbands[band]; + int rate_idx; + int i; + u16 bitrate; +@@ -6836,8 +6879,11 @@ ath10k_mac_bitrate_mask_get_single_rate(struct ath10k *ar, + if (hweight32(mask->control[band].legacy) == 1) { + rate_idx = ffs(mask->control[band].legacy) - 1; + +- hw_rate = sband->bitrates[rate_idx].hw_value; +- bitrate = sband->bitrates[rate_idx].bitrate; ++ if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) ++ rate_idx += ATH10K_MAC_FIRST_OFDM_RATE_IDX; ++ ++ hw_rate = ath10k_wmi_legacy_rates[rate_idx].hw_value; ++ bitrate = ath10k_wmi_legacy_rates[rate_idx].bitrate; + + if (ath10k_mac_bitrate_is_cck(bitrate)) + preamble = WMI_RATE_PREAMBLE_CCK; diff --git a/package/kernel/ath10k-ct/patches/977-ath10k-add-support-for-configuring-management-packet.patch b/package/kernel/ath10k-ct/patches/977-ath10k-add-support-for-configuring-management-packet.patch new file mode 100644 index 0000000000000000000000000000000000000000..6cc6df271fc73431b9467ac9878c360345e0754f --- /dev/null +++ b/package/kernel/ath10k-ct/patches/977-ath10k-add-support-for-configuring-management-packet.patch @@ -0,0 +1,94 @@ +From: Sriram R +Date: Mon, 10 Sep 2018 11:09:40 +0530 +Subject: [PATCH] ath10k: add support for configuring management packet rate + +By default the firmware uses 1Mbps and 6Mbps rate for management packets +in 2G and 5G bands respectively. But when the user selects different +basic rates from the userspace, we need to send the management +packets at the lowest basic rate selected by the user. + +This change makes use of WMI_VDEV_PARAM_MGMT_RATE param for configuring the +management packets rate to the firmware. + +Chipsets Tested : QCA988X, QCA9887, QCA9984 +FW Tested : 10.2.4-1.0-41, 10.4-3.6.104 + +Signed-off-by: Sriram R +Signed-off-by: Kalle Valo + +Origin: backport, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f279294e9ee22a8f306fdc8e4181cf555e6f0f70 +--- + ath10k-4.13/mac.c | 45 +++++++++++++++++++++++++-- + 1 file changed, 43 insertions(+), 2 deletions(-) + +diff --git a/ath10k-4.13/mac.c b/ath10k-4.13/mac.c +index 1937526c8c18da85f7730429759391d47e12cf81..47e5992afcd7564743f513eb250b57381aba3233 100644 +--- a/ath10k-4.13/mac.c ++++ b/ath10k-4.13/mac.c +@@ -155,6 +155,22 @@ u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband, + return 0; + } + ++static int ath10k_mac_get_rate_hw_value(int bitrate) ++{ ++ int i; ++ u8 hw_value_prefix = 0; ++ ++ if (ath10k_mac_bitrate_is_cck(bitrate)) ++ hw_value_prefix = WMI_RATE_PREAMBLE_CCK << 6; ++ ++ for (i = 0; i < sizeof(ath10k_rates); i++) { ++ if (ath10k_rates[i].bitrate == bitrate) ++ return hw_value_prefix | ath10k_rates[i].hw_value; ++ } ++ ++ return -EINVAL; ++} ++ + static int ath10k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss) + { + switch ((mcs_map >> (2 * nss)) & 0x3) { +@@ -5394,9 +5410,10 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, + struct cfg80211_chan_def def; + u32 vdev_param, pdev_param, slottime, preamble; + u16 bitrate, hw_value; +- u8 rate; +- int rateidx, ret = 0; ++ u8 rate, basic_rate_idx; ++ int rateidx, ret = 0, hw_rate_code; + enum nl80211_band band; ++ const struct ieee80211_supported_band *sband; + + mutex_lock(&ar->conf_mutex); + +@@ -5602,6 +5619,30 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, + arvif->vdev_id, ret); + } + ++ if (changed & BSS_CHANGED_BASIC_RATES) { ++ if (WARN_ON(ath10k_mac_vif_chan(vif, &def))) { ++ mutex_unlock(&ar->conf_mutex); ++ return; ++ } ++ ++ sband = ar->hw->wiphy->bands[def.chan->band]; ++ basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; ++ bitrate = sband->bitrates[basic_rate_idx].bitrate; ++ ++ hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate); ++ if (hw_rate_code < 0) { ++ ath10k_warn(ar, "bitrate not supported %d\n", bitrate); ++ mutex_unlock(&ar->conf_mutex); ++ return; ++ } ++ ++ vdev_param = ar->wmi.vdev_param->mgmt_rate; ++ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ++ hw_rate_code); ++ if (ret) ++ ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret); ++ } ++ + mutex_unlock(&ar->conf_mutex); + } + diff --git a/package/kernel/ath10k-ct/patches/978-ath10k-fix-possible-out-of-bound-access-of-ath10k_ra.patch b/package/kernel/ath10k-ct/patches/978-ath10k-fix-possible-out-of-bound-access-of-ath10k_ra.patch new file mode 100644 index 0000000000000000000000000000000000000000..cc13e547aa7e983fcff6137de9463e0b706651c5 --- /dev/null +++ b/package/kernel/ath10k-ct/patches/978-ath10k-fix-possible-out-of-bound-access-of-ath10k_ra.patch @@ -0,0 +1,70 @@ +From: Sriram R +Date: Wed, 3 Oct 2018 08:43:50 +0530 +Subject: [PATCH] ath10k: fix possible out of bound access of ath10k_rates array + +While using 'ath10k_mac_get_rate_hw_value()' to obtain the hw value +from the passed bitrate, there is a chance of out of bound array access +when wrong bitrate is passed. This is fixed by comparing the bitrates +within the correct size of the ath10k_rates array. + +Fixes commit f279294e9ee2 ("ath10k: add support for configuring management +packet rate"). Also correction made to some indents used in the above commit. + +Signed-off-by: Sriram R +Signed-off-by: Kalle Valo + +Origin: backport, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e141eea7dd8525dd1ef7a925459e455b4d307f +--- + ath10k-4.13/mac.c | 30 +++++++++++++-------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/ath10k-4.13/mac.c b/ath10k-4.13/mac.c +index 47e5992afcd7564743f513eb250b57381aba3233..e93b04c8e6fb2fa7968b910e0cc97ad8144bd7e8 100644 +--- a/ath10k-4.13/mac.c ++++ b/ath10k-4.13/mac.c +@@ -163,7 +163,7 @@ static int ath10k_mac_get_rate_hw_value(int bitrate) + if (ath10k_mac_bitrate_is_cck(bitrate)) + hw_value_prefix = WMI_RATE_PREAMBLE_CCK << 6; + +- for (i = 0; i < sizeof(ath10k_rates); i++) { ++ for (i = 0; i < ARRAY_SIZE(ath10k_rates); i++) { + if (ath10k_rates[i].bitrate == bitrate) + return hw_value_prefix | ath10k_rates[i].hw_value; + } +@@ -5625,22 +5625,22 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, + return; + } + +- sband = ar->hw->wiphy->bands[def.chan->band]; +- basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; +- bitrate = sband->bitrates[basic_rate_idx].bitrate; ++ sband = ar->hw->wiphy->bands[def.chan->band]; ++ basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1; ++ bitrate = sband->bitrates[basic_rate_idx].bitrate; + +- hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate); +- if (hw_rate_code < 0) { +- ath10k_warn(ar, "bitrate not supported %d\n", bitrate); +- mutex_unlock(&ar->conf_mutex); +- return; +- } ++ hw_rate_code = ath10k_mac_get_rate_hw_value(bitrate); ++ if (hw_rate_code < 0) { ++ ath10k_warn(ar, "bitrate not supported %d\n", bitrate); ++ mutex_unlock(&ar->conf_mutex); ++ return; ++ } + +- vdev_param = ar->wmi.vdev_param->mgmt_rate; +- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, +- hw_rate_code); +- if (ret) +- ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret); ++ vdev_param = ar->wmi.vdev_param->mgmt_rate; ++ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, ++ hw_rate_code); ++ if (ret) ++ ath10k_warn(ar, "failed to set mgmt tx rate %d\n", ret); + } + + mutex_unlock(&ar->conf_mutex);