Files
wlan-ap/feeds/wifi-ax/mac80211/patches/pending/214-debugfs-set-rate-mgmt-mcast-bcn.patch
Chaitanya Godavarthi 0ec23e8dba wifi-2940: Add ath11k beacon and mcast rate
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>
2021-07-28 09:12:46 -04:00

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 {