From: Sven Eckelmann <sven@narfation.org>
Date: Fri, 16 Feb 2018 13:49:51 +0100
Subject: [PATCH] ath10k: Allow to configure bcast/mcast rate
TODO:
* find better way to get mcast_rate
* better get the lowest configured basic rate for APs
* remove netifd WAR
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Forwarded: no
not yet in the correct shape
---
drivers/net/wireless/ath/ath10k/core.h | 1 +
drivers/net/wireless/ath/ath10k/debug.c | 78 ++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/debug.h | 11 ++++
drivers/net/wireless/ath/ath10k/mac.c | 113 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath10k/mac.h | 1 +
5 files changed, 204 insertions(+)
@@ -423,6 +423,7 @@ struct ath10k_vif {
bool nohwcrypt;
int num_legacy_stations;
int txpower;
+ u16 mcast_rate;
struct wmi_wmm_params_all_arg wmm_params;
struct work_struct ap_csa_work;
struct delayed_work connection_loss_work;
@@ -23,6 +23,7 @@
#include <linux/firmware.h>
#include "core.h"
+#include "mac.h"
#include "debug.h"
#include "hif.h"
#include "wmi-ops.h"
@@ -2454,6 +2455,83 @@ void ath10k_debug_unregister(struct ath10k *ar)
cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
}
+
+
+static ssize_t ath10k_write_mcast_rate(struct file *file,
+ const char __user *ubuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath10k_vif *arvif = file->private_data;
+ struct ath10k *ar = arvif->ar;
+ ssize_t ret = 0;
+ u32 mcast_rate;
+
+ ret = kstrtou32_from_user(ubuf, count, 0, &mcast_rate);
+ if (ret)
+ return ret;
+
+ mutex_lock(&ar->conf_mutex);
+
+ arvif->mcast_rate = mcast_rate;
+ ret = ath10k_mac_set_mcast_rate(arvif);
+ if (ret)
+ goto unlock;
+
+ ret = count;
+unlock:
+ mutex_unlock(&ar->conf_mutex);
+
+ return ret;
+}
+
+static ssize_t ath10k_read_mcast_rate(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
+
+{
+ struct ath10k_vif *arvif = file->private_data;
+ struct ath10k *ar = arvif->ar;
+ char buf[32];
+ int len = 0;
+ u16 mcast_rate;
+
+ mutex_lock(&ar->conf_mutex);
+ mcast_rate = arvif->mcast_rate;
+ mutex_unlock(&ar->conf_mutex);
+
+ len = scnprintf(buf, sizeof(buf) - len, "%u\n", mcast_rate);
+
+ return simple_read_from_buffer(ubuf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_mcast_rate = {
+ .read = ath10k_read_mcast_rate,
+ .write = ath10k_write_mcast_rate,
+ .open = simple_open
+};
+
+int ath10k_debug_register_netdev(struct ath10k_vif *arvif)
+{
+ struct dentry *debugfs_netdev;
+
+ debugfs_netdev = debugfs_create_dir("ath10k", arvif->vif->debugfs_dir);
+ if (IS_ERR_OR_NULL(debugfs_netdev)) {
+ if (IS_ERR(debugfs_netdev))
+ return PTR_ERR(debugfs_netdev);
+
+ return -ENOMEM;
+ }
+
+ debugfs_create_file("mcast_rate", S_IRUGO | S_IWUSR,
+ debugfs_netdev, arvif,
+ &fops_mcast_rate);
+
+ return 0;
+}
+
+void ath10k_debug_unregister_netdev(struct ath10k_vif *arvif)
+{
+}
+
#endif /* CPTCFG_ATH10K_DEBUGFS */
#ifdef CPTCFG_ATH10K_DEBUG
@@ -77,6 +77,8 @@ int ath10k_debug_create(struct ath10k *ar);
void ath10k_debug_destroy(struct ath10k *ar);
int ath10k_debug_register(struct ath10k *ar);
void ath10k_debug_unregister(struct ath10k *ar);
+int ath10k_debug_register_netdev(struct ath10k_vif *arvif);
+void ath10k_debug_unregister_netdev(struct ath10k_vif *arvif);
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
void ath10k_debug_tpc_stats_process(struct ath10k *ar,
struct ath10k_tpc_stats *tpc_stats);
@@ -134,6 +136,15 @@ static inline void ath10k_debug_unregister(struct ath10k *ar)
{
}
+static inline int ath10k_debug_register_netdev(struct ath10k_vif *arvif)
+{
+ return 0;
+}
+
+static inline void ath10k_debug_unregister_netdev(struct ath10k_vif *arvif)
+{
+}
+
static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
struct sk_buff *skb)
{
@@ -152,6 +152,101 @@ u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
return 0;
}
+int ath10k_mac_set_mcast_rate(struct ath10k_vif *arvif)
+{
+ const struct ieee80211_supported_band *sband;
+ struct ath10k *ar = arvif->ar;
+ struct cfg80211_chan_def def;
+ enum nl80211_band band;
+ u16 best_bitrate = 0;
+ u16 hw_value;
+ u32 ratemask;
+ u8 rate_code;
+ u8 preamble;
+ int i;
+ int ret;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ if (ath10k_mac_vif_chan(arvif->vif, &def))
+ return -EPERM;
+
+ band = def.chan->band;
+ sband = ar->hw->wiphy->bands[band];
+ ratemask = arvif->bitrate_mask.control[band].legacy;
+
+ /* it seems that arvif is lost on every fw crash
+ * read the lowest mcast read of bss
+ */
+ if (!arvif->mcast_rate && arvif->vif->bss_conf.mcast_rate[band])
+ arvif->mcast_rate = sband->bitrates[arvif->vif->bss_conf.mcast_rate[band] - 1].bitrate;
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (!(ratemask & BIT(i)))
+ continue;
+
+ if (best_bitrate &&
+ arvif->mcast_rate != sband->bitrates[i].bitrate)
+ continue;
+
+ best_bitrate = sband->bitrates[i].bitrate;
+ hw_value = sband->bitrates[i].hw_value;
+
+ if (ath10k_mac_bitrate_is_cck(sband->bitrates[i].bitrate)) {
+ preamble = WMI_RATE_PREAMBLE_CCK;
+
+ /* QCA didn't use the correct rate values for CA99x0
+ * and above (ath10k_g_rates_rev2)
+ */
+ switch (sband->bitrates[i].bitrate) {
+ case 10:
+ hw_value = ATH10K_HW_RATE_CCK_LP_1M;
+ break;
+ case 20:
+ hw_value = ATH10K_HW_RATE_CCK_LP_2M;
+ break;
+ case 55:
+ hw_value = ATH10K_HW_RATE_CCK_LP_5_5M;
+ break;
+ case 110:
+ hw_value = ATH10K_HW_RATE_CCK_LP_11M;
+ break;
+ }
+ } else {
+ preamble = WMI_RATE_PREAMBLE_OFDM;
+ }
+
+ rate_code = ATH10K_HW_RATECODE(hw_value, 0, preamble);
+ }
+
+ if (!best_bitrate) {
+ ath10k_warn(ar, "failed to select multicast rate\n");
+ return -EINVAL;
+ }
+
+ arvif->mcast_rate = best_bitrate;
+
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
+ ar->wmi.vdev_param->mgmt_rate,
+ rate_code);
+ if (ret)
+ ath10k_warn(ar, "failed to set mgmt fixed rate: %d\n",ret);
+
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
+ ar->wmi.vdev_param->bcast_data_rate,
+ rate_code);
+ if (ret)
+ ath10k_warn(ar, "failed to set bcast fixed rate: %d\n",ret);
+
+ ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
+ ar->wmi.vdev_param->mcast_data_rate,
+ rate_code);
+ if (ret)
+ ath10k_warn(ar, "failed to set mcast fixed rate: %d\n",ret);
+
+ return 0;
+}
+
static int ath10k_mac_get_max_vht_mcs_map(u16 mcs_map, int nss)
{
switch ((mcs_map >> (2 * nss)) & 0x3) {
@@ -5133,6 +5228,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->htt.tx_lock);
mutex_unlock(&ar->conf_mutex);
+
+ ath10k_debug_register_netdev(arvif);
+
return 0;
err_peer_delete:
@@ -5179,6 +5277,8 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
cancel_work_sync(&arvif->ap_csa_work);
cancel_delayed_work_sync(&arvif->connection_loss_work);
+ ath10k_debug_unregister_netdev(arvif);
+
mutex_lock(&ar->conf_mutex);
spin_lock_bh(&ar->data_lock);
@@ -5474,6 +5574,12 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
}
+ /* TODO when should we actually call that */
+ ret = ath10k_mac_set_mcast_rate(arvif);
+ if (ret)
+ ath10k_warn(ar, "failed to set multicast rate params on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+
mutex_unlock(&ar->conf_mutex);
}
@@ -6958,6 +7064,13 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
goto exit;
}
+ ret = ath10k_mac_set_mcast_rate(arvif);
+ if (ret) {
+ ath10k_warn(ar, "failed to set multicast rate params on vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ goto exit;
+ }
+
exit:
mutex_unlock(&ar->conf_mutex);
@@ -69,6 +69,7 @@ u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
u8 hw_rate, bool cck);
u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
u32 bitrate);
+int ath10k_mac_set_mcast_rate(struct ath10k_vif *arvif);
void ath10k_mac_tx_lock(struct ath10k *ar, int reason);
void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);