mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 09:32:34 +00:00
Add support for changing mcast and beacon rate in opensync for ath11k Add debugfs entry for ath11k driver to set mcast, beacon and mgmt rate. For help: cat /sys/kernel/debug/ieee80211/phyX/ath11k/set_rates Eg: Set beacon rate to 12Mbps for iface wlan0 5G band echo "wlan0 beacon 5 0x10000002" > /sys/kernel/debug/ieee80211/phy0/ath11k/set_rates Signed-off-by: Chaitanya Godavarthi <chaitanya.kiran@netexperience.com>
393 lines
13 KiB
Diff
393 lines
13 KiB
Diff
Index: backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/debug.c
|
|
===================================================================
|
|
--- backports-20200902_001-4.4.60-931c337125.orig/drivers/net/wireless/ath/ath11k/debug.c
|
|
+++ backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/debug.c
|
|
@@ -1838,6 +1838,230 @@ static const struct file_operations fops
|
|
.open = simple_open
|
|
};
|
|
|
|
+static ssize_t ath11k_read_set_rates(struct file *file,
|
|
+ char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ const char buf[] =
|
|
+ "This is to set fixed bcast, mcast, and beacon rates. Normal rate-ctrl\n"
|
|
+ "is handled through normal API using 'iw', etc.\n"
|
|
+ "To set a value, you specify the dev-name, type, band and rate-code:\n"
|
|
+ "types: bcast, mcast, beacon, mgmt\n"
|
|
+ "bands: 2, 5\n"
|
|
+ "rate-codes: 1M (0x10000103), 2M (0x10000102), 5.5M (0x10000101),\n 11M (0x10000100), 6M (0x10000003),9M (0x10000007),\n 12M (0x10000002), 18M (0x10000006),\n 24M (0x10000001), 36M (0x10000005), 48M (0x10000000),\n 54M (0x10000004) , 0xFF default\n"
|
|
+ "Example, set beacon to 18Mbps on wlan0(2.4G):\n echo \"wlan0 beacon 2 0x10000006\" > /sys/kernel/debug/ieee80211/phy0/ath11k/set_rates\n";
|
|
+
|
|
+ return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
|
|
+}
|
|
+
|
|
+bool check_band_rate_compat(struct ath11k *ar, long rc, int band)
|
|
+{
|
|
+ struct ieee80211_supported_band *sband = NULL;
|
|
+ int br, i = 0;
|
|
+ long rcode = 0;
|
|
+
|
|
+ sband = ar->hw->wiphy->bands[band];
|
|
+ if (sband == NULL) {
|
|
+ ath11k_err(ar->ab, "band not valid\n");
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < sband->n_bitrates; i++) {
|
|
+ br = sband->bitrates[i].bitrate;
|
|
+ rcode = ath11k_mac_get_rate_hw_value(sband->bitrates[i].bitrate);
|
|
+ if (rcode == rc){
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ ath11k_err(ar->ab, "rate-code not found rc=%ld(0x%lx)", rc, rc);
|
|
+ return false;
|
|
+}
|
|
+
|
|
+/* Set the rates for specific types of traffic. */
|
|
+static ssize_t ath11k_write_set_rates(struct file *file,
|
|
+ const char __user *user_buf,
|
|
+ size_t count, loff_t *ppos)
|
|
+{
|
|
+ struct ath11k *ar = file->private_data;
|
|
+ char buf[80];
|
|
+ int ret;
|
|
+ struct ath11k_vif *arvif;
|
|
+ struct ieee80211_vif *vif;
|
|
+ unsigned int vdev_id = 0xFFFF;
|
|
+ char* bufptr = buf;
|
|
+ long rc;
|
|
+ int cfg_band;
|
|
+ struct cfg80211_chan_def def;
|
|
+ char dev_name_match[IFNAMSIZ + 2];
|
|
+ struct wireless_dev *wdev;
|
|
+ int set_rate_type;
|
|
+
|
|
+ memset(buf, 0, sizeof(buf));
|
|
+
|
|
+ simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
|
|
+
|
|
+ /* make sure that buf is null terminated */
|
|
+ buf[sizeof(buf) - 1] = 0;
|
|
+
|
|
+ /* drop the possible '\n' from the end */
|
|
+ if (buf[count - 1] == '\n')
|
|
+ buf[count - 1] = 0;
|
|
+
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+
|
|
+ /* Ignore empty lines, 'echo' appends them sometimes at least. */
|
|
+ if (buf[0] == 0) {
|
|
+ ret = count;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ /* String starts with vdev name, ie 'wlan0' Find the proper vif that
|
|
+ * matches the name.
|
|
+ */
|
|
+ list_for_each_entry(arvif, &ar->arvifs, list) {
|
|
+ vif = arvif->vif;
|
|
+ wdev = ieee80211_vif_to_wdev(vif);
|
|
+
|
|
+ if (!wdev)
|
|
+ continue;
|
|
+ snprintf(dev_name_match, sizeof(dev_name_match) - 1, "%s ",
|
|
+ wdev->netdev->name);
|
|
+ if (strncmp(dev_name_match, buf, strlen(dev_name_match)) == 0) {
|
|
+ vdev_id = arvif->vdev_id;
|
|
+ bufptr = buf + strlen(dev_name_match);
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (vdev_id == 0xFFFF) {
|
|
+ ath11k_warn(ar->ab, "set-rate, unknown netdev name: %s\n", buf);
|
|
+ ret = -EINVAL;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ /* Now, check the type. */
|
|
+ if (strncmp(bufptr, "beacon ", strlen("beacon ")) == 0) {
|
|
+ set_rate_type = WMI_VDEV_PARAM_BEACON_RATE;
|
|
+ bufptr += strlen("beacon ");
|
|
+ }
|
|
+ else if (strncmp(bufptr, "mgmt ", strlen("mgmt ")) == 0) {
|
|
+ set_rate_type = WMI_VDEV_PARAM_MGMT_RATE;
|
|
+ bufptr += strlen("mgmt ");
|
|
+ }
|
|
+ else if (strncmp(bufptr, "bcast ", strlen("bcast ")) == 0) {
|
|
+ set_rate_type = WMI_VDEV_PARAM_BCAST_DATA_RATE;
|
|
+ bufptr += strlen("bcast ");
|
|
+ }
|
|
+ else if (strncmp(bufptr, "mcast ", strlen("mcast ")) == 0) {
|
|
+ set_rate_type = WMI_VDEV_PARAM_MCAST_DATA_RATE;
|
|
+ bufptr += strlen("mcast ");
|
|
+ }
|
|
+ else {
|
|
+ ath11k_warn(ar->ab, "set-rate, invalid rate type: %s\n",
|
|
+ bufptr);
|
|
+ ret = -EINVAL;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ /* And the band */
|
|
+ if (strncmp(bufptr, "2 ", 2) == 0) {
|
|
+ cfg_band = NL80211_BAND_2GHZ;
|
|
+ bufptr += 2;
|
|
+ }
|
|
+ else if (strncmp(bufptr, "5 ", 2) == 0) {
|
|
+ cfg_band = NL80211_BAND_5GHZ;
|
|
+ bufptr += 2;
|
|
+ }
|
|
+ else if (strncmp(bufptr, "60 ", 3) == 0) {
|
|
+ cfg_band = NL80211_BAND_60GHZ;
|
|
+ bufptr += 3;
|
|
+ }
|
|
+ else {
|
|
+ ath11k_warn(ar->ab, "set-rate, invalid band: %s\n",
|
|
+ bufptr);
|
|
+ ret = -EINVAL;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ /* Parse the rate-code. */
|
|
+ ret = kstrtol(bufptr, 0, &rc);
|
|
+ if (ret != 0) {
|
|
+ ath11k_warn(ar->ab, "set-rate, invalid rate-code: %s\n",
|
|
+ bufptr);
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ /* Store the value so we can re-apply it if firmware is restarted. */
|
|
+ if (set_rate_type == WMI_VDEV_PARAM_MGMT_RATE) {
|
|
+ arvif->mgt_rate[cfg_band] = rc;
|
|
+ arvif->mgt_rate_set[cfg_band] = true;
|
|
+ }
|
|
+ else if (set_rate_type == WMI_VDEV_PARAM_BCAST_DATA_RATE) {
|
|
+ arvif->bcast_rate[cfg_band] = rc;
|
|
+ arvif->bcast_rate_set[cfg_band] = true;
|
|
+ }
|
|
+ else if (set_rate_type == WMI_VDEV_PARAM_MCAST_DATA_RATE) {
|
|
+ arvif->mcast_rate[cfg_band] = rc;
|
|
+ arvif->mcast_rate_set[cfg_band] = true;
|
|
+ }
|
|
+ else if (set_rate_type == WMI_VDEV_PARAM_BEACON_RATE) {
|
|
+ arvif->bcn_rate[cfg_band] = rc;
|
|
+ arvif->bcn_rate_set[cfg_band] = true;
|
|
+ }
|
|
+
|
|
+ if (ar->state != ATH11K_STATE_ON &&
|
|
+ ar->state != ATH11K_STATE_RESTARTED) {
|
|
+ /* OK, we will set it when vdev comes up */
|
|
+ ath11k_warn(ar->ab, "set-rates, deferred-state is down, vdev %i type: 0x%x rc: 0x%lx band: %d\n",
|
|
+ arvif->vdev_id, set_rate_type, rc, cfg_band);
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ if (ath11k_mac_vif_chan(vif, &def) == 0) {
|
|
+ if (def.chan->band != cfg_band) {
|
|
+ /* We stored value, will apply it later if we move to
|
|
+ * the different band.
|
|
+ */
|
|
+ ath11k_warn(ar->ab, "set-rates, deferred-other-band, vdev %i type: 0x%x rc: 0x%lx band: %d\n",
|
|
+ arvif->vdev_id, set_rate_type,
|
|
+ rc, cfg_band);
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ if (check_band_rate_compat(ar, rc, def.chan->band) == false) {
|
|
+ ath11k_warn(ar->ab, "set-rate, wrong rate code\n");
|
|
+ ret = -EINVAL;
|
|
+ goto exit;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* finally, send results to the firmware */
|
|
+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
|
+ set_rate_type, rc);
|
|
+ if (ret) {
|
|
+ ath11k_warn(ar->ab, "set-rates: vdev %i failed to set fixed rate, param 0x%x rate-code 0x%02lx\n",
|
|
+ arvif->vdev_id, set_rate_type, rc);
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ ath11k_warn(ar->ab, "set-rates, vdev %i type: 0x%x rc: 0x%lx band: %d\n",
|
|
+ arvif->vdev_id, set_rate_type, rc, cfg_band);
|
|
+
|
|
+ ret = count;
|
|
+
|
|
+exit:
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static const struct file_operations fops_set_rates = {
|
|
+ .read = ath11k_read_set_rates,
|
|
+ .write = ath11k_write_set_rates,
|
|
+ .open = simple_open,
|
|
+ .owner = THIS_MODULE,
|
|
+ .llseek = default_llseek,
|
|
+};
|
|
+
|
|
static ssize_t ath11k_write_enable_m3_dump(struct file *file,
|
|
const char __user *ubuf,
|
|
size_t count, loff_t *ppos)
|
|
@@ -2532,6 +2756,9 @@ int ath11k_debug_register(struct ath11k
|
|
&fops__btcoex_duty_cycle);
|
|
debugfs_create_file("dump_mgmt_stats", 0644, ar->debug.debugfs_pdev,
|
|
ar, &fops_dump_mgmt_stats);
|
|
+ debugfs_create_file("set_rates", 0600, ar->debug.debugfs_pdev,
|
|
+ ar, &fops_set_rates);
|
|
+
|
|
|
|
if (ar->hw->wiphy->bands[NL80211_BAND_5GHZ]) {
|
|
debugfs_create_file("dfs_simulate_radar", 0200,
|
|
Index: backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/mac.c
|
|
===================================================================
|
|
--- backports-20200902_001-4.4.60-931c337125.orig/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -414,8 +414,8 @@ static u8 ath11k_parse_mpdudensity(u8 mp
|
|
}
|
|
}
|
|
|
|
-static int ath11k_mac_vif_chan(struct ieee80211_vif *vif,
|
|
- struct cfg80211_chan_def *def)
|
|
+int ath11k_mac_vif_chan(struct ieee80211_vif *vif,
|
|
+ struct cfg80211_chan_def *def)
|
|
{
|
|
struct ieee80211_chanctx_conf *conf;
|
|
|
|
@@ -2633,7 +2633,7 @@ static void ath11k_bss_disassoc(struct i
|
|
/* TODO: cancel connection_loss_work */
|
|
}
|
|
|
|
-static u32 ath11k_mac_get_rate_hw_value(int bitrate)
|
|
+u32 ath11k_mac_get_rate_hw_value(int bitrate)
|
|
{
|
|
u32 preamble;
|
|
u16 hw_value;
|
|
@@ -2672,6 +2672,11 @@ static void ath11k_recalculate_mgmt_rate
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
+ /* If user has over-ridden the mgt rate, don't muck with it here. */
|
|
+ if (arvif->mgt_rate_set[def->chan->band] ||
|
|
+ arvif->bcn_rate_set[def->chan->band])
|
|
+ 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;
|
|
@@ -2682,12 +2687,14 @@ static void ath11k_recalculate_mgmt_rate
|
|
return;
|
|
}
|
|
|
|
+ arvif->mgt_rate[def->chan->band] = hw_rate_code;
|
|
vdev_param = WMI_VDEV_PARAM_MGMT_RATE;
|
|
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
|
|
hw_rate_code);
|
|
if (ret)
|
|
ath11k_warn(ar->ab, "failed to set mgmt tx rate %d\n", ret);
|
|
|
|
+ arvif->bcn_rate[def->chan->band] = hw_rate_code;
|
|
vdev_param = WMI_VDEV_PARAM_BEACON_RATE;
|
|
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, vdev_param,
|
|
hw_rate_code);
|
|
@@ -3116,17 +3123,23 @@ static void ath11k_mac_op_bss_info_chang
|
|
rate = ATH11K_HW_RATE_CODE(hw_value, 0, preamble);
|
|
|
|
ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
|
|
- "mac vdev %d mcast_rate %x\n",
|
|
- arvif->vdev_id, rate);
|
|
-
|
|
- vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
|
|
- ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
|
- vdev_param, rate);
|
|
- if (ret)
|
|
- ath11k_warn(ar->ab,
|
|
- "failed to set mcast rate on vdev %i: %d\n",
|
|
- arvif->vdev_id, ret);
|
|
+ "mac vdev %d mcast_rate %x override-set-mcast: %d override-set-bcast: %d\n",
|
|
+ arvif->vdev_id, rate, arvif->mcast_rate_set[band],
|
|
+ arvif->bcast_rate_set[band]);
|
|
+
|
|
+ if (!arvif->mcast_rate_set[band]) {
|
|
+ arvif->mcast_rate[band] = rate;
|
|
+ vdev_param = WMI_VDEV_PARAM_MCAST_DATA_RATE;
|
|
+ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
|
+ vdev_param, rate);
|
|
+ if (ret)
|
|
+ ath11k_warn(ar->ab,
|
|
+ "failed to set mcast rate on vdev %i: %d\n",
|
|
+ arvif->vdev_id, ret);
|
|
+ }
|
|
|
|
+ if (!arvif->bcast_rate_set[band]) {
|
|
+ arvif->bcast_rate[band] = rate;
|
|
vdev_param = WMI_VDEV_PARAM_BCAST_DATA_RATE;
|
|
ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
|
|
vdev_param, rate);
|
|
@@ -3134,6 +3147,7 @@ static void ath11k_mac_op_bss_info_chang
|
|
ath11k_warn(ar->ab,
|
|
"failed to set bcast rate on vdev %i: %d\n",
|
|
arvif->vdev_id, ret);
|
|
+ }
|
|
}
|
|
|
|
if (changed & BSS_CHANGED_BASIC_RATES &&
|
|
@@ -5832,6 +5846,12 @@ static int ath11k_mac_op_add_interface(s
|
|
|
|
memset(arvif, 0, sizeof(*arvif));
|
|
|
|
+ memset(&arvif->bcast_rate, WMI_FIXED_RATE_NONE,
|
|
+ sizeof(arvif->bcast_rate));
|
|
+ memset(&arvif->mcast_rate, WMI_FIXED_RATE_NONE,
|
|
+ sizeof(arvif->mcast_rate));
|
|
+ memset(&arvif->mgt_rate, WMI_FIXED_RATE_NONE, sizeof(arvif->mgt_rate));
|
|
+
|
|
arvif->ar = ar;
|
|
arvif->vif = vif;
|
|
|
|
Index: backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/mac.h
|
|
===================================================================
|
|
--- backports-20200902_001-4.4.60-931c337125.orig/drivers/net/wireless/ath/ath11k/mac.h
|
|
+++ backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/mac.h
|
|
@@ -164,4 +164,8 @@ u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
|
|
enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw);
|
|
enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher);
|
|
void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif);
|
|
+int ath11k_mac_vif_chan(struct ieee80211_vif *vif,
|
|
+ struct cfg80211_chan_def *def);
|
|
+
|
|
+u32 ath11k_mac_get_rate_hw_value(int bitrate);
|
|
#endif
|
|
Index: backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/core.h
|
|
===================================================================
|
|
--- backports-20200902_001-4.4.60-931c337125.orig/drivers/net/wireless/ath/ath11k/core.h
|
|
+++ backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/core.h
|
|
@@ -265,6 +265,23 @@ struct ath11k_vif {
|
|
#ifdef CPTCFG_ATH11K_NSS_SUPPORT
|
|
struct arvif_nss nss;
|
|
#endif
|
|
+ /* Firmware allows configuring rate of each of these traffic types.
|
|
+ * 0xFF will mean value has not been set by user, and in that case,
|
|
+ * we will auto-adjust the rates based on the legacy rate mask.
|
|
+ **/
|
|
+ /* TODO-BEN: This may conflict with upstream code? */
|
|
+ u8 mcast_rate[NUM_NL80211_BANDS];
|
|
+ u8 bcast_rate[NUM_NL80211_BANDS];
|
|
+ u8 mgt_rate[NUM_NL80211_BANDS];
|
|
+ u8 bcn_rate[NUM_NL80211_BANDS];
|
|
+
|
|
+ /* Flag if these rates are set through debugfs, in that case, ignore
|
|
+ * setting from farther up the stack.
|
|
+ */
|
|
+ bool mcast_rate_set[NUM_NL80211_BANDS];
|
|
+ bool bcast_rate_set[NUM_NL80211_BANDS];
|
|
+ bool mgt_rate_set[NUM_NL80211_BANDS];
|
|
+ bool bcn_rate_set[NUM_NL80211_BANDS];
|
|
};
|
|
|
|
struct ath11k_vif_iter {
|