[openwrt/openwrt] mac80211: remove extra patch accidentally added during rebase

LEDE Commits lede-commits at lists.infradead.org
Fri Jun 18 00:56:31 PDT 2021


nbd pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/165a0263643af6831edcef28d2863babb660d24b

commit 165a0263643af6831edcef28d2863babb660d24b
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Fri Jun 18 09:55:46 2021 +0200

    mac80211: remove extra patch accidentally added during rebase
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ...nstrel_ht-add-debugfs-monitoring-controll.patch | 888 ---------------------
 1 file changed, 888 deletions(-)

diff --git a/package/kernel/mac80211/patches/subsys/361-mac80211-minstrel_ht-add-debugfs-monitoring-controll.patch b/package/kernel/mac80211/patches/subsys/361-mac80211-minstrel_ht-add-debugfs-monitoring-controll.patch
deleted file mode 100644
index ef57234bea..0000000000
--- a/package/kernel/mac80211/patches/subsys/361-mac80211-minstrel_ht-add-debugfs-monitoring-controll.patch
+++ /dev/null
@@ -1,888 +0,0 @@
-From: Felix Fietkau <nbd at nbd.name>
-Date: Mon, 1 Feb 2021 10:47:58 +0100
-Subject: [PATCH] mac80211: minstrel_ht: add debugfs monitoring/controlling
- API
-
-This allows user space to monitor tx status and take over rate control
-functionality.
-
-Signed-off-by: Felix Fietkau <nbd at nbd.name>
----
- create mode 100644 net/mac80211/rc80211_minstrel_ht_api.c
-
---- a/local-symbols
-+++ b/local-symbols
-@@ -49,6 +49,7 @@ LIB80211_DEBUG=
- MAC80211=
- MAC80211_HAS_RC=
- MAC80211_RC_MINSTREL=
-+MAC80211_RC_MINSTREL_DEBUGFS_API=
- MAC80211_RC_DEFAULT_MINSTREL=
- MAC80211_RC_DEFAULT=
- MAC80211_MESH=
---- a/net/mac80211/Kconfig
-+++ b/net/mac80211/Kconfig
-@@ -29,6 +29,15 @@ config MAC80211_RC_MINSTREL
- 	help
- 	  This option enables the 'minstrel' TX rate control algorithm
- 
-+config MAC80211_RC_MINSTREL_DEBUGFS_API
-+	bool "Minstrel debugfs userspace control API"
-+	depends on MAC80211_RC_MINSTREL
-+	depends on MAC80211_DEBUGFS
-+	select RELAY
-+	help
-+	  This option creates debugfs files that allow user space to observe
-+	  and/or control minstrel rate selection behavior
-+
- choice
- 	prompt "Default rate control algorithm"
- 	depends on MAC80211_HAS_RC
---- a/net/mac80211/Makefile
-+++ b/net/mac80211/Makefile
-@@ -61,6 +61,9 @@ rc80211_minstrel-y := \
- rc80211_minstrel-$(CPTCFG_MAC80211_DEBUGFS) += \
- 	rc80211_minstrel_ht_debugfs.o
- 
-+rc80211_minstrel-$(CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API) += \
-+	rc80211_minstrel_ht_api.o
-+
- mac80211-$(CPTCFG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
- 
- ccflags-y += -DDEBUG
---- a/net/mac80211/rc80211_minstrel_ht.c
-+++ b/net/mac80211/rc80211_minstrel_ht.c
-@@ -276,7 +276,8 @@ static const u8 minstrel_sample_seq[] =
- };
- 
- static void
--minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
-+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+			 bool force);
- 
- /*
-  * Some VHT MCSes are invalid (when Ndbps / Nes is not an integer)
-@@ -346,7 +347,7 @@ minstrel_vht_get_group_idx(struct ieee80
- 
- static struct minstrel_rate_stats *
- minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
--		      struct ieee80211_tx_rate *rate)
-+		      struct ieee80211_tx_rate *rate, u16 *dest_idx)
- {
- 	int group, idx;
- 
-@@ -381,6 +382,7 @@ minstrel_ht_get_stats(struct minstrel_pr
- 
- 	idx = 0;
- out:
-+	*dest_idx = MI_RATE(group, idx);
- 	return &mi->groups[group].rates[idx];
- }
- 
-@@ -1024,6 +1026,8 @@ minstrel_ht_update_stats(struct minstrel
- 			tp_rate = tmp_legacy_tp_rate;
- 
- 		for (i = MCS_GROUP_RATES - 1; i >= 0; i--) {
-+			bool changed;
-+
- 			if (!(mi->supported[group] & BIT(i)))
- 				continue;
- 
-@@ -1031,7 +1035,11 @@ minstrel_ht_update_stats(struct minstrel
- 
- 			mrs = &mg->rates[i];
- 			mrs->retry_updated = false;
-+			changed = mrs->attempts > 0;
- 			minstrel_ht_calc_rate_stats(mp, mrs);
-+			if (changed)
-+				minstrel_ht_report_rate_update(mp, mi, index,
-+							       mrs);
- 
- 			if (mrs->att_hist)
- 				last_prob = max(last_prob, mrs->prob_avg);
-@@ -1080,7 +1088,8 @@ minstrel_ht_update_stats(struct minstrel
- 
- 	mi->max_prob_rate = tmp_max_prob_rate;
- 
--	minstrel_ht_refill_sample_rates(mi);
-+	if (!minstrel_ht_manual_mode(mp))
-+		minstrel_ht_refill_sample_rates(mi);
- 
- #ifdef CPTCFG_MAC80211_DEBUGFS
- 	/* use fixed index if set */
-@@ -1177,6 +1186,7 @@ minstrel_ht_tx_status(void *priv, struct
- 	struct minstrel_priv *mp = priv;
- 	u32 update_interval = mp->update_interval;
- 	bool last, update = false;
-+	u16 rate_list[IEEE80211_TX_MAX_RATES] = {};
- 	int i;
- 
- 	/* This packet was aggregated but doesn't carry status info */
-@@ -1208,13 +1218,15 @@ minstrel_ht_tx_status(void *priv, struct
- 		last = (i == IEEE80211_TX_MAX_RATES - 1) ||
- 		       !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]);
- 
--		rate = minstrel_ht_get_stats(mp, mi, &ar[i]);
-+		rate = minstrel_ht_get_stats(mp, mi, &ar[i], &rate_list[i]);
- 		if (last)
- 			rate->success += info->status.ampdu_ack_len;
- 
- 		rate->attempts += ar[i].count * info->status.ampdu_len;
- 	}
- 
-+	minstrel_ht_report_tx_status(mp, mi, info, rate_list, i);
-+
- 	if (mp->hw->max_rates > 1) {
- 		/*
- 		 * check for sudden death of spatial multiplexing,
-@@ -1236,7 +1248,7 @@ minstrel_ht_tx_status(void *priv, struct
- 	}
- 
- 	if (update)
--		minstrel_ht_update_rates(mp, mi);
-+		minstrel_ht_update_rates(mp, mi, false);
- }
- 
- static void
-@@ -1299,7 +1311,7 @@ minstrel_calc_retransmit(struct minstrel
- }
- 
- 
--static void
-+void
- minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-                      struct ieee80211_sta_rates *ratetbl, int offset, int index)
- {
-@@ -1408,11 +1420,15 @@ minstrel_ht_get_max_amsdu_len(struct min
- }
- 
- static void
--minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
-+minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+			 bool force)
- {
- 	struct ieee80211_sta_rates *rates;
- 	int i = 0;
- 
-+	if (minstrel_ht_manual_mode(mp) && !force)
-+		return;
-+
- 	rates = kzalloc(sizeof(*rates), GFP_ATOMIC);
- 	if (!rates)
- 		return;
-@@ -1439,7 +1455,7 @@ minstrel_ht_get_sample_rate(struct minst
- {
- 	u8 seq;
- 
--	if (mp->hw->max_rates > 1) {
-+	if (mp->hw->max_rates > 1 && !minstrel_ht_manual_mode(mp)) {
- 		seq = mi->sample_seq;
- 		mi->sample_seq = (seq + 1) % ARRAY_SIZE(minstrel_sample_seq);
- 		seq = minstrel_sample_seq[seq];
-@@ -1689,7 +1705,9 @@ minstrel_ht_update_caps(void *priv, stru
- 
- 	/* create an initial rate table with the lowest supported rates */
- 	minstrel_ht_update_stats(mp, mi);
--	minstrel_ht_update_rates(mp, mi);
-+	minstrel_ht_update_rates(mp, mi, true);
-+
-+	minstrel_ht_sta_update(mp, mi);
- }
- 
- static void
-@@ -1725,12 +1743,18 @@ minstrel_ht_alloc_sta(void *priv, struct
- 			max_rates = sband->n_bitrates;
- 	}
- 
--	return kzalloc(sizeof(*mi), gfp);
-+	mi = kzalloc(sizeof(*mi), gfp);
-+#ifdef CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API
-+	INIT_LIST_HEAD(&mi->list);
-+#endif
-+
-+	return mi;
- }
- 
- static void
- minstrel_ht_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta)
- {
-+	minstrel_ht_sta_remove(priv, priv_sta);
- 	kfree(priv_sta);
- }
- 
-@@ -1841,12 +1865,14 @@ static void minstrel_ht_add_debugfs(stru
- 	mp->fixed_rate_idx = (u32) -1;
- 	debugfs_create_u32("fixed_rate_idx", S_IRUGO | S_IWUGO, debugfsdir,
- 			   &mp->fixed_rate_idx);
-+	minstrel_ht_add_debugfs_api(hw, priv, debugfsdir);
- }
- #endif
- 
- static void
- minstrel_ht_free(void *priv)
- {
-+	minstrel_ht_remove_debugfs_api(priv);
- 	kfree(priv);
- }
- 
---- a/net/mac80211/rc80211_minstrel_ht.h
-+++ b/net/mac80211/rc80211_minstrel_ht.h
-@@ -72,6 +72,10 @@
- #define MINSTREL_SAMPLE_RATES		5 /* rates per sample type */
- #define MINSTREL_SAMPLE_INTERVAL	(HZ / 50)
- 
-+#define MINSTREL_MONITOR_STA		BIT(0)
-+#define MINSTREL_MONITOR_TXS		BIT(1)
-+#define MINSTREL_MONITOR_STATS		BIT(2)
-+
- struct minstrel_priv {
- 	struct ieee80211_hw *hw;
- 	bool has_mrr;
-@@ -93,6 +97,13 @@ struct minstrel_priv {
- 	 */
- 	u32 fixed_rate_idx;
- #endif
-+#ifdef CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API
-+	struct rchan *relay_ev;
-+	struct list_head stations;
-+	spinlock_t lock;
-+	u8 monitor;
-+	bool manual;
-+#endif
- };
- 
- 
-@@ -153,6 +164,9 @@ struct minstrel_sample_category {
- };
- 
- struct minstrel_ht_sta {
-+#ifdef CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API
-+	struct list_head list;
-+#endif
- 	struct ieee80211_sta *sta;
- 
- 	/* ampdu length (average, per sampling interval) */
-@@ -197,6 +211,80 @@ struct minstrel_ht_sta {
- };
- 
- void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
-+
-+#ifdef CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API
-+void minstrel_ht_sta_update(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
-+void minstrel_ht_sta_remove(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
-+void __minstrel_ht_report_tx_status(struct minstrel_priv *mp,
-+				    struct minstrel_ht_sta *mi,
-+				    struct ieee80211_tx_info *info,
-+				    u16 *rate_list, int n_rates);
-+void __minstrel_ht_report_rate_update(struct minstrel_priv *mp,
-+				      struct minstrel_ht_sta *mi, u16 rate,
-+				      struct minstrel_rate_stats *mrs);
-+void minstrel_ht_add_debugfs_api(struct ieee80211_hw *hw, void *priv,
-+				 struct dentry *dir);
-+void minstrel_ht_remove_debugfs_api(void *priv);
-+#else
-+static inline void
-+minstrel_ht_sta_update(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
-+{
-+}
-+static inline void
-+minstrel_ht_sta_remove(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
-+{
-+}
-+static inline void
-+minstrel_ht_add_debugfs_api(struct ieee80211_hw *hw, void *priv,
-+			    struct dentry *dir)
-+{
-+}
-+static inline void
-+minstrel_ht_remove_debugfs_api(void *priv)
-+{
-+}
-+#endif
-+
-+static inline void
-+minstrel_ht_report_tx_status(struct minstrel_priv *mp,
-+			     struct minstrel_ht_sta *mi,
-+			     struct ieee80211_tx_info *info,
-+			     u16 *rate_list, int n_rates)
-+{
-+#ifdef CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API
-+	if (!(mp->monitor & MINSTREL_MONITOR_TXS))
-+		return;
-+
-+	__minstrel_ht_report_tx_status(mp, mi, info, rate_list, n_rates);
-+#endif
-+}
-+
-+static inline void
-+minstrel_ht_report_rate_update(struct minstrel_priv *mp,
-+			       struct minstrel_ht_sta *mi, u16 rate,
-+			       struct minstrel_rate_stats *mrs)
-+{
-+#ifdef CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API
-+	if (!(mp->monitor & MINSTREL_MONITOR_STATS))
-+		return;
-+
-+	__minstrel_ht_report_rate_update(mp, mi, rate, mrs);
-+#endif
-+}
-+
-+static inline bool
-+minstrel_ht_manual_mode(struct minstrel_priv *mp)
-+{
-+#ifdef CPTCFG_MAC80211_RC_MINSTREL_DEBUGFS_API
-+	return mp->manual;
-+#else
-+	return false;
-+#endif
-+}
-+
-+void minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+						  struct ieee80211_sta_rates *ratetbl, int offset,
-+						  int index);
- int minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate,
- 			   int prob_avg);
- 
---- /dev/null
-+++ b/net/mac80211/rc80211_minstrel_ht_api.c
-@@ -0,0 +1,540 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (C) 2021 Felix Fietkau <nbd at nbd.name>
-+ */
-+#include <linux/kernel.h>
-+#include <linux/debugfs.h>
-+#include <linux/relay.h>
-+#include <net/mac80211.h>
-+#include "rc80211_minstrel_ht.h"
-+
-+enum sta_cmd {
-+	STA_CMD_PROBE,
-+	STA_CMD_RATES,
-+};
-+
-+static void
-+minstrel_ht_print_rate_durations(struct seq_file *s, int group)
-+{
-+	const struct mcs_group *g = &minstrel_mcs_groups[group];
-+	int n_rates;
-+	int i;
-+
-+	if (g->flags & IEEE80211_TX_RC_VHT_MCS)
-+		n_rates = 10;
-+	else
-+		n_rates = 8;
-+
-+	seq_printf(s, "%x", g->duration[0] << g->shift);
-+	for (i = 1; i < n_rates; i++)
-+		seq_printf(s, ",%x", g->duration[i] << g->shift);
-+}
-+
-+static int
-+minstrel_ht_read_api_info(struct seq_file *s, void *data)
-+{
-+	int i;
-+
-+	seq_printf(s, "#group;index;offset;type;nss;bw;gi;airtime\n");
-+	seq_printf(s, "#sta;action;macaddr;overhead_mcs;overhead_legacy;supported\n");
-+	seq_printf(s, "#txs;macaddr;num_frames;num_acked;probe;rates;counts\n");
-+	seq_printf(s, "#stats;macaddr;rate;avg_prob;avg_tp;cur_success;cur_attempts;hist_success;hist_attempts\n");
-+	seq_printf(s, "#rates;macaddr;rates;counts\n");
-+	seq_printf(s, "#probe;macaddr;rate\n");
-+	for (i = 0; i < MINSTREL_GROUPS_NB; i++) {
-+		const struct mcs_group *g = &minstrel_mcs_groups[i];
-+		const char *type;
-+
-+		if (i == MINSTREL_CCK_GROUP)
-+			type = "cck";
-+		else if (i == MINSTREL_OFDM_GROUP)
-+			type = "ofdm";
-+		else if (g->flags & IEEE80211_TX_RC_VHT_MCS)
-+			type = "vht";
-+		else
-+			type = "ht";
-+
-+		seq_printf(s, "group;%x;%x;%s;%x;%x;%x;",
-+			   i, (u32) MI_RATE(i, 0), type, g->streams, g->bw,
-+			   !!(g->flags & IEEE80211_TX_RC_SHORT_GI));
-+		minstrel_ht_print_rate_durations(s, i);
-+		seq_printf(s, "\n");
-+	}
-+
-+	return 0;
-+}
-+
-+static struct dentry *
-+create_buf_file_cb(const char *filename, struct dentry *parent, umode_t mode,
-+		   struct rchan_buf *buf, int *is_global)
-+{
-+	struct dentry *f;
-+
-+	f = debugfs_create_file("api_event", mode, parent, buf,
-+				&relay_file_operations);
-+	if (IS_ERR(f))
-+		return NULL;
-+
-+	*is_global = 1;
-+
-+	return f;
-+}
-+
-+static int
-+remove_buf_file_cb(struct dentry *f)
-+{
-+	debugfs_remove(f);
-+
-+	return 0;
-+}
-+
-+static struct rchan_callbacks relay_ev_cb = {
-+	.create_buf_file = create_buf_file_cb,
-+	.remove_buf_file = remove_buf_file_cb,
-+};
-+
-+static void
-+minstrel_ht_dump_sta(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+		     const char *type)
-+{
-+	char info[64 + MINSTREL_GROUPS_NB * 4];
-+	int ofs = 0;
-+	int i;
-+
-+	ofs += scnprintf(info + ofs, sizeof(info) - ofs, "%llx;sta;%s;%pM;%x;%x;",
-+			(unsigned long long)ktime_get_boottime_ns(),
-+			 type, mi->sta->addr, mi->overhead, mi->overhead_legacy);
-+
-+	ofs += scnprintf(info + ofs, sizeof(info) - ofs, "%x",
-+			 mi->supported[0]);
-+	for (i = 1; i < MINSTREL_GROUPS_NB; i++)
-+		ofs += scnprintf(info + ofs, sizeof(info) - ofs, ",%x",
-+				 mi->supported[i]);
-+
-+	ofs += scnprintf(info + ofs, sizeof(info) - ofs, "\n");
-+	relay_write(mp->relay_ev, info, ofs);
-+	relay_flush(mp->relay_ev);
-+}
-+
-+static void
-+__minstrel_ht_dump_stations(struct minstrel_priv *mp, const char *type)
-+{
-+	struct minstrel_ht_sta *mi;
-+
-+	list_for_each_entry(mi, &mp->stations, list)
-+		minstrel_ht_dump_sta(mp, mi, type);
-+}
-+
-+static void
-+minstrel_ht_dump_stations(struct minstrel_priv *mp)
-+{
-+	spin_lock_bh(&mp->lock);
-+	__minstrel_ht_dump_stations(mp, "dump");
-+	spin_unlock_bh(&mp->lock);
-+}
-+
-+static void
-+minstrel_ht_api_start(struct minstrel_priv *mp, char *params)
-+{
-+	char *cur;
-+	u8 mask = 0;
-+
-+	spin_lock_bh(&mp->lock);
-+
-+	while ((cur = strsep(&params, ";")) != NULL) {
-+		if (!strlen(cur))
-+			break;
-+
-+		if (!strcmp(cur, "txs"))
-+			mask |= MINSTREL_MONITOR_TXS;
-+		else if (!strcmp(cur, "sta"))
-+			mask |= MINSTREL_MONITOR_STA;
-+		else if (!strcmp(cur, "stats"))
-+			mask |= MINSTREL_MONITOR_STATS;
-+	}
-+
-+	if (!mask)
-+		mask = MINSTREL_MONITOR_TXS;
-+
-+	if (!mp->monitor)
-+		__minstrel_ht_dump_stations(mp, "add");
-+	mp->monitor = mask | MINSTREL_MONITOR_STA;
-+
-+	spin_unlock_bh(&mp->lock);
-+}
-+
-+static void
-+minstrel_ht_api_stop(struct minstrel_priv *mp)
-+{
-+	spin_lock_bh(&mp->lock);
-+	mp->monitor = 0;
-+	relay_reset(mp->relay_ev);
-+	spin_unlock_bh(&mp->lock);
-+}
-+
-+static void
-+minstrel_ht_reset_sample_table(struct minstrel_ht_sta *mi)
-+{
-+	memset(mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates, 0,
-+	       sizeof(mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates));
-+}
-+
-+static void
-+minstrel_ht_api_set_manual(struct minstrel_priv *mp, bool manual)
-+{
-+	struct minstrel_ht_sta *mi;
-+
-+	mp->manual = manual;
-+
-+	spin_lock_bh(&mp->lock);
-+	list_for_each_entry(mi, &mp->stations, list)
-+		minstrel_ht_reset_sample_table(mi);
-+	spin_unlock_bh(&mp->lock);
-+}
-+
-+static struct minstrel_ht_sta *
-+minstrel_ht_api_get_sta(struct minstrel_priv *mp, const u8 *macaddr)
-+{
-+	struct minstrel_ht_sta *mi;
-+
-+	list_for_each_entry(mi, &mp->stations, list) {
-+		if (!memcmp(mi->sta->addr, macaddr, ETH_ALEN))
-+			return mi;
-+	}
-+
-+	return NULL;
-+}
-+
-+static int
-+minstrel_ht_get_args(char **dest, int dest_size, char *str, char *sep)
-+{
-+	int i, n;
-+
-+	for (i = 0, n = 0; i < dest_size; i++) {
-+		if (!str) {
-+			dest[i] = NULL;
-+			continue;
-+		}
-+
-+		dest[i] = strsep(&str, sep);
-+		if (dest[i])
-+			n++;
-+	}
-+
-+	return n;
-+}
-+
-+static bool
-+minstrel_ht_valid_rate(struct minstrel_ht_sta *mi, u32 rate)
-+{
-+	int group, idx;
-+
-+	group = MI_RATE_GROUP(rate);
-+	if (group >= MINSTREL_GROUPS_NB)
-+		return false;
-+
-+	idx = MI_RATE_IDX(rate);
-+
-+	return !!(mi->supported[group] & BIT(idx));
-+}
-+
-+static int
-+minstrel_ht_rate_from_str(struct minstrel_ht_sta *mi, const char *str)
-+{
-+	unsigned int rate;
-+
-+	if (kstrtouint(str, 16, &rate))
-+		return -EINVAL;
-+
-+	if (!minstrel_ht_valid_rate(mi, rate))
-+		return -EINVAL;
-+
-+	return rate;
-+}
-+
-+static int
-+minstrel_ht_set_probe_rate(struct minstrel_ht_sta *mi, const char *rate_str)
-+{
-+	u16 *sample_rates;
-+	int rate, i;
-+
-+	if (!rate_str)
-+		return -EINVAL;
-+
-+	rate = minstrel_ht_rate_from_str(mi, rate_str);
-+	if (rate < 0)
-+		return rate;
-+
-+	sample_rates = mi->sample[MINSTREL_SAMPLE_TYPE_INC].sample_rates;
-+	for (i = 0; i < MINSTREL_SAMPLE_RATES; i++) {
-+		if (sample_rates[i])
-+			continue;
-+
-+		sample_rates[i] = rate;
-+		mi->sample_time = jiffies;
-+		return 0;
-+	}
-+
-+	return -ENOSPC;
-+}
-+
-+static int
-+minstrel_ht_set_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
-+		      char *rate_str, char *count_str)
-+{
-+	struct ieee80211_sta_rates *ratetbl;
-+	unsigned int count;
-+	char *countlist[4];
-+	char *ratelist[4];
-+	int rate;
-+	int n_rates;
-+	int n_count;
-+	int err = -EINVAL;
-+	int i;
-+
-+	if (!rate_str || !count_str)
-+		return -EINVAL;
-+
-+	ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC);
-+	if (!ratetbl)
-+		return -ENOMEM;
-+
-+	n_rates = minstrel_ht_get_args(ratelist, ARRAY_SIZE(ratelist),
-+				       rate_str, ",");
-+	n_count = minstrel_ht_get_args(countlist, ARRAY_SIZE(countlist),
-+				       count_str, ",");
-+	for (i = 0; i < min(n_rates, n_count); i++) {
-+		rate = minstrel_ht_rate_from_str(mi, ratelist[i]);
-+		if (rate < 0)
-+			goto error;
-+
-+		if (kstrtouint(countlist[0], 16, &count))
-+			goto error;
-+
-+		minstrel_ht_set_rate(mp, mi, ratetbl, i, rate);
-+		ratetbl->rate[i].count = count;
-+		ratetbl->rate[i].count_rts = count;
-+		ratetbl->rate[i].count_cts = count;
-+	}
-+
-+	rate_control_set_rates(mp->hw, mi->sta, ratetbl);
-+
-+	return 0;
-+
-+error:
-+	kfree(ratetbl);
-+	return err;
-+}
-+
-+static int
-+minstrel_ht_api_sta_cmd(struct minstrel_priv *mp, enum sta_cmd cmd,
-+			char *arg_str)
-+{
-+	struct minstrel_ht_sta *mi;
-+	uint8_t macaddr[ETH_ALEN];
-+	char *args[3];
-+	int n_args;
-+	int ret = -EINVAL;
-+
-+	spin_lock_bh(&mp->lock);
-+	if (!mp->manual)
-+		goto out;
-+
-+	n_args = minstrel_ht_get_args(args, ARRAY_SIZE(args), arg_str, ";");
-+	if (!args[0])
-+		goto out;
-+
-+	if (!mac_pton(args[0], macaddr))
-+		goto out;
-+
-+	mi = minstrel_ht_api_get_sta(mp, macaddr);
-+	if (!mi) {
-+		ret = -ENOENT;
-+		goto out;
-+	}
-+
-+	switch (cmd) {
-+	case STA_CMD_PROBE:
-+		ret = minstrel_ht_set_probe_rate(mi, args[1]);
-+		break;
-+	case STA_CMD_RATES:
-+		ret = minstrel_ht_set_rates(mp, mi, args[1], args[2]);
-+		break;
-+	}
-+
-+out:
-+	spin_unlock_bh(&mp->lock);
-+
-+	return ret;
-+}
-+
-+static ssize_t
-+minstrel_ht_control_write(struct file *file, const char __user *userbuf,
-+			  size_t count, loff_t *ppos)
-+{
-+	struct minstrel_priv *mp = file->private_data;
-+	char *pos, *cur;
-+	char buf[64];
-+	size_t len = count;
-+	int err;
-+
-+	if (len > sizeof(buf) - 1)
-+		return -EINVAL;
-+
-+	if (copy_from_user(buf, userbuf, len))
-+		return -EFAULT;
-+
-+	if (count > 0 && buf[len - 1] == '\n')
-+		len--;
-+
-+	buf[len] = 0;
-+	if (!len)
-+		return count;
-+
-+	pos = buf;
-+	cur = strsep(&pos, ";");
-+
-+	err = 0;
-+	if (!strcmp(cur, "dump"))
-+		minstrel_ht_dump_stations(mp);
-+	else if (!strcmp(cur, "start"))
-+		minstrel_ht_api_start(mp, pos);
-+	else if (!strcmp(cur, "stop"))
-+		minstrel_ht_api_stop(mp);
-+	else if (!strcmp(cur, "manual"))
-+		minstrel_ht_api_set_manual(mp, true);
-+	else if (!strcmp(cur, "auto"))
-+		minstrel_ht_api_set_manual(mp, false);
-+	else if (!strcmp(cur, "rates"))
-+		err = minstrel_ht_api_sta_cmd(mp, STA_CMD_RATES, pos);
-+	else if (!strcmp(cur, "probe"))
-+		err = minstrel_ht_api_sta_cmd(mp, STA_CMD_PROBE, pos);
-+	else
-+		err = -EINVAL;
-+
-+	if (err)
-+		return err;
-+
-+	return count;
-+}
-+
-+static const struct file_operations fops_control = {
-+	.open = simple_open,
-+	.llseek = generic_file_llseek,
-+	.write = minstrel_ht_control_write,
-+};
-+
-+void minstrel_ht_sta_update(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
-+{
-+	bool add = list_empty(&mi->list);
-+
-+	spin_lock_bh(&mp->lock);
-+	if (add)
-+		list_add(&mi->list, &mp->stations);
-+	if (mp->monitor)
-+		minstrel_ht_dump_sta(mp, mi, add ? "add" : "update");
-+	spin_unlock_bh(&mp->lock);
-+}
-+
-+void minstrel_ht_sta_remove(struct minstrel_priv *mp, struct minstrel_ht_sta *mi)
-+{
-+	char info[64];
-+	int ofs = 0;
-+
-+	spin_lock_bh(&mp->lock);
-+	list_del_init(&mi->list);
-+
-+	if (!mp->monitor)
-+		goto out;
-+
-+	ofs = scnprintf(info, sizeof(info), "%llx;sta;remove;%pM;;;\n",
-+			(unsigned long long)ktime_get_boottime_ns(),
-+			mi->sta->addr);
-+	relay_write(mp->relay_ev, info, ofs);
-+	relay_flush(mp->relay_ev);
-+
-+out:
-+	spin_unlock_bh(&mp->lock);
-+}
-+
-+void __minstrel_ht_report_tx_status(struct minstrel_priv *mp,
-+				    struct minstrel_ht_sta *mi,
-+				    struct ieee80211_tx_info *info,
-+				    u16 *rate_list,
-+				    int n_rates)
-+{
-+	char txs[64 + IEEE80211_TX_MAX_RATES * 8];
-+	int ofs = 0;
-+	int i;
-+
-+	if (!n_rates)
-+		return;
-+
-+	ofs += scnprintf(txs, sizeof(txs), "%llx;txs;%pM;%x;%x;%x;",
-+			 (unsigned long long)ktime_get_boottime_ns(),
-+			 mi->sta->addr,
-+			 info->status.ampdu_len,
-+			 info->status.ampdu_ack_len,
-+			 !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE));
-+
-+	ofs += scnprintf(txs + ofs, sizeof(txs) - ofs, "%x",
-+			 rate_list[0]);
-+	for (i = 1; i < n_rates; i++)
-+		ofs += scnprintf(txs + ofs, sizeof(txs) - ofs, ",%x",
-+				 rate_list[i]);
-+
-+	ofs += scnprintf(txs + ofs, sizeof(txs) - ofs, ";%x",
-+			 info->status.rates[0].count);
-+	for (i = 1; i < n_rates; i++)
-+		ofs += scnprintf(txs + ofs, sizeof(txs) - ofs, ",%x",
-+				 info->status.rates[i].count);
-+	ofs += scnprintf(txs + ofs, sizeof(txs) - ofs, "\n");
-+	relay_write(mp->relay_ev, txs, ofs);
-+	relay_flush(mp->relay_ev);
-+}
-+
-+void __minstrel_ht_report_rate_update(struct minstrel_priv *mp,
-+				      struct minstrel_ht_sta *mi, u16 rate,
-+				      struct minstrel_rate_stats *mrs)
-+{
-+	char stat[100];
-+	int ofs;
-+	int tp;
-+
-+	tp = minstrel_ht_get_tp_avg(mi, MI_RATE_GROUP(rate), MI_RATE_IDX(rate),
-+				    mrs->prob_avg);
-+
-+	ofs = scnprintf(stat, sizeof(stat),
-+			"%llx;stats;%pM;%x;%x;%x;%x;%x;%x;%x\n",
-+			(unsigned long long)ktime_get_boottime_ns(),
-+			mi->sta->addr, rate,
-+			MINSTREL_TRUNC(mrs->prob_avg * 1000), tp,
-+			mrs->last_success,
-+			mrs->last_attempts,
-+			mrs->succ_hist, mrs->att_hist);
-+
-+	relay_write(mp->relay_ev, stat, ofs);
-+	relay_flush(mp->relay_ev);
-+}
-+
-+void minstrel_ht_add_debugfs_api(struct ieee80211_hw *hw, void *priv,
-+				 struct dentry *dir)
-+{
-+	struct minstrel_priv *mp = priv;
-+
-+	spin_lock_init(&mp->lock);
-+	INIT_LIST_HEAD(&mp->stations);
-+	mp->relay_ev = relay_open("api_event", dir, 256, 512, &relay_ev_cb,
-+				  NULL);
-+	debugfs_create_devm_seqfile(&hw->wiphy->dev, "api_info",
-+				    dir, minstrel_ht_read_api_info);
-+	debugfs_create_file("api_control", 0200, dir, mp, &fops_control);
-+}
-+
-+void minstrel_ht_remove_debugfs_api(void *priv)
-+{
-+	struct minstrel_priv *mp = priv;
-+
-+	if (mp->relay_ev)
-+		relay_close(mp->relay_ev);
-+}



More information about the lede-commits mailing list