Re: [PATCH 3/3] mac80211: Implement functionality to monitor station's signal stregnth

2018-11-11 Thread Tamizh chelvam

On 2018-11-09 17:25, Johannes Berg wrote:

Oh, umm, that patch is still here ...

I guess we can combine 2 and 3 too.



Sure.


+   if (sta->rssi_low && bss_conf->enable_beacon) {
+   int last_event =
+   sta->last_rssi_event_value;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+   int low = sta->rssi_low;
+   int high = sta->rssi_high;


This doesn't really support a list, like in patch 2 where you store
sta_info::rssi_tholds?

rssi_low and rssi_high will have a configured value or zero know ? 
Configured value has been stored in the previous patch.



+   if (sig < low &&
+   (last_event == 0 || last_event >= low)) {
+   sta->last_rssi_event_value = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   rssi_cross = true;
+   } else if (sig > high &&
+  (last_event == 0 || last_event <= high)) {
+   sta->last_rssi_event_value = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   rssi_cross = true;
+   }
+   }
+
+   if (rssi_cross) {
+   ieee80211_update_rssi_config(sta);
+   rssi_cross = false;
+   }
+}


Ah, but it does, just hard to understand.

However, this does mean what I suspected on the other patch is true -
you're calling ieee80211_update_rssi_config() here, and that uses the
sta->rssi_tholds array without any protection, while a concurrent 
change

of configuration can free the data.


yes, I'll add a protection mechanism.


You need to sort that out. I would suggest to stick all the sta->rssi_*
fields you add into a new struct (you even had an empty one), and
protect that struct using RCU. That also saves the memory in case it's
not assigned at all. Something like

struct sta_mon_rssi_config {
struct rcu_head rcu_head;
int n_thresholds;
s32 low, high;
u32 hyst;
s32 last_value;
s32 thresholds[];
};

then you can kfree_rcu() it, and just do a single allocation using
struct_size() for however many entries you need.


Yes correct. I'll change it.

+ * @count_rx_signal: Number of data frames used in averaging station 
signal.
+ *	This can be used to avoid generating less reliable station rssi 
cross

+ * events that would be based only on couple of received frames.
  */
 struct sta_info {
/* General information, mostly static */
@@ -600,6 +603,7 @@ struct sta_info {
s32 rssi_high;
u32 rssi_hyst;
s32 last_rssi_event_value;
+   unsigned int count_rx_signal;


I guess that would also move into the new struct.


Okay.

Thanks,
Tamizh.


Re: [PATCH 2/3] mac80211: Implement API to configure station specific rssi threshold

2018-11-11 Thread Tamizh chelvam

On 2018-11-09 17:19, Johannes Berg wrote:

On Mon, 2018-10-15 at 23:27 +0530, Tamizh chelvam wrote:


+   sta_mon_rssi_config_free(sta);
+   sta->rssi_hyst = rssi_hyst;
+   if (fixed_thold) {
+   if (n_rssi_tholds > 2) {
+   ret = -EINVAL;
+   goto out;
+   }


This might be slightly wrong, you free and then can still return an
error.


Sure. I'll move the free part after the validation check.


+   if (n_rssi_tholds == 1) {
+   sta->rssi_low = rssi_tholds[0];
+   sta->rssi_high = rssi_tholds[0];
+   } else {
+   sta->rssi_low = rssi_tholds[0];
+   sta->rssi_high = rssi_tholds[1];
+   }
+   } else {
+   const s32 *rssi_tholds;
+
+   rssi_tholds = kmemdup(rssi_tholds,
+ n_rssi_tholds * sizeof(s32),
+ GFP_KERNEL);
+   if (!rssi_tholds) {
+   ret = -ENOMEM;
+   goto out;
+   }


Similarly here, I guess you should do the allocation (and other error
checking) before freeing.


ditto, Sure. I'll move the free part after the validation check.


+   sta->rssi_tholds = rssi_tholds;
+   sta->n_rssi_tholds = n_rssi_tholds;
+   ieee80211_update_rssi_config(sta);





+struct sta_mon_rssi_config {
+};


Huh?

oops:( I have kept all configuring parameters in sta_info itself, 
mistakenly didn't remove this struct:(


The commit log also makes it sounds like mac80211 actually *supports*
this, but clearly that's not the case. However you don't give any data
to the driver either, did you lose a patch along the way? Previously 
you

had patch 5 ("mac80211: Implement functionality to monitor station's
rssi cross event") and if I remember correctly I said you should squash
some, but now that's not here?



Thanks,
Tamizh.


Re: [PATCH 1/3] cfg80211: Add support to configure station specific RSSI threshold for AP mode

2018-11-11 Thread Tamizh chelvam




+   int (*set_sta_mon_rssi_config)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *addr,
+ const s32 *rssi_tholds,
+ u32 rssi_hyst, int rssi_n_tholds,
+ bool fixed_thold);
 };


I think it might be better to pass all the last 4 arguments (rssi
related ones) as a struct? That's a pattern we typically have elsewhere
too, and it makes things easier to extend and also easier to pass
around.


Sure.

+ * @NL80211_CMD_SET_STA_MON: This command is used to configure 
station's

+ * connection monitoring notification trigger levels.
+ * @NL80211_CMD_NOTIFY_STA_MON: This is used as an event to notify
+ * the user space that a trigger level was reached for a station.


Please describe the attributes to use with this.


I'll add that in the next version of patchset



+ * @NL80211_ATTR_STA_MON_FIXED_THOLD: Flag attribute is used with
+ * %NL80211_CMD_SET_STA_MON to indicate driver that the monitoring
+ * configuration is fixed limit or a moving range threshold.


This isn't really clear to me, what does it mean?

Sorry for not clear. This flag introduced to mention the driver that if 
this flag set then don't change the rssi_low and rssi_high limit upon
the station's rssi crossing the configured limit. Keep the rssi_low and 
rssi_high as a fixed limit.



+   if (!sta_mon || !(info->attrs[NL80211_ATTR_MAC]))


Don't really need the parentheses in !(info->...)


Yes, I'll remove it.


+   err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, sta_mon,
+  nl80211_attr_cqm_policy, info->extack);


I *think* I made that a proper nested policy, check and then you can
remove passing it here.


Sure. I'll modify it in the next patchset version.


+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+enum nl80211_cqm_rssi_threshold_event rssi_event,
+s32 rssi_level, gfp_t gfp)
+{
+   struct sk_buff *msg;
+
+   if (WARN_ON(!peer))
+   return;


Tracing for this might be nice too?


Sure.

Thanks,
Tamizh.


RE: [EXTERNAL] Re: [PATCH 1/3] cfg80211: Add support to configure station specific RSSI threshold for AP mode

2018-10-16 Thread Tamizh Chelvam Raja
>> +static int nl80211_set_sta_mon(struct sk_buff *skb, struct genl_info 
>> +*info) {
>> +   struct cfg80211_registered_device *rdev = info->user_ptr[0];
>> +   struct net_device *dev = info->user_ptr[1];
>> +   struct nlattr *attrs[NL80211_ATTR_CQM_MAX + 1];
>> +   bool fixed_thold = false;
>> +   struct nlattr *sta_mon;
>> +   u8 *addr = NULL;
>> +   int err;
>> +
>> +   if (!wiphy_ext_feature_isset(>wiphy,
>> +
>> NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
>> +   return -EOPNOTSUPP;
>> +
>> +   sta_mon = info->attrs[NL80211_ATTR_CQM];
>> +   if (!sta_mon || !(info->attrs[NL80211_ATTR_MAC]))
>> +   return -EINVAL;
>> +
>> +   err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, sta_mon,
>> +  nl80211_attr_cqm_policy, info->extack);
>> +   if (err)
>> +   return err;
>> +
>> +   addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
>> +   fixed_thold =
>> +   
>> + nla_get_flag(info->attrs[NL80211_ATTR_STA_MON_FIXED_THOLD]);
>> +
>> +   if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
>> +   attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
>> +   const s32 *thresholds =
>> +   nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
>> +   int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
>> +   u32 hysteresis = 
>> + nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
>> +
>> +   if (len % 4)
>> +   return -EINVAL;
>> +
>> +   err = nl80211_validate_rssi_tholds(thresholds, len / 4);
>> +   if (err)
>> +   return err;
>> +
>> +   return rdev_set_sta_mon_rssi_config(rdev, dev, addr, 
>> thresholds,
>> +   hysteresis, len / 4,
>> +   fixed_thold);
>> +   }
>> +
>> +   return -EINVAL;
>> +}

>IIUC there is a noticeable overlap between this new command and existing 
>nl80211_set_cqm_rssi command. Is there any reason why >nl80211_set_cqm_rss can 
>not be adapted for AP case ?

[Tamizh] This new command for AP mode introduced as per the previous 
discussion. 

>If there is a reason to handle AP case separately, then it looks like it makes 
>sense to add explicit check for supported iftype in this new command. 
>>Besides, it looks like there is no generic way to handle disabling of RSSI 
>monitoring in the new command.
>As a result, we may end up in multiple driver specific implementations.

[Tamizh] thanks for pointing me out. I'll add the ifmode check in the next 
patchset version.

Thanks,
Tamizh.


[PATCH 2/3] mac80211: Implement API to configure station specific rssi threshold

2018-10-15 Thread Tamizh chelvam
Implement set_sta_mon_rssi_config API to configure station
specific rssi threshold value to monitor change in connected
station's signal strength.

Signed-off-by: Tamizh chelvam 
---
 net/mac80211/cfg.c  |   91 +++
 net/mac80211/sta_info.c |1 +
 net/mac80211/sta_info.h |   19 ++
 3 files changed, 111 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5162233..72d2b07 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3849,6 +3849,96 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
return drv_get_ftm_responder_stats(local, sdata, ftm_stats);
 }
 
+void sta_mon_rssi_config_free(struct sta_info *sta)
+{
+   kfree(sta->rssi_tholds);
+   sta->rssi_tholds = NULL;
+   sta->n_rssi_tholds = 0;
+}
+
+static void ieee80211_update_rssi_config(struct sta_info *sta)
+{
+   s32 last;
+   u32 hyst;
+   int i, n;
+
+   if (!sta->n_rssi_tholds)
+   return;
+
+   if (!sta->last_rssi_event_value)
+   sta->last_rssi_event_value =
+   -ewma_signal_read(>rx_stats_avg.signal);
+
+   last = sta->last_rssi_event_value;
+   hyst = sta->rssi_hyst;
+   n = sta->n_rssi_tholds;
+
+   for (i = 0; i < n; i++)
+   if (last < sta->rssi_tholds[i])
+   break;
+
+   sta->rssi_low = i > 0 ? (sta->rssi_tholds[i - 1] - hyst) : S32_MIN;
+   sta->rssi_high = i < n ? (sta->rssi_tholds[i] + hyst - 1) : S32_MAX;
+}
+
+static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *mac_addr,
+const s32 *rssi_tholds,
+u32 rssi_hyst, int n_rssi_tholds,
+bool fixed_thold)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct ieee80211_local *local = sdata->local;
+   struct sta_info *sta;
+   int ret = 0;
+
+   mutex_lock(>sta_mtx);
+
+   if (mac_addr) {
+   sta = sta_info_get_bss(sdata, mac_addr);
+   if (!sta) {
+   ret = -ENOENT;
+   goto out;
+   }
+
+   sta_mon_rssi_config_free(sta);
+   sta->rssi_hyst = rssi_hyst;
+   if (fixed_thold) {
+   if (n_rssi_tholds > 2) {
+   ret = -EINVAL;
+   goto out;
+   }
+
+   if (n_rssi_tholds == 1) {
+   sta->rssi_low = rssi_tholds[0];
+   sta->rssi_high = rssi_tholds[0];
+   } else {
+   sta->rssi_low = rssi_tholds[0];
+   sta->rssi_high = rssi_tholds[1];
+   }
+   } else {
+   const s32 *rssi_tholds;
+
+   rssi_tholds = kmemdup(rssi_tholds,
+ n_rssi_tholds * sizeof(s32),
+ GFP_KERNEL);
+   if (!rssi_tholds) {
+   ret = -ENOMEM;
+   goto out;
+   }
+
+   sta->rssi_tholds = rssi_tholds;
+   sta->n_rssi_tholds = n_rssi_tholds;
+   ieee80211_update_rssi_config(sta);
+   }
+   }
+
+out:
+   mutex_unlock(>sta_mtx);
+   return ret;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3944,4 +4034,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
.tx_control_port = ieee80211_tx_control_port,
.get_txq_stats = ieee80211_get_txq_stats,
.get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
+   .set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
 };
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index fb8c225..28e9a6b 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1020,6 +1020,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
 
rate_control_remove_sta_debugfs(sta);
ieee80211_sta_debugfs_remove(sta);
+   sta_mon_rssi_config_free(sta);
 
cleanup_single_sta(sta);
 }
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 9a04327..acbad98 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -411,6 +411,9 @@ struct ieee80211_sta_rx_stats {
u64 msdu[IEEE80211_NUM_TIDS + 1];
 };
 
+struct sta_mon_rssi_config {
+};
+
 /*
  * The band

[PATCH 3/3] mac80211: Implement functionality to monitor station's signal stregnth

2018-10-15 Thread Tamizh chelvam
Triggers cfg80211_sta_mon_rssi_notify with the corresponding event when
station signal goes out of configured threshold. It uses rx data signal
to check against rssi threshold configured by the user. And update
the lower and upper RSSI threshold for the station if it is not
configured as a fixed threshold.
This event will be useful for the application like steering to take
decision on any station depends on its current link quality.

Signed-off-by: Tamizh chelvam 
---
 include/net/mac80211.h  |7 +++
 net/mac80211/cfg.c  |2 +-
 net/mac80211/rx.c   |   51 ++-
 net/mac80211/sta_info.h |5 +
 4 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 71985e9..355e522 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -849,6 +849,13 @@ enum mac80211_rate_control_flags {
 };
 
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
 
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 72d2b07..be386ff 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3856,7 +3856,7 @@ void sta_mon_rssi_config_free(struct sta_info *sta)
sta->n_rssi_tholds = 0;
 }
 
-static void ieee80211_update_rssi_config(struct sta_info *sta)
+void ieee80211_update_rssi_config(struct sta_info *sta)
 {
s32 last;
u32 hyst;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3bd3b57..1afef40 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1681,6 +1681,52 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf = >sdata->vif.bss_conf;
+   bool rssi_cross =  false;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (sta->rssi_low && bss_conf->enable_beacon) {
+   int last_event =
+   sta->last_rssi_event_value;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+   int low = sta->rssi_low;
+   int high = sta->rssi_high;
+
+   if (sig < low &&
+   (last_event == 0 || last_event >= low)) {
+   sta->last_rssi_event_value = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   rssi_cross = true;
+   } else if (sig > high &&
+  (last_event == 0 || last_event <= high)) {
+   sta->last_rssi_event_value = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   rssi_cross = true;
+   }
+   }
+
+   if (rssi_cross) {
+   ieee80211_update_rssi_config(sta);
+   rssi_cross = false;
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1736,6 +1782,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -4177,9 +4224,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
/* statistics part of ieee80211_rx_h_sta_process() */
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
-   if (!fast_rx->uses_rss)
+   if (!fast_rx->uses_rss) {
ewma_signal_add(>rx_stats_avg.signal,
-status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
+   }
}
 
if (status->chains) {
diff --git a/net/mac8021

[PATCH 1/3] cfg80211: Add support to configure station specific RSSI threshold for AP mode

2018-10-15 Thread Tamizh chelvam
Add infrastructure to configure station specific RSSI threshold
configuration to monitor station's signal strength variation.
This configuration will be useful for the application like
steering which requires change in the station's current signal
strength.

New NL80211_CMD_SET_STA_MON introduced to configure the RSSI threshold
using NL80211_ATTR_CQM nested attributes. The MAC address of
a station is passed in NL80211_ATTR_MAC. And NL80211_ATTR_STA_MON_FIXED_THOLD
introduced to have this RSSI threshold as a fixed limit or moving range 
thresholds.
Depends on the application's use case user can have either fixed or
moving RSSI range thresholds.

cfg80211_sta_mon_rssi_notify introduced to notify change in the
station's signal stregnth cross event using NL80211_CMD_NOTIFY_STA_MON.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG feature flag.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |   28 +
 include/uapi/linux/nl80211.h |   18 ++
 net/wireless/nl80211.c   |  131 +-
 net/wireless/rdev-ops.h  |   18 ++
 4 files changed, 181 insertions(+), 14 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1fa41b7..8f6a906 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3183,6 +3183,12 @@ struct cfg80211_ftm_responder_stats {
  *
  * @get_ftm_responder_stats: Retrieve FTM responder statistics, if available.
  * Statistics should be cumulative, currently no way to reset is provided.
+ *
+ * @set_sta_mon_rssi_config: Configure  RSSI threshold for a station.
+ * After configuration, the driver should (soon) send an event indicating
+ * the current level of a station is above/below the configured threshold;
+ * this may need some care when the configuration is changed
+ * (without first being disabled.)
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3492,6 +3498,12 @@ struct cfg80211_ops {
int (*get_ftm_responder_stats)(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_ftm_responder_stats *ftm_stats);
+   int (*set_sta_mon_rssi_config)(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *addr,
+ const s32 *rssi_tholds,
+ u32 rssi_hyst, int rssi_n_tholds,
+ bool fixed_thold);
 };
 
 /*
@@ -6024,6 +6036,22 @@ bool cfg80211_rx_control_port(struct net_device *dev,
  struct sk_buff *skb, bool unencrypted);
 
 /**
+ * cfg80211_sta_mon_rssi_notify - Station's rssi out of range event
+ * @dev: network device
+ * @peer: Station's mac address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured rssi threshold reached event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+enum nl80211_cqm_rssi_threshold_event rssi_event,
+s32 rssi_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event
  * @dev: network device
  * @rssi_event: the triggered RSSI event
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 6d610ba..0f4cc09 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1036,6 +1036,11 @@
  * @NL80211_CMD_GET_FTM_RESPONDER_STATS: Retrieve FTM responder statistics, in
  * the %NL80211_ATTR_FTM_RESPONDER_STATS attribute.
  *
+ * @NL80211_CMD_SET_STA_MON: This command is used to configure station's
+ * connection monitoring notification trigger levels.
+ * @NL80211_CMD_NOTIFY_STA_MON: This is used as an event to notify
+ * the user space that a trigger level was reached for a station.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1250,6 +1255,9 @@ enum nl80211_commands {
 
NL80211_CMD_GET_FTM_RESPONDER_STATS,
 
+   NL80211_CMD_SET_STA_MON,
+   NL80211_CMD_NOTIFY_STA_MON,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -2254,6 +2262,10 @@ enum nl80211_commands {
  * @NL80211_ATTR_FTM_RESPONDER_STATS: Nested attribute with FTM responder
  * statistics, see  nl80211_ftm_responder_stats.
  *
+ * @NL80211_ATTR_STA_MON_FIXED_THOLD: Flag attribute is used with
+ * %NL80211_CMD_SET_STA_MON to indicate driver that the monitoring
+ * configuration is fixed limit or a moving range threshold.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest

[PATCH 0/3] cfg80211/mac80211: Add support to configure and monitor station's rssi threshold

2018-10-15 Thread Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring rssi threshold for the connected stations and api to notify
userspace application upon crossing the configured threshold.
This will be useful for the application which requires
station's current signal strength change information.
Monitoring station's signal strength through station dump command
will unnecessarily increase the system overhead. This event based
mechanism will reduce the system overhead and helps application to
take a decision for the station for which event received.


Tamizh chelvam (3):
  cfg80211: Add support to configure station specific RSSI threshold
for AP mode
  mac80211: Implement API to configure station specific rssi threshold
  mac80211: Implement functionality to monitor station's signal
stregnth

 include/net/cfg80211.h   |   28 +
 include/net/mac80211.h   |7 +++
 include/uapi/linux/nl80211.h |   18 ++
 net/mac80211/cfg.c   |   91 +
 net/mac80211/rx.c|   51 +++-
 net/mac80211/sta_info.c  |1 +
 net/mac80211/sta_info.h  |   24 
 net/wireless/nl80211.c   |  131 +-
 net/wireless/rdev-ops.h  |   18 ++
 9 files changed, 354 insertions(+), 15 deletions(-)

-- 
1.7.9.5



Re: [PATCH 2/7] cfg80211: Add new NL command to configure peer specific rssi threshold

2018-07-11 Thread Tamizh chelvam

On 2018-07-06 17:10, Johannes Berg wrote:

On Wed, 2018-07-04 at 11:39 +0530, Tamizh chelvam wrote:

On 2018-06-29 14:59, Johannes Berg wrote:
> On Wed, 2018-06-13 at 16:15 +0530, Tamizh chelvam wrote:
> >
> > + * @NL80211_ATTR_STA_MON: Station's connection monitor configuration
> > in a
> > + *   nested attribute with %NL80211_ATTR_STA_MON_* sub-attributes.
>
> Can't we reuse the existing attributes in this nesting?

This new attributes introduced as per the previous discussion.
https://patchwork.kernel.org/patch/10240697/
Is my understanding correct ?


Yeah ok ... I'm thinking perhaps we could share some part of it, but
it's not really worth making it more complex due to that.

Sure, i'll reuse those cqm attributes and event notification enum as 
well.



> Wait, you went to all this effort in the first patch and now you don't
> add this to the list?
>
No, the list and the rssi_config structure is for multi threshold 
value

and not for single threshold.


Yeah, though I'm still not sure why we need the single threshold thing
at all.
For taking steering kind of decision single threshold value can be used 
to monitor

the station's rssi.


List should always be a superset.

I believe superset you meant will accept a signle threshold 
configuration also from user ?

If so, we can remove the single threshold api implementation.

Thanks,
Tamizh.


Re: [PATCH 1/7] wireless: Change single cqm_config to rssi config list

2018-07-11 Thread Tamizh chelvam

On 2018-07-06 17:16, Johannes Berg wrote:

On Wed, 2018-07-04 at 23:46 +0530, Tamizh chelvam wrote:


> > - struct cfg80211_cqm_config *cqm_config;
> > + struct cfg80211_rssi_config *rssi_config;
> > + struct list_head rssi_config_list;
>
> Why do you need both now? Perhaps instead you should allow a NULL/all-
> ones MAC address for where you have the direct pointer now, and remove
> that? You anyway need to pass something to the peer argument in
>

In the current cqm/sta_mon implementation the range_config will be
updated before notify event posted to userspace.
To update the range config for a specific station we need to have this
peer addr based configuration list which holds the thresholds info
to choose the next rssi range.
Or do you want me to handle and store the rssi_config structure in
mac80211 and update it in mac80211 itself ? And simply pass the
notification event to userspace application ?


I don't have any issues with storing it in mac80211 - could attach it 
to

the station entry there?

yes.


Come to think of it, that might also clarify the lifetime rules. As it
is now, what if the station is removed? What are the lifetime rules for
a per-station configuration?
If we go with mac80211 based approach then the lifetime of the 
configuration would be for the current connection.


It would almost look like it stays here (or maybe I missed when you
remove it from the list when a station is removed), but that doesn't
seem like a good idea.

Please document the lifetime rules also in the API, and make sure you
implement them properly.
In AP mode, the lifetime would be for the station's current connection. 
It will be removed in case of roaming/disconnected.



> What's the locking scheme for this? It's way more complex now so
> perhaps stick ASSERT_RTNL() in there or so?
>

Isn't wdev_lock enough ?


I guess it should be :-) Maybe assert on that, also to document the
locking rules.

Sure



> >   /* RSSI reporting disabled? */
> > - if (!wdev->cqm_config)
> > + if (!wdev->rssi_config)
> >   return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
>
>
> So I guess the wdev->rssi_config is used for the case of "always use
> this config for any AP you're connected to" or so - but maybe it'd be
> better to track the AP as a station? Then again, I guess we can't force
> userspace to change that.


Sorry I didn't get your point:( I didn't change anything in the 
station

mode. Functionality remains same for the station mode.


Right, that sort of goes back to my thoughts about lifetime rules too.
The rule for stations would be to have it deleted when the station is
deleted, but I guess the rule for client-mode is to keep the config
active even when roaming?

I was just thinking that you don't need to *store* it like that, you
could still - in client mode - store the configuration treating the AP
as a (peer) station, perhaps with an ff:ff:ff:ff:ff:ff MAC address or
something (instead of using the BSSID, to get lifetime rules adjusted
right).

Going with mac80211 based storing configuration will remove these list 
implementation in the cfg80211.
So, there won't be any MAC address stored for client-mode in cqm_config 
structure.


But now that I'm thinking about how the lifetime rules differ ... 
that's

probably not worth it.


> >   wdev_lock(wdev);
> >   if (n_thresholds) {
> > - struct cfg80211_cqm_config *cqm_config;
> > -
> > - cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config) +
> > -  n_thresholds * sizeof(s32), GFP_KERNEL);
> > - if (!cqm_config) {
> > + wdev->rssi_config = cfg80211_get_rssi_config(
> > + wdev, thresholds,
> > + n_thresholds, hysteresis,
> > + wdev->current_bss->pub.bssid);
>
> Here you link it to the BSSID anyway, but do we always have a
> current_bss at this point?
>

Oops! I didn't think about that condition. I'll fix that in the next
version.


Again though - see above. I'm not sure it's even correct to link it to
the BSSID since until now, I think the configuration would remain 
across

roaming?

As mentioned above storing configuration parameters in mac80211 will 
avoid this list implementation here.

So, no need of worrying about those roaming scenario know ?

Thanks,
Tamizh.


Re: [PATCH 4/7] cfg80211: Add support to notify station's rssi level crossing

2018-07-10 Thread Tamizh chelvam

On 2018-07-06 17:09, Johannes Berg wrote:

On Wed, 2018-07-04 at 11:43 +0530, Tamizh chelvam wrote:


> > --- a/include/uapi/linux/nl80211.h
> > +++ b/include/uapi/linux/nl80211.h
> > @@ -1249,6 +1249,7 @@ enum nl80211_commands {
> >   NL80211_CMD_CONTROL_PORT_FRAME,
> >
> >   NL80211_CMD_SET_STA_MON,
> > + NL80211_CMD_NOTIFY_STA_MON,
>
> Missing documentation - but again, why not unify it with the existing
> event? Or can't we because that might confuse older applications?
> Perhaps anyway we should unicast these notifications? Not sure though,
> perhaps one app could set them up and the other might care?
>

This new command introduced as per the previous discussion
https://patchwork.kernel.org/patch/10168685/
https://patchwork.kernel.org/patch/10240697/

Is my understanding correct ?


I guess you're right. To my defense, this was like almost half a year
ago :)

Yeah;)



I just referred this code from cfg80211_prepare_cqm. Do you want me to
change this to struct based?


Please, I guess we can fix up cqm too later.


Sure, I'll fix it in the next version.

Thanks,
Tamizh.


Re: [PATCH 6/7] cfg80211: Accept multiple RSSI threholds for STA_MON command

2018-07-05 Thread Tamizh chelvam

On 2018-06-29 15:09, Johannes Berg wrote:

On Wed, 2018-06-13 at 16:15 +0530, Tamizh chelvam wrote:

Change the NL80211_CMD_STA_MON RSSI threshold attribut to


This seems weird - you just introduced it a few patches back, and now
you change it and even worry about compatibility and have both cfg80211
callbacks etc. Just remove set_sta_mon_rssi_config() and ask that
drivers/mac80211 implement set_sta_mon_rssi_range_config?

First I've done patch to have single threshold value for AP mode and as 
per the previous discussion extended to multiple thresholds also. Here 
the intention is to accept one or more than one RSSI thresholds to 
monitor. Any thought ?



  * @NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG: With this driver can set
  * rssi threshold using %NL80211_ATTR_STA_MON_RSSI_THOLD attribute
  * for a connected station.
+ * @NL80211_EXT_FEATURE_STA_MON_RSSI_LIST: With this driver the
+ *	%NL80211_ATTR_STA_MON_RSSI_THOLD attribute accepts a list of zero 
or
+ *	more RSSI threshold values to monitor rather than exactly one 
threshold.


And maybe not have two bits here either?

Or do you expect somebody to actually really need the single threshold
in the near future? It seems you're implementing it for mac80211 only,
which doesn't care.



Thanks,
Tamizh.


Re: [PATCH 1/7] wireless: Change single cqm_config to rssi config list

2018-07-04 Thread Tamizh chelvam

On 2018-06-29 14:56, Johannes Berg wrote:

On Wed, 2018-06-13 at 16:15 +0530, Tamizh chelvam wrote:


diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5fbfe61..3e123a3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4139,7 +4139,7 @@ static inline struct wiphy *wiphy_new(const 
struct cfg80211_ops *ops,

 struct cfg80211_conn;
 struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
-struct cfg80211_cqm_config;
+struct cfg80211_rssi_config;


I think something like rssi_mon_config would be better? Just _rssi_
could be interpreted in many ways.


Okay sure

-   struct cfg80211_cqm_config *cqm_config;
+   struct cfg80211_rssi_config *rssi_config;
+   struct list_head rssi_config_list;


Why do you need both now? Perhaps instead you should allow a NULL/all-
ones MAC address for where you have the direct pointer now, and remove
that? You anyway need to pass something to the peer argument in

In the current cqm/sta_mon implementation the range_config will be 
updated before notify event posted to userspace.
To update the range config for a specific station we need to have this 
peer addr based configuration list which holds the thresholds info

to choose the next rssi range.
Or do you want me to handle and store the rssi_config structure in 
mac80211 and update it in mac80211 itself ? And simply pass the 
notification event to userspace application ?



-void cfg80211_cqm_config_free(struct wireless_dev *wdev)
+void cfg80211_rssi_config_free(struct wireless_dev *wdev, const u8 
*peer)


even when the pointer is used.


-   kfree(wdev->cqm_config);
-   wdev->cqm_config = NULL;
+   struct cfg80211_rssi_config *rssi_config, *tmp;
+
+   if (list_empty(>rssi_config_list))
+   goto free;
+
+   list_for_each_entry_safe(rssi_config, tmp, >rssi_config_list,
+list) {
+   if (peer && memcmp(rssi_config->addr, peer, ETH_ALEN))
+   continue;
+
+   list_del(_config->list);
+   kfree(rssi_config);
+   if (list_empty(>rssi_config_list) || peer)
+   goto out;
+   }


That logic could use some comments if we even decide to keep it this
way.

NULL means "free all"?


Yes.
What's the locking scheme for this? It's way more complex now so 
perhaps

stick ASSERT_RTNL() in there or so?


Isn't wdev_lock enough ?
@@ -10140,7 +10141,7 @@ static int cfg80211_cqm_rssi_update(struct 
cfg80211_registered_device *rdev,

int err;

/* RSSI reporting disabled? */
-   if (!wdev->cqm_config)
+   if (!wdev->rssi_config)
return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);



So I guess the wdev->rssi_config is used for the case of "always use
this config for any AP you're connected to" or so - but maybe it'd be
better to track the AP as a station? Then again, I guess we can't force
userspace to change that.

Sorry I didn't get your point:( I didn't change anything in the station 
mode. Functionality remains

same for the station mode.


+static struct cfg80211_rssi_config *
+cfg80211_get_rssi_config(struct wireless_dev *wdev, const s32 
*thresholds,

+int n_thresholds, u32 hysteresis, const u8 *peer)
+{
+   struct cfg80211_rssi_config *rssi_config;
+
+   if (!peer)
+   return NULL;
+
+   if (list_empty(>rssi_config_list))
+   goto new;
+
+   list_for_each_entry(rssi_config, >rssi_config_list, list) {
+   if (!memcmp(rssi_config->addr, peer, ETH_ALEN))
+   goto found;
+   }
+
+new:
+   rssi_config = kzalloc(sizeof(struct cfg80211_rssi_config) +
+ n_thresholds * sizeof(s32), GFP_KERNEL);
+   list_add(_config->list, >rssi_config_list);


Why does "get" always imply "create"?


I'll rename the function.


wdev_lock(wdev);
if (n_thresholds) {
-   struct cfg80211_cqm_config *cqm_config;
-
-   cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config) +
-n_thresholds * sizeof(s32), GFP_KERNEL);
-   if (!cqm_config) {
+   wdev->rssi_config = cfg80211_get_rssi_config(
+   wdev, thresholds,
+   n_thresholds, hysteresis,
+   wdev->current_bss->pub.bssid);


Here you link it to the BSSID anyway, but do we always have a
current_bss at this point?

Oops! I didn't think about that condition. I'll fix that in the next 
version.


Re: [PATCH 5/7] mac80211: Implement functionality to monitor station's rssi cross event

2018-07-04 Thread Tamizh chelvam

On 2018-06-29 15:06, Johannes Berg wrote:

On Wed, 2018-06-13 at 16:15 +0530, Tamizh chelvam wrote:


+   if (sta->rssi_thold && bss_conf->enable_beacon) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int thold = sta->rssi_thold;
+   int hyst = sta->rssi_hyst;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+
+   if (sig < thold &&
+   (last_event == 0 || sig < last_event - hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > thold &&
+  (last_event == 0 || sig > last_event + hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }


This seems really familiar - perhaps if you unify the cfg80211 API for
sta_mon and "normal" CQM (distinguish based on the peer address?) you
can unify this block of code too?


Sure I'll check and update it in the next version of the patch.


Re: [PATCH 4/7] cfg80211: Add support to notify station's rssi level crossing

2018-07-04 Thread Tamizh chelvam

On 2018-06-29 15:05, Johannes Berg wrote:

On Wed, 2018-06-13 at 16:15 +0530, Tamizh chelvam wrote:

Add cfg80211_sta_mon_rssi_notify api to update user space upon
crossing the configured rssi threshold of a station.
NL80211_CMD_NOTIFY_STA_MON introduced to send this event to
userspace along with NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
NL80211_ATTR_MAC and NL80211_ATTR_STA_MON_RSSI_LEVEL info.
Userspace application can make a decision depends on this
notification.


I guess you should also combine this with patch 2, it's a bit weird to
only have one side and not be able to use it in one patch, and both
aren't all that big.

Sure




--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1249,6 +1249,7 @@ enum nl80211_commands {
NL80211_CMD_CONTROL_PORT_FRAME,

NL80211_CMD_SET_STA_MON,
+   NL80211_CMD_NOTIFY_STA_MON,


Missing documentation - but again, why not unify it with the existing
event? Or can't we because that might confuse older applications?
Perhaps anyway we should unicast these notifications? Not sure though,
perhaps one app could set them up and the other might care?


This new command introduced as per the previous discussion
https://patchwork.kernel.org/patch/10168685/
https://patchwork.kernel.org/patch/10240697/

Is my understanding correct ?

+static struct sk_buff *cfg80211_prepare_sta_mon(struct net_device 
*dev,

+   const char *mac, gfp_t gfp)
+{
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = 
wiphy_to_rdev(wdev->wiphy);

+   struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+   void **cb;
+
+   if (!msg)
+   return NULL;
+
+   cb = (void **)msg->cb;


Uh, what's that? Please use a structure.


I just referred this code from cfg80211_prepare_cqm. Do you want me to 
change this to struct based?



+   cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_STA_MON);


[...]

+
+   cb[1] = nla_nest_start(msg, NL80211_ATTR_STA_MON);
+   if (!cb[1])
+   goto nla_put_failure;
+
+   cb[2] = rdev;


Yeah, definitely use a struct instead of three magic array indices.


+
+   msg = cfg80211_prepare_sta_mon(dev, peer, gfp);
+   if (!msg)
+   return;
+
+   if (nla_put_u32(msg, NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
+   rssi_event))
+   goto nla_put_failure;
+
+   if (rssi_level && nla_put_s32(msg, NL80211_ATTR_STA_MON_RSSI_LEVEL,
+ rssi_level))
+   goto nla_put_failure;
+
+   cfg80211_send_sta_mon(msg, gfp);


In fact, perhaps better to have something like

struct nl80211_sta_mon_prep {
struct sk_buff *skb;

};

struct nl80211_sta_mon_prep prep;

if (cfg80211_prepare_sta_mon())
return;
...
cfg80211_send_sta_mon(, gfp);

or so?


Tamizh.


Re: [PATCH 2/7] cfg80211: Add new NL command to configure peer specific rssi threshold

2018-07-04 Thread Tamizh chelvam

On 2018-06-29 14:59, Johannes Berg wrote:

On Wed, 2018-06-13 at 16:15 +0530, Tamizh chelvam wrote:


+ * @NL80211_ATTR_STA_MON: Station's connection monitor configuration 
in a

+ * nested attribute with %NL80211_ATTR_STA_MON_* sub-attributes.


Can't we reuse the existing attributes in this nesting?

This new attributes introduced as per the previous discussion.
https://patchwork.kernel.org/patch/10240697/
Is my understanding correct ?



+/**
+ * enum nl80211_sta_mon_rssi_threshold_event - RSSI threshold event
+ * @NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower 
than the

+ * configured threshold
+ * @NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher 
than the

+ * configured threshold
+ */
+enum nl80211_sta_mon_rssi_threshold_event {
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+};


It seems like this should already exist also for the CQM? Can we not
reuse it?


+static int nl80211_set_sta_mon_rssi(struct genl_info *info,
+   const u8 *peer, s32 threshold,
+   u32 hysteresis)
+{
+   struct cfg80211_registered_device *rdev = info->user_ptr[0];
+   struct net_device *dev = info->user_ptr[1];
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+   if (threshold > 0)
+   return -EINVAL;
+
+   if (threshold == 0)
+   hysteresis = 0;
+
+   if (!rdev->ops->set_sta_mon_rssi_config)
+   return -EOPNOTSUPP;
+
+   if ((wdev->iftype != NL80211_IFTYPE_AP &&
+wdev->iftype != NL80211_IFTYPE_P2P_GO &&
+wdev->iftype != NL80211_IFTYPE_AP_VLAN) ||
+   !wiphy_ext_feature_isset(>wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
+   return -EOPNOTSUPP;
+
+   return rdev_set_sta_mon_rssi_config(rdev, dev, peer,
+   threshold, hysteresis);
+}


Wait, you went to all this effort in the first patch and now you don't
add this to the list?

No, the list and the rssi_config structure is for multi threshold value 
and not for single threshold.


Thanks,
Tamizh.


Re: [PATCH 0/4] cfg80211/mac80211: Add support to configure and monitor txrate threshold

2018-06-19 Thread Tamizh chelvam

On 2018-06-15 17:16, Janusz Dziedzic wrote:
2018-06-14 9:50 GMT+02:00 Arend van Spriel 
:

On 6/13/2018 5:10 PM, Toke Høiland-Jørgensen wrote:


Tamizh Chelvam Raja  writes:


This patchsets introduced new NL command and api to support
configuring txrate threshold for the connected stations and api to
notify userspace application upon crossing the configured txrate
threshold.
This will be useful for the application which requires station's
current capability change information.



What is the intended use case? Asking mostly out of curiosity :)



[Tamizh] This is to monitor txrate change for a station. By 
notifying

userspace when the txrate for a station goes out of configured
threshold, It can take steering decisions on the particular station.



Do we really need kernel notification for that?
You can simple monitor all this information same way iw station dump 
show.


In this case user space application need to fetch the station statistics 
periodically and parse those detail.
Let say AP has more number of stations(like more than 50) in all 
bands(2G and 5G), then the system overhead will be more for fetching the 
detail periodically.
But with this kernel notification we can avoid those overhead and more 
or less this is similar to the CQM(rssi, txe,..) notification in STA 
mode.


Thanks,
Tamizh.


As a metric use tx/rx bitrate, signal or even expected throughput.

Maybe small patch that will average tx/rx bitrate for few seconds
(additional fields in station dump) could be helpful here.

BR
Janusz



Yeah, I got that part. I was curious as to what (userspace) 
application

you were planning to use this for? I.e., what kind of steering
decisions? :)



It sounds like network initiated handover as opposed to station 
roaming.

Suspect the user-space application referred to here is a proprietary
application. At plumbers conf I attended a couple of years ago there 
was an
idea to have a network management application controlling multiple 
hostapd
instances for this type of functionality, but not sure if that project 
ever

got of the ground.

Regards,
Arend



RE: [PATCH 0/4] cfg80211/mac80211: Add support to configure and monitor txrate threshold

2018-06-13 Thread Tamizh Chelvam Raja
> This patchsets introduced new NL command and api to support 
> configuring txrate threshold for the connected stations and api to 
> notify userspace application upon crossing the configured txrate threshold.
> This will be useful for the application which requires station's 
> current capability change information.

What is the intended use case? Asking mostly out of curiosity :)
[Tamizh] This is to monitor txrate change for a station. By notifying userspace 
when the txrate for a station goes out of configured threshold, It can take 
steering decisions on the particular station.

-Toke


[PATCH 2/4] mac80211: Add api to configure low and high txrate threshold

2018-06-13 Thread Tamizh chelvam
Add set_sta_mon_txrate_config api to configure low and high
txrate threshold for a connected station. The configuration
will be represented in 100kbps.

Signed-off-by: Tamizh chelvam 
---
 net/mac80211/cfg.c  |   35 +++
 net/mac80211/sta_info.h |7 +++
 2 files changed, 42 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5cdd8a3..649f5c7 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3876,6 +3876,40 @@ static int ieee80211_set_sta_mon_rssi_range_cfg(struct 
wiphy *wiphy,
return 0;
 }
 
+static int ieee80211_set_sta_mon_txrate_config(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *peer,
+  u32 low_txrate_thold,
+  u32 high_txrate_thold)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->txrate_low == low_txrate_thold &&
+   sta->txrate_high == high_txrate_thold)
+   goto unlock;
+
+   sta->txrate_low = low_txrate_thold;
+   sta->txrate_high = high_txrate_thold;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3972,4 +4006,5 @@ static int ieee80211_set_sta_mon_rssi_range_cfg(struct 
wiphy *wiphy,
.get_txq_stats = ieee80211_get_txq_stats,
.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
.set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_cfg,
+   .set_sta_mon_txrate_config = ieee80211_set_sta_mon_txrate_config,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 05d68f8..a71f50c 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -497,6 +497,10 @@ struct ieee80211_sta_rx_stats {
  * @count_rx_signal: Number of data frames used in averaging station signal.
  * This can be used to avoid generating less reliable station rssi cross
  * events that would be based only on couple of received frames
+ * @txrate_low: TXRATE lower threshold for a station to monitor, this will be
+ * in 100Kbps
+ * @txrate_high: TXRATE upper threshold for a station to monitor, this will be
+ * in 100Kbps
  */
 struct sta_info {
/* General information, mostly static */
@@ -605,6 +609,9 @@ struct sta_info {
int last_sta_mon_event_signal;
unsigned int count_rx_signal;
 
+   u32 txrate_low;
+   u32 txrate_high;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.7.9.5



[PATCH 1/4] cfg80211: Add support to configure station specific txrate threshold

2018-06-13 Thread Tamizh chelvam
Add support to configure station specific txrate threshold
to monitor variation in the txrate for a station. Configuration
is passed using NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD and
NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD in NL80211_CMD_SET_STA_MON
command and the configuration will be represented in 100kbps.
This will be useful for the application like steering which requires
station's current capability.

Driver supporting this configuration feature should advertise
NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |9 +
 include/uapi/linux/nl80211.h |   34 ++
 net/wireless/nl80211.c   |   40 
 net/wireless/rdev-ops.h  |   17 +
 net/wireless/trace.h |   25 +
 5 files changed, 125 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4c49cc5..5bf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3035,6 +3035,10 @@ struct cfg80211_external_auth_params {
  * The driver should advertise %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if
  * this method is implemented. If it is provided then there's no point
  * providing @set_sta_mon_rssi_config
+ * @set_sta_mon_txrate_config: Configure low and high TXRATE threshold in 
100kbs
+ * for a connected station. The driver should(soon) send an event
+ * indicating the current attempted frame txrate level is above/below the
+ * configured threshold
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3348,6 +3352,11 @@ struct cfg80211_ops {
 struct net_device *dev,
 const u8 *addr,
 s32 rssi_low, s32 rssi_high);
+   int (*set_sta_mon_txrate_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+u32 low_txrate_thold,
+u32 high_txrate_thold);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8e2a84b..c7ce475 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4301,6 +4301,15 @@ enum nl80211_ps_state {
  * @NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT: RSSI threshold event
  * @NL80211_ATTR_STA_MON_RSSI_LEVEL: the RSSI value in dBm that triggered the
  * RSSI threshold event.
+ * @NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the low txrate threshold. Event will be sent
+ * if the txrate for a station goes lesser than this threshold.
+ * @NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the upper txrate threshold. Event will be sent
+ * if the txrate for a station goes greater than this threshold.
+ * @NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT: TX_RATE threshold cross event
+ * @NL80211_ATTR_STA_MON_TXRATE_LEVEL: TXRATE for a station in 100kbps that
+ * triggered the TX_RATE threshold cross event.
  */
 enum nl80211_attr_sta_mon {
__NL80211_ATTR_STA_MON_INVALID,
@@ -4308,6 +4317,10 @@ enum nl80211_attr_sta_mon {
NL80211_ATTR_STA_MON_RSSI_HYST,
NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
NL80211_ATTR_STA_MON_RSSI_LEVEL,
+   NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT,
+   NL80211_ATTR_STA_MON_TXRATE_LEVEL,
 
/* keep last */
__NL80211_ATTR_STA_MON_AFTER_LAST,
@@ -4327,6 +4340,21 @@ enum nl80211_sta_mon_rssi_threshold_event {
 };
 
 /**
+ * enum nl80211_sta_mon_txrate_threshold_event - TX_RATE threshold event
+ * @NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE: The TX_RATE level is in between
+ * low and high threshold
+ * @NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW: The TX_RATE level is lower than
+ * the configured threshold
+ * @NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH: The TX_RATE is higher than the
+ * configured threshold
+ */
+enum nl80211_sta_mon_txrate_threshold_event {
+   NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE,
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW,
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH,
+};
+
+/**
  * enum nl80211_attr_cqm - connection quality monitor attributes
  * @__NL80211_ATTR_CQM_INVALID: invalid
  * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies
@@ -5191,6 +5219,11 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_STA_MON_RSSI_LIST: With this driver the
  * %NL80211_ATTR_STA_MON_RSSI_THOLD attribute accepts a list of zero or
  * more RSSI threshold values to monitor rather

[PATCH 3/4] cfg80211: Add support to notify station's txrate crossing event

2018-06-13 Thread Tamizh chelvam
Add cfg80211_sta_mon_txrate_notify to update userspace upon
crossing the configured txrate threshold for a station.
This uses NL80211_CMD_NOTIFY_STA_MON along with
NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT, NL80211_ATTR_MAC
and NL80211_ATTR_STA_MON_TXRATE_LEVEL. Userspace application can
make a decision on the station depends on this notification.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h |   17 +
 net/wireless/nl80211.c |   38 ++
 net/wireless/trace.h   |   25 +
 3 files changed, 80 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5bf..c0f8018 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5899,6 +5899,23 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
  s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_txrate_notify - txrate event for connected stations
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @txrate_event: the triggered TX RATE event
+ * @txrate_level: new TX RATE level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a average of attempted frame txrate crossed
+ * above configured high txrate or below configured low txrate event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_txrate_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+   u32 txrate_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 31680d6..645a9fd 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15576,6 +15576,44 @@ void cfg80211_sta_mon_rssi_notify(struct net_device 
*dev, const u8 *peer,
 }
 EXPORT_SYMBOL(cfg80211_sta_mon_rssi_notify);
 
+void
+cfg80211_sta_mon_txrate_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+   u32 txrate_level, gfp_t gfp)
+{
+   struct sk_buff *msg;
+
+   trace_cfg80211_sta_mon_txrate_notify(dev, peer, txrate_event,
+txrate_level);
+
+   if (WARN_ON(txrate_event !=
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW &&
+   txrate_event !=
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH &&
+   txrate_event !=
+   NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE))
+   return;
+
+   msg = cfg80211_prepare_sta_mon(dev, peer, gfp);
+   if (!msg)
+   return;
+
+   if (nla_put_u32(msg, NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT,
+   txrate_event))
+   goto nla_put_failure;
+
+   if (txrate_level && nla_put_u32(msg, NL80211_ATTR_STA_MON_TXRATE_LEVEL,
+   txrate_level))
+   goto nla_put_failure;
+
+   cfg80211_send_sta_mon(msg, gfp);
+
+   return;
+nla_put_failure:
+   nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_sta_mon_txrate_notify);
+
 static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
 struct net_device *netdev,
 struct cfg80211_chan_def *chandef,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index ca985c2..95f4a31 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3355,6 +3355,31 @@
  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
  __entry->low_txrate_thold, __entry->high_txrate_thold)
 );
+
+TRACE_EVENT(cfg80211_sta_mon_txrate_notify,
+   TP_PROTO(struct net_device *netdev, const u8 *peer,
+enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+u32 txrate_level),
+   TP_ARGS(netdev, peer, txrate_event, txrate_level),
+   TP_STRUCT__entry(
+   NETDEV_ENTRY
+   MAC_ENTRY(peer)
+   __field(enum nl80211_sta_mon_txrate_threshold_event,
+   txrate_event)
+   __field(u32, txrate_level)
+   ),
+   TP_fast_assign(
+   NETDEV_ASSIGN;
+   MAC_ASSIGN(peer, peer);
+   __entry->txrate_event = txrate_event;
+   __entry->txrate_level = txrate_level;
+   ),
+   TP_printk(NETDEV_PR_FMT ", peer: " MAC_PR_FMT
+ ", tx_rate event: %d, txrate : %u",
+ NETDEV_PR_ARG, MAC_PR_ARG(peer),
+ __entry->txrate_event, __entry->txrate_level)
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
-- 
1.7.9.5



[PATCH 4/4] mac80211: Implement functionality to monitor txrate cross event for a station

2018-06-13 Thread Tamizh chelvam
Trigger cfg80211_sta_mon_txrate_notify with the corresponding txrate
event when the txrate for a station goes out of configured range.
This event will be useful for the application like steering to take
decision on any station depends on its current capability.

Signed-off-by: Tamizh chelvam 
---
 include/net/mac80211.h  |5 +
 net/mac80211/cfg.c  |1 +
 net/mac80211/sta_info.h |   10 ++
 net/mac80211/status.c   |   40 +++-
 4 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 96fb9a8..02714ea 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -808,6 +808,11 @@ enum mac80211_rate_control_flags {
  */
 #define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
 
+/* Number of txrate count need to have been used in average station's
+ * txrate before checking against the threshold
+ */
+#define IEEE80211_STA_TXRATE_AVE_MIN_COUNT 4
+
 
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 649f5c7..36ec5fb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3904,6 +3904,7 @@ static int ieee80211_set_sta_mon_txrate_config(struct 
wiphy *wiphy,
 
sta->txrate_low = low_txrate_thold;
sta->txrate_high = high_txrate_thold;
+   sta->last_txrate_event = 0;
 
 unlock:
mutex_unlock(>local->sta_mtx);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index a71f50c..f978e5a 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -419,6 +419,8 @@ struct ieee80211_sta_rx_stats {
  */
 #define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
 
+DECLARE_EWMA(sta_txrate, 4, 4)
+
 /**
  * struct sta_info - STA information
  *
@@ -501,6 +503,11 @@ struct ieee80211_sta_rx_stats {
  * in 100Kbps
  * @txrate_high: TXRATE upper threshold for a station to monitor, this will be
  * in 100Kbps
+ * @count_sta_txrate: Number of transmitted data frames used in ave_sta_txrate
+ * @last_txrate_event: Last txrate event that triggered sta_mon event for a
+ * station
+ * @ave_sta_txrate: Average txrate to check against the txrate_low and
+ * txrate_high. Values expressed in 100kbps
  */
 struct sta_info {
/* General information, mostly static */
@@ -611,6 +618,9 @@ struct sta_info {
 
u32 txrate_low;
u32 txrate_high;
+   unsigned int count_sta_txrate;
+   enum nl80211_sta_mon_txrate_threshold_event last_txrate_event;
+   struct ewma_sta_txrate ave_sta_txrate;
 
/* keep last! */
struct ieee80211_sta sta;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 9a6d720..112b18d 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -701,6 +701,40 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, 
struct sk_buff *skb,
dev_kfree_skb(skb);
 }
 
+static void ieee80211_sta_mon_txrate_thold_check(struct sta_info *sta)
+{
+   struct rate_info rinfo;
+   enum nl80211_sta_mon_txrate_threshold_event sta_txrate_event;
+   int txrate;
+
+   if (!sta->txrate_high)
+   return;
+
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   txrate = cfg80211_calculate_bitrate();
+   ewma_sta_txrate_add(>ave_sta_txrate, txrate);
+   sta->count_sta_txrate++;
+
+   if (sta->count_sta_txrate < IEEE80211_STA_TXRATE_AVE_MIN_COUNT)
+   return;
+
+   txrate = ewma_sta_txrate_read(>ave_sta_txrate);
+
+   if (txrate < sta->txrate_low)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW;
+   else if (txrate > sta->txrate_high)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH;
+   else
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE;
+
+   if (sta_txrate_event != sta->last_txrate_event) {
+   cfg80211_sta_mon_txrate_notify(sta->sdata->dev, sta->addr,
+  sta_txrate_event, txrate,
+  GFP_ATOMIC);
+   sta->last_txrate_event = sta_txrate_event;
+   }
+}
+
 static void __ieee80211_tx_status(struct ieee80211_hw *hw,
  struct ieee80211_tx_status *status)
 {
@@ -750,9 +784,13 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
 
if (ieee80211_hw_check(>hw, HAS_RATE_CONTROL) &&
(ieee80211_is_data(hdr->frame_control)) &&
-   (rates_idx != -1))
+   (rates_idx != -1)) {
sta->tx_stats.last_rate =
info->status.rates[rates_idx];
+   if (wiphy_ext_feature_isset(hw->wiphy,
+   NL80211_EXT_FEATURE_ST

[PATCH 0/4] cfg80211/mac80211: Add support to configure and monitor txrate threshold

2018-06-13 Thread Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring txrate threshold for the connected stations and api to
notify userspace application upon crossing the configured txrate threshold.
This will be useful for the application which requires
station's current capability change information.

Tamizh chelvam (4):
  cfg80211: Add support to configure station specific txrate threshold
  mac80211: Add api to configure low and high txrate threshold
  cfg80211: Add support to notify station's txrate crossing event
  mac80211: Implement functionality to monitor txrate cross event for a
station

Note:
  * This patchset rebased on top of below patchset
[PATCH 0/7] cfg80211/mac80211: Add support to configure and monitor rssi 
threshold

 include/net/cfg80211.h   |   26 ++
 include/net/mac80211.h   |5 +++
 include/uapi/linux/nl80211.h |   34 ++
 net/mac80211/cfg.c   |   36 +++
 net/mac80211/sta_info.h  |   17 +
 net/mac80211/status.c|   40 +-
 net/wireless/nl80211.c   |   78 ++
 net/wireless/rdev-ops.h  |   17 +
 net/wireless/trace.h |   50 +++
 9 files changed, 302 insertions(+), 1 deletion(-)

-- 
1.7.9.5



[PATCH 4/7] cfg80211: Add support to notify station's rssi level crossing

2018-06-13 Thread Tamizh chelvam
Add cfg80211_sta_mon_rssi_notify api to update user space upon
crossing the configured rssi threshold of a station.
NL80211_CMD_NOTIFY_STA_MON introduced to send this event to
userspace along with NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
NL80211_ATTR_MAC and NL80211_ATTR_STA_MON_RSSI_LEVEL info.
Userspace application can make a decision depends on this
notification.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |   16 +++
 include/uapi/linux/nl80211.h |1 +
 net/wireless/nl80211.c   |   98 ++
 net/wireless/trace.h |   22 ++
 4 files changed, 137 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 584697b..7dcf9b9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5916,6 +5916,22 @@ void cfg80211_cqm_txe_notify(struct net_device *dev, 
const u8 *peer,
 void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_rssi_notify - Station's rssi out of range event
+ * @dev: network device
+ * @peer: Station's mac address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured rssi threshold reached event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_rssi_threshold_event rssi_event,
+   s32 rssi_level, gfp_t gfp);
+
+/**
  * cfg80211_radar_event - radar detection event
  * @wiphy: the wiphy
  * @chandef: chandef for the current channel
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f13ad07..9d47ee6 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1249,6 +1249,7 @@ enum nl80211_commands {
NL80211_CMD_CONTROL_PORT_FRAME,
 
NL80211_CMD_SET_STA_MON,
+   NL80211_CMD_NOTIFY_STA_MON,
 
/* add new commands above here */
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 587a5cb1..021e55a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15364,6 +15364,104 @@ void cfg80211_pmksa_candidate_notify(struct 
net_device *dev, int index,
 }
 EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
 
+static struct sk_buff *cfg80211_prepare_sta_mon(struct net_device *dev,
+   const char *mac, gfp_t gfp)
+{
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+   struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+   struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+   void **cb;
+
+   if (!msg)
+   return NULL;
+
+   cb = (void **)msg->cb;
+
+   cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_STA_MON);
+   if (!cb[0]) {
+   nlmsg_free(msg);
+   return NULL;
+   }
+
+   if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+   nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
+   goto nla_put_failure;
+
+   if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
+   goto nla_put_failure;
+
+   cb[1] = nla_nest_start(msg, NL80211_ATTR_STA_MON);
+   if (!cb[1])
+   goto nla_put_failure;
+
+   cb[2] = rdev;
+
+   return msg;
+nla_put_failure:
+   nlmsg_free(msg);
+   return NULL;
+}
+
+static void cfg80211_send_sta_mon(struct sk_buff *msg, gfp_t gfp)
+{
+   void **cb = (void **)msg->cb;
+   struct cfg80211_registered_device *rdev = cb[2];
+
+   nla_nest_end(msg, cb[1]);
+   genlmsg_end(msg, cb[0]);
+
+   memset(msg->cb, 0, sizeof(msg->cb));
+
+   genlmsg_multicast_netns(_fam, wiphy_net(>wiphy), msg, 0,
+   NL80211_MCGRP_MLME, gfp);
+}
+
+void cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_rssi_threshold_event rssi_event,
+   s32 rssi_level, gfp_t gfp)
+{
+   struct sk_buff *msg;
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+   struct cfg80211_rssi_config *rssi_config;
+
+   if (WARN_ON(!peer))
+   return;
+
+   if (WARN_ON(rssi_event != NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW &&
+   rssi_event != NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH))
+   return;
+
+   trace_cfg80211_sta_mon_rssi_notify(dev, peer, rssi_event, rssi_level);
+
+   list_for_each_entry(rssi_config, >rssi_config_list, list) {
+   if (!memcmp(rssi_config->addr, peer, ETH_ALEN)) {
+   wdev->rssi_config = rssi_config;
+   wdev->rssi_config->last_rssi_event_value = rssi_level;
+   break;
+   }
+   }
+
+   msg = cfg80211_prepare_sta_mon(dev, peer, gfp);
+   if (!msg)

[PATCH 2/7] cfg80211: Add new NL command to configure peer specific rssi threshold

2018-06-13 Thread Tamizh chelvam
This patch add support to configure peer specific rssi configuration
to monitor station's signal strength variation.
New NL80211_CMD_SET_STA_MON introduced to configure rssi threshold
and hysteresis info using NL80211_ATTR_STA_MON_RSSI_THOLD and
NL80211_ATTR_STA_MON_RSSI_HYST along with NL80211_ATTR_MAC.
Driver supporting this configuration should advertise
NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG.
Monitoring station's signal strength variation will be useful
for the application like steering.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |9 +
 include/uapi/linux/nl80211.h |   55 ++
 net/wireless/nl80211.c   |   77 ++
 net/wireless/rdev-ops.h  |   16 +
 net/wireless/trace.h |   25 ++
 5 files changed, 182 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3e123a3..584697b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3024,6 +3024,11 @@ struct cfg80211_external_auth_params {
  *
  * @tx_control_port: TX a control port frame (EAPoL).  The noencrypt parameter
  * tells the driver that the frame should not be encrypted.
+ * @set_sta_mon_rssi_config: Configure  RSSI threshold for a station.
+ * After configuration, the driver should (soon) send an event indicating
+ * the current level of a station is above/below the configured threshold;
+ * this may need some care when the configuration is changed
+ * (without first being disabled.)
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3329,6 +3334,10 @@ struct cfg80211_ops {
   const u8 *buf, size_t len,
   const u8 *dest, const __be16 proto,
   const bool noencrypt);
+   int (*set_sta_mon_rssi_config)(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *addr,
+  s32 rssi_thold, u32 rssi_hyst);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 28b3654..f13ad07 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1033,6 +1033,9 @@
  * _ATTR_CHANNEL_WIDTH,_ATTR_NSS attributes with its
  * address(specified in _ATTR_MAC).
  *
+ * @NL80211_CMD_SET_STA_MON: This command is used to configure station's
+ * connection monitoring notification trigger levels.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1245,6 +1248,8 @@ enum nl80211_commands {
 
NL80211_CMD_CONTROL_PORT_FRAME,
 
+   NL80211_CMD_SET_STA_MON,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -2238,6 +2243,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
  *  a flow is assigned on each round of the DRR scheduler.
  *
+ * @NL80211_ATTR_STA_MON: Station's connection monitor configuration in a
+ * nested attribute with %NL80211_ATTR_STA_MON_* sub-attributes.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2677,6 +2685,8 @@ enum nl80211_attrs {
NL80211_ATTR_TXQ_MEMORY_LIMIT,
NL80211_ATTR_TXQ_QUANTUM,
 
+   NL80211_ATTR_STA_MON,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
@@ -4276,6 +4286,46 @@ enum nl80211_ps_state {
 };
 
 /**
+ * enum nl80211_attr_sta_mon - Attributes to monitor station's connection
+ * @NL80211_ATTR_STA_MON_RSSI_THOLD: RSSI threshold in dBm. This value 
specifies
+ * the threshold for the RSSI level at which an event will be sent. Zero
+ * to disable.  Alternatively, if %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST is
+ * set, multiple values can be supplied as a low-to-high sorted array of\
+ * threshold values in dBm.  Events will be sent when the RSSI value
+ * crosses any of the thresholds. This threshold values are station
+ * specific.
+ * @NL80211_ATTR_STA_MON_RSSI_HYST: RSSI hysteresis in dBm. This value 
specifies
+ * the minimum amount the RSSI level must change after an event before a
+ * new event may be issued (to reduce effects of RSSI oscillation).
+ * @NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT: RSSI threshold event
+ * @NL80211_ATTR_STA_MON_RSSI_LEVEL: the RSSI value in dBm that triggered the
+ * RSSI threshold event.
+ */
+enum nl80211_attr_sta_mon {
+   __NL80211_ATTR_STA_MON_INVALID,
+   NL80211_ATTR_STA_MON_RSSI_THOLD,
+   NL80211_ATTR_STA_MON_RSSI_HYST,
+   NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
+   NL80211_ATTR_STA_MON_RSSI_LEVEL,
+
+   /* keep last

[PATCH 7/7] mac80211: Add api to configure low and high RSSI threshold

2018-06-13 Thread Tamizh chelvam
Add set_sta_mon_rssi_range_config api to support
configuring low and high RSSI threshold values
for a connected station. And trigger an event if a
station's signal strength goes out of configured
range.

Signed-off-by: Tamizh chelvam 
---
 net/mac80211/cfg.c  |   40 
 net/mac80211/rx.c   |   23 +++
 net/mac80211/sta_info.h |6 ++
 3 files changed, 69 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 80ced50..5cdd8a3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3831,12 +3831,51 @@ static int ieee80211_set_sta_mon_rssi_config(struct 
wiphy *wiphy,
 
sta->rssi_thold = rssi_thold;
sta->rssi_hyst = rssi_hyst;
+   sta->rssi_low = 0;
+   sta->rssi_high = 0;
sta->last_sta_mon_event_signal = 0;
 unlock:
mutex_unlock(>local->sta_mtx);
return 0;
 }
 
+static int ieee80211_set_sta_mon_rssi_range_cfg(struct wiphy *wiphy,
+   struct net_device *dev,
+   const u8 *peer,
+   s32 rssi_low, s32 rssi_high)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+NL80211_EXT_FEATURE_STA_MON_RSSI_LIST)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_low == rssi_low &&
+   sta->rssi_high == rssi_high)
+   goto unlock;
+
+   sta->rssi_thold = 0;
+   sta->rssi_hyst = 0;
+   sta->rssi_low = rssi_low;
+   sta->rssi_high = rssi_high;
+   sta->last_sta_mon_event_signal = 0;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3932,4 +3971,5 @@ static int ieee80211_set_sta_mon_rssi_config(struct wiphy 
*wiphy,
.tx_control_port = ieee80211_tx_control_port,
.get_txq_stats = ieee80211_get_txq_stats,
.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
+   .set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_cfg,
 };
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 06a6111..fddb5c6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1569,6 +1569,29 @@ static void ieee80211_sta_rx_signal_thold_check(struct 
ieee80211_rx_data *rx)
sig, GFP_ATOMIC);
}
}
+
+   if (sta->rssi_low) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+   int low = sta->rssi_low;
+   int high = sta->rssi_high;
+
+   if (sig < low &&
+   (last_event == 0 || last_event >= low)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > high &&
+  (last_event == 0 || last_event <= high)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
 }
 
 static ieee80211_rx_result debug_noinline
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index e130f6d..05d68f8 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -487,6 +487,10 @@ struct ieee80211_sta_rx_stats {
  * should cause an event to be sent indicating where the current value
  * is in relation to the newly configured threshold
  * @rssi_hyst: Station's RSSI hysteresis
+ * @rssi_low: RSSI lower threshold to monitor station's signal strength, a zero
+ * value implies disabled.  This is an alternative mechanism to the single
+ * threshold event and can't be enabled simultaneously with it
+ * @rssi_high: RSSI upper threshold for station
  * @last_sta_mon_event_signal: Last signal strength average for a station
  * that triggered a sta

[PATCH 6/7] cfg80211: Accept multiple RSSI threholds for STA_MON command

2018-06-13 Thread Tamizh chelvam
Change the NL80211_CMD_STA_MON RSSI threshold attribut to
accept any number of thresholds as a sorted array. If
user send the configuration with single RSSI threshold then
the old mechanism is enabled. Same netlink event will be
generated in both cases. This patch introduced
set_sta_mon_rssi_range_config to configure high and low
value.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_STA_MON_RSSI_LIST.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |   10 +++
 include/uapi/linux/nl80211.h |4 +
 net/wireless/nl80211.c   |  176 ++
 net/wireless/rdev-ops.h  |   15 
 net/wireless/trace.h |   26 +++
 5 files changed, 180 insertions(+), 51 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7dcf9b9..4c49cc5 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3029,6 +3029,12 @@ struct cfg80211_external_auth_params {
  * the current level of a station is above/below the configured threshold;
  * this may need some care when the configuration is changed
  * (without first being disabled.)
+ * @set_sta_mon_rssi_range_config: Configure two RSSI thresholds in the
+ * station's rssi monitor.  An event is to be sent only when the
+ * signal level of a station is found to be outside the two values.
+ * The driver should advertise %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if
+ * this method is implemented. If it is provided then there's no point
+ * providing @set_sta_mon_rssi_config
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3338,6 +3344,10 @@ struct cfg80211_ops {
   struct net_device *dev,
   const u8 *addr,
   s32 rssi_thold, u32 rssi_hyst);
+   int (*set_sta_mon_rssi_range_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+s32 rssi_low, s32 rssi_high);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9d47ee6..8e2a84b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5188,6 +5188,9 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG: With this driver can set
  * rssi threshold using %NL80211_ATTR_STA_MON_RSSI_THOLD attribute
  * for a connected station.
+ * @NL80211_EXT_FEATURE_STA_MON_RSSI_LIST: With this driver the
+ * %NL80211_ATTR_STA_MON_RSSI_THOLD attribute accepts a list of zero or
+ * more RSSI threshold values to monitor rather than exactly one threshold.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5223,6 +5226,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT,
NL80211_EXT_FEATURE_TXQS,
NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_LIST,
 
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 021e55a..c0fccb4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10134,61 +10134,101 @@ static int nl80211_set_cqm_txe(struct genl_info 
*info,
 
 static const struct nla_policy
 nl80211_attr_sta_mon_policy[NL80211_ATTR_STA_MON_MAX + 1] = {
-   [NL80211_ATTR_STA_MON_RSSI_THOLD] = { .type = NLA_U32 },
+   [NL80211_ATTR_STA_MON_RSSI_THOLD] = { .type = NLA_BINARY },
[NL80211_ATTR_STA_MON_RSSI_HYST] = { .type = NLA_U32 },
[NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
[NL80211_ATTR_STA_MON_RSSI_LEVEL] = { .type = NLA_S32 },
 };
 
-static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
-   struct net_device *dev)
+static int cfg80211_set_rssi_range(struct cfg80211_registered_device *rdev,
+  struct net_device *dev, const u8 *mac_addr,
+  bool get_last_rssi)
 {
struct wireless_dev *wdev = dev->ieee80211_ptr;
-   s32 last, low, high;
+   s32 low, high, last;
u32 hyst;
-   int i, n;
-   int err;
-
-   /* RSSI reporting disabled? */
-   if (!wdev->rssi_config)
-   return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
+   int i, n, err;
 
-   /*
-* Obtain current RSSI value if possible, if not and no RSSI threshold
-* event has been received yet, we should receive an event after a
-* connection is established and enough beacons received to calculate
-* the average.
-*/
-   if (!wdev->rssi_config->last_rssi

[PATCH 5/7] mac80211: Implement functionality to monitor station's rssi cross event

2018-06-13 Thread Tamizh chelvam
Triggers cfg80211_sta_mon_rssi_notify with the corresponding event when
station signal goes out of configured threshold. It uses rx data signal
to check against rssi threshold configured by the user.
This event will be useful for the application like steering to take
decision on any station depends on its current capability.

Signed-off-by: Tamizh chelvam 
---
 include/net/mac80211.h  |6 ++
 net/mac80211/rx.c   |   42 +-
 net/mac80211/sta_info.h |4 
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 851a5e1..96fb9a8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -802,6 +802,12 @@ enum mac80211_rate_control_flags {
IEEE80211_TX_RC_160_MHZ_WIDTH   = BIT(10),
 };
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
 
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 0a38cc1..06a6111 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1534,6 +1534,43 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf = >sdata->vif.bss_conf;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (sta->rssi_thold && bss_conf->enable_beacon) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int thold = sta->rssi_thold;
+   int hyst = sta->rssi_hyst;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+
+   if (sig < thold &&
+   (last_event == 0 || sig < last_event - hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > thold &&
+  (last_event == 0 || sig > last_event + hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1589,6 +1626,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -4030,9 +4068,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
/* statistics part of ieee80211_rx_h_sta_process() */
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
-   if (!fast_rx->uses_rss)
+   if (!fast_rx->uses_rss) {
ewma_signal_add(>rx_stats_avg.signal,
-status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
+   }
}
 
if (status->chains) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 8c459a7..e130f6d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -490,6 +490,9 @@ struct ieee80211_sta_rx_stats {
  * @last_sta_mon_event_signal: Last signal strength average for a station
  * that triggered a sta_mon event. 0 indicates that no event has been
  * generated for the current association
+ * @count_rx_signal: Number of data frames used in averaging station signal.
+ * This can be used to avoid generating less reliable station rssi cross
+ * events that would be based only on couple of received frames
  */
 struct sta_info {
/* General information, mostly static */
@@ -594,6 +597,7 @@ struct sta_info {
s32 rssi_thold;
   

[PATCH 1/7] wireless: Change single cqm_config to rssi config list

2018-06-13 Thread Tamizh chelvam
This patch changes single cqm_config into mac address based
rssi config list. This way the same structure can be
utilized by AP mode as well.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h |8 --
 net/wireless/core.c|   29 +++
 net/wireless/core.h|6 ++--
 net/wireless/nl80211.c |   74 
 4 files changed, 82 insertions(+), 35 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5fbfe61..3e123a3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4139,7 +4139,7 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
 struct cfg80211_conn;
 struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
-struct cfg80211_cqm_config;
+struct cfg80211_rssi_config;
 
 /**
  * struct wireless_dev - wireless device state
@@ -4204,7 +4204,8 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
  * @nl_owner_dead: (private) owner socket went away
- * @cqm_config: (private) nl80211 RSSI monitor state
+ * @rssi_config: (private) nl80211 RSSI monitor state
+ * @rssi_config_list: (private) peer based list for rssi config
  */
 struct wireless_dev {
struct wiphy *wiphy;
@@ -4275,7 +4276,8 @@ struct wireless_dev {
} wext;
 #endif
 
-   struct cfg80211_cqm_config *cqm_config;
+   struct cfg80211_rssi_config *rssi_config;
+   struct list_head rssi_config_list;
 };
 
 static inline u8 *wdev_address(struct wireless_dev *wdev)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5fe35aa..62e496e 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -994,10 +994,28 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool 
blocked)
 }
 EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev)
+void cfg80211_rssi_config_free(struct wireless_dev *wdev, const u8 *peer)
 {
-   kfree(wdev->cqm_config);
-   wdev->cqm_config = NULL;
+   struct cfg80211_rssi_config *rssi_config, *tmp;
+
+   if (list_empty(>rssi_config_list))
+   goto free;
+
+   list_for_each_entry_safe(rssi_config, tmp, >rssi_config_list,
+list) {
+   if (peer && memcmp(rssi_config->addr, peer, ETH_ALEN))
+   continue;
+
+   list_del(_config->list);
+   kfree(rssi_config);
+   if (list_empty(>rssi_config_list) || peer)
+   goto out;
+   }
+
+free:
+   kfree(wdev->rssi_config);
+out:
+   wdev->rssi_config = NULL;
 }
 
 void cfg80211_unregister_wdev(struct wireless_dev *wdev)
@@ -1027,7 +1045,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
break;
}
 
-   cfg80211_cqm_config_free(wdev);
+   cfg80211_rssi_config_free(wdev, NULL);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
 
@@ -1163,6 +1181,7 @@ static int cfg80211_netdev_notifier_call(struct 
notifier_block *nb,
spin_lock_init(>event_lock);
INIT_LIST_HEAD(>mgmt_registrations);
spin_lock_init(>mgmt_registrations_lock);
+   INIT_LIST_HEAD(>rssi_config_list);
 
/*
 * We get here also when the interface changes network 
namespaces,
@@ -1292,7 +1311,7 @@ static int cfg80211_netdev_notifier_call(struct 
notifier_block *nb,
kzfree(wdev->wext.keys);
 #endif
flush_work(>disconnect_wk);
-   cfg80211_cqm_config_free(wdev);
+   cfg80211_rssi_config_free(wdev, NULL);
}
/*
 * synchronise (so that we won't find this netdev
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 63eb1b5..170a31b 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -260,10 +260,12 @@ struct cfg80211_beacon_registration {
u32 nlportid;
 };
 
-struct cfg80211_cqm_config {
+struct cfg80211_rssi_config {
+   struct list_head list;
u32 rssi_hyst;
s32 last_rssi_event_value;
int n_rssi_thresholds;
+   u8 addr[ETH_ALEN];
s32 rssi_thresholds[0];
 };
 
@@ -514,6 +516,6 @@ void cfg80211_stop_nan(struct cfg80211_registered_device 
*rdev,
 #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; })
 #endif
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev);
+void cfg80211_rssi_config_free(struct wireless_dev *wdev, const u8 *peer);
 
 #endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 07514ca..2fb2e97 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3200,6 +3200,7 @@ static int nl80211_new_interface(struct sk_buff *skb, 
struct genl_info *info)
spin_l

[PATCH 0/7] cfg80211/mac80211: Add support to configure and monitor rssi threshold

2018-06-13 Thread Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring rssi for the connected stations and api to notify
userspace application upon crossing the configured threshold.
This will be useful for the application which requires
station's current capability change information.

Tamizh chelvam (7):
  wireless: Change single cqm_config to rssi config list
  cfg80211: Add new NL command to configure peer specific rssi
threshold
  mac80211: Add api to support configuring station specific rssi
threshold
  cfg80211: Add support to notify station's rssi level crossing
  mac80211: Implement functionality to monitor station's rssi cross
event
  cfg80211: Accept multiple RSSI threholds for STA_MON command
  mac80211: Add api to configure low and high RSSI threshold

 include/net/cfg80211.h   |   42 -
 include/net/mac80211.h   |6 +
 include/uapi/linux/nl80211.h |   60 +++
 net/mac80211/cfg.c   |   75 +
 net/mac80211/rx.c|   65 +++-
 net/mac80211/sta_info.h  |   22 +++
 net/wireless/core.c  |   29 +++-
 net/wireless/core.h  |6 +-
 net/wireless/nl80211.c   |  377 --
 net/wireless/rdev-ops.h  |   31 
 net/wireless/trace.h |   73 
 11 files changed, 723 insertions(+), 63 deletions(-)

-- 
1.7.9.5



[PATCH 3/7] mac80211: Add api to support configuring station specific rssi threshold

2018-06-13 Thread Tamizh chelvam
This patch add set_sta_mon_rssi_config api to configure rssi and
hysteresis threshold value for a connected station. This configuration
will be applied only for the connected station.

Signed-off-by: Tamizh chelvam 
---
 net/mac80211/cfg.c  |   35 +++
 net/mac80211/sta_info.h |   12 
 2 files changed, 47 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bdf6fa7..80ced50 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3803,6 +3803,40 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
return ret;
 }
 
+static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *peer, s32 rssi_thold,
+u32 rssi_hyst)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+!wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_thold == rssi_thold &&
+   sta->rssi_hyst == rssi_hyst)
+   goto unlock;
+
+   sta->rssi_thold = rssi_thold;
+   sta->rssi_hyst = rssi_hyst;
+   sta->last_sta_mon_event_signal = 0;
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3897,4 +3931,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
.tx_control_port = ieee80211_tx_control_port,
.get_txq_stats = ieee80211_get_txq_stats,
+   .set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 81b35f6..8c459a7 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -482,6 +482,14 @@ struct ieee80211_sta_rx_stats {
  * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
  * this (by advertising the USES_RSS hw flag)
  * @status_stats: TX status statistics
+ * @rssi_thold: RSSI threshold to monitor station's signal strength, a zero
+ * value implies disabled. As with the cfg80211 callback, a change here
+ * should cause an event to be sent indicating where the current value
+ * is in relation to the newly configured threshold
+ * @rssi_hyst: Station's RSSI hysteresis
+ * @last_sta_mon_event_signal: Last signal strength average for a station
+ * that triggered a sta_mon event. 0 indicates that no event has been
+ * generated for the current association
  */
 struct sta_info {
/* General information, mostly static */
@@ -583,6 +591,10 @@ struct sta_info {
 
struct cfg80211_chan_def tdls_chandef;
 
+   s32 rssi_thold;
+   u32 rssi_hyst;
+   int last_sta_mon_event_signal;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.7.9.5



[RFCv3 4/4] mac80211: Implement functionality to monitor txrate cross event for a station

2018-05-30 Thread Tamizh chelvam
Trigger cfg80211_sta_mon_txrate_notify with the corresponding txrate
event when the txrate for a station goes out of configured range.
This event will be useful for the application like steering to take
decision on any station depends on its current capability.

Signed-off-by: Tamizh chelvam 
---
 include/net/mac80211.h  |  5 +
 net/mac80211/cfg.c  |  1 +
 net/mac80211/sta_info.h | 10 ++
 net/mac80211/status.c   | 40 +++-
 4 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 96fb9a8..02714ea 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -808,6 +808,11 @@ enum mac80211_rate_control_flags {
  */
 #define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
 
+/* Number of txrate count need to have been used in average station's
+ * txrate before checking against the threshold
+ */
+#define IEEE80211_STA_TXRATE_AVE_MIN_COUNT 4
+
 
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 649f5c7..36ec5fb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3904,6 +3904,7 @@ static int ieee80211_set_sta_mon_txrate_config(struct 
wiphy *wiphy,
 
sta->txrate_low = low_txrate_thold;
sta->txrate_high = high_txrate_thold;
+   sta->last_txrate_event = 0;
 
 unlock:
mutex_unlock(>local->sta_mtx);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index a71f50c..f978e5a 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -419,6 +419,8 @@ struct ieee80211_sta_rx_stats {
  */
 #define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
 
+DECLARE_EWMA(sta_txrate, 4, 4)
+
 /**
  * struct sta_info - STA information
  *
@@ -501,6 +503,11 @@ struct ieee80211_sta_rx_stats {
  * in 100Kbps
  * @txrate_high: TXRATE upper threshold for a station to monitor, this will be
  * in 100Kbps
+ * @count_sta_txrate: Number of transmitted data frames used in ave_sta_txrate
+ * @last_txrate_event: Last txrate event that triggered sta_mon event for a
+ * station
+ * @ave_sta_txrate: Average txrate to check against the txrate_low and
+ * txrate_high. Values expressed in 100kbps
  */
 struct sta_info {
/* General information, mostly static */
@@ -611,6 +618,9 @@ struct sta_info {
 
u32 txrate_low;
u32 txrate_high;
+   unsigned int count_sta_txrate;
+   enum nl80211_sta_mon_txrate_threshold_event last_txrate_event;
+   struct ewma_sta_txrate ave_sta_txrate;
 
/* keep last! */
struct ieee80211_sta sta;
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 9a6d720..112b18d 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -701,6 +701,40 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, 
struct sk_buff *skb,
dev_kfree_skb(skb);
 }
 
+static void ieee80211_sta_mon_txrate_thold_check(struct sta_info *sta)
+{
+   struct rate_info rinfo;
+   enum nl80211_sta_mon_txrate_threshold_event sta_txrate_event;
+   int txrate;
+
+   if (!sta->txrate_high)
+   return;
+
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   txrate = cfg80211_calculate_bitrate();
+   ewma_sta_txrate_add(>ave_sta_txrate, txrate);
+   sta->count_sta_txrate++;
+
+   if (sta->count_sta_txrate < IEEE80211_STA_TXRATE_AVE_MIN_COUNT)
+   return;
+
+   txrate = ewma_sta_txrate_read(>ave_sta_txrate);
+
+   if (txrate < sta->txrate_low)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW;
+   else if (txrate > sta->txrate_high)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH;
+   else
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE;
+
+   if (sta_txrate_event != sta->last_txrate_event) {
+   cfg80211_sta_mon_txrate_notify(sta->sdata->dev, sta->addr,
+  sta_txrate_event, txrate,
+  GFP_ATOMIC);
+   sta->last_txrate_event = sta_txrate_event;
+   }
+}
+
 static void __ieee80211_tx_status(struct ieee80211_hw *hw,
  struct ieee80211_tx_status *status)
 {
@@ -750,9 +784,13 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
 
if (ieee80211_hw_check(>hw, HAS_RATE_CONTROL) &&
(ieee80211_is_data(hdr->frame_control)) &&
-   (rates_idx != -1))
+   (rates_idx != -1)) {
sta->tx_stats.last_rate =
info->status.rates[rates_idx];
+   if (wiphy_ext_feature_isset(hw->wiphy,
+   NL80211_EXT_FEATURE_ST

[RFCv3 1/4] cfg80211: Add support to configure station specific txrate threshold

2018-05-30 Thread Tamizh chelvam
Add support to configure station specific txrate threshold
to monitor variation in the txrate for a station. Configuration
is passed using NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD and
NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD in NL80211_CMD_SET_STA_MON
command and the configuration will be represented in 100kbps.
This will be useful for the application like steering which requires
station's current capability.

Driver supporting this configuration feature should advertise
NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |  9 +
 include/uapi/linux/nl80211.h | 34 ++
 net/wireless/nl80211.c   | 40 
 net/wireless/rdev-ops.h  | 17 +
 net/wireless/trace.h | 25 +
 5 files changed, 125 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ffd1204..ab8a43f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3035,6 +3035,10 @@ struct cfg80211_external_auth_params {
  * The driver should advertise %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if
  * this method is implemented. If it is provided then there's no point
  * providing @set_sta_mon_rssi_config
+ * @set_sta_mon_txrate_config: Configure low and high TXRATE threshold in 
100kbs
+ * for a connected station. The driver should(soon) send an event
+ * indicating the current attempted frame txrate level is above/below the
+ * configured threshold
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3348,6 +3352,11 @@ struct cfg80211_ops {
 struct net_device *dev,
 const u8 *addr,
 s32 rssi_low, s32 rssi_high);
+   int (*set_sta_mon_txrate_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+u32 low_txrate_thold,
+u32 high_txrate_thold);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8e2a84b..c7ce475 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4301,6 +4301,15 @@ enum nl80211_ps_state {
  * @NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT: RSSI threshold event
  * @NL80211_ATTR_STA_MON_RSSI_LEVEL: the RSSI value in dBm that triggered the
  * RSSI threshold event.
+ * @NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the low txrate threshold. Event will be sent
+ * if the txrate for a station goes lesser than this threshold.
+ * @NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the upper txrate threshold. Event will be sent
+ * if the txrate for a station goes greater than this threshold.
+ * @NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT: TX_RATE threshold cross event
+ * @NL80211_ATTR_STA_MON_TXRATE_LEVEL: TXRATE for a station in 100kbps that
+ * triggered the TX_RATE threshold cross event.
  */
 enum nl80211_attr_sta_mon {
__NL80211_ATTR_STA_MON_INVALID,
@@ -4308,6 +4317,10 @@ enum nl80211_attr_sta_mon {
NL80211_ATTR_STA_MON_RSSI_HYST,
NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
NL80211_ATTR_STA_MON_RSSI_LEVEL,
+   NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT,
+   NL80211_ATTR_STA_MON_TXRATE_LEVEL,
 
/* keep last */
__NL80211_ATTR_STA_MON_AFTER_LAST,
@@ -4327,6 +4340,21 @@ enum nl80211_sta_mon_rssi_threshold_event {
 };
 
 /**
+ * enum nl80211_sta_mon_txrate_threshold_event - TX_RATE threshold event
+ * @NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE: The TX_RATE level is in between
+ * low and high threshold
+ * @NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW: The TX_RATE level is lower than
+ * the configured threshold
+ * @NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH: The TX_RATE is higher than the
+ * configured threshold
+ */
+enum nl80211_sta_mon_txrate_threshold_event {
+   NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE,
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW,
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH,
+};
+
+/**
  * enum nl80211_attr_cqm - connection quality monitor attributes
  * @__NL80211_ATTR_CQM_INVALID: invalid
  * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies
@@ -5191,6 +5219,11 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_STA_MON_RSSI_LIST: With this driver the
  * %NL80211_ATTR_STA_MON_RSSI_THOLD attribute accepts a list of zero or
  * more RSSI threshold values to monitor rather than

[RFCv3 2/4] mac80211: Add api to configure low and high txrate threshold

2018-05-30 Thread Tamizh chelvam
Add set_sta_mon_txrate_config api to configure low and high
txrate threshold for a connected station. The configuration
will be represented in 100kbps.

Signed-off-by: Tamizh chelvam 
---
 net/mac80211/cfg.c  | 35 +++
 net/mac80211/sta_info.h |  7 +++
 2 files changed, 42 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5cdd8a3..649f5c7 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3876,6 +3876,40 @@ static int ieee80211_set_sta_mon_rssi_range_cfg(struct 
wiphy *wiphy,
return 0;
 }
 
+static int ieee80211_set_sta_mon_txrate_config(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *peer,
+  u32 low_txrate_thold,
+  u32 high_txrate_thold)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->txrate_low == low_txrate_thold &&
+   sta->txrate_high == high_txrate_thold)
+   goto unlock;
+
+   sta->txrate_low = low_txrate_thold;
+   sta->txrate_high = high_txrate_thold;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3972,4 +4006,5 @@ static int ieee80211_set_sta_mon_rssi_range_cfg(struct 
wiphy *wiphy,
.get_txq_stats = ieee80211_get_txq_stats,
.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
.set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_cfg,
+   .set_sta_mon_txrate_config = ieee80211_set_sta_mon_txrate_config,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 05d68f8..a71f50c 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -497,6 +497,10 @@ struct ieee80211_sta_rx_stats {
  * @count_rx_signal: Number of data frames used in averaging station signal.
  * This can be used to avoid generating less reliable station rssi cross
  * events that would be based only on couple of received frames
+ * @txrate_low: TXRATE lower threshold for a station to monitor, this will be
+ * in 100Kbps
+ * @txrate_high: TXRATE upper threshold for a station to monitor, this will be
+ * in 100Kbps
  */
 struct sta_info {
/* General information, mostly static */
@@ -605,6 +609,9 @@ struct sta_info {
int last_sta_mon_event_signal;
unsigned int count_rx_signal;
 
+   u32 txrate_low;
+   u32 txrate_high;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.9.1



[RFCv3 3/4] cfg80211: Add support to notify station's txrate crossing event

2018-05-30 Thread Tamizh chelvam
Add cfg80211_sta_mon_txrate_notify to update userspace upon
crossing the configured txrate threshold for a station.
This uses NL80211_CMD_NOTIFY_STA_MON along with
NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT, NL80211_ATTR_MAC
and NL80211_ATTR_STA_MON_TXRATE_LEVEL. Userspace application can
make a decision on the station depends on this notification.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h | 17 +
 net/wireless/nl80211.c | 36 
 net/wireless/trace.h   | 25 +
 3 files changed, 78 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ab8a43f..b02ed31 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5898,6 +5898,23 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
  s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_txrate_notify - txrate event for connected stations
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @txrate_event: the triggered TX RATE event
+ * @txrate_level: new TX RATE level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a average of attempted frame txrate crossed
+ * above configured high txrate or below configured low txrate event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_txrate_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+   u32 txrate_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 31680d6..6701961 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15576,6 +15576,42 @@ void cfg80211_sta_mon_rssi_notify(struct net_device 
*dev, const u8 *peer,
 }
 EXPORT_SYMBOL(cfg80211_sta_mon_rssi_notify);
 
+void
+cfg80211_sta_mon_txrate_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+   u32 txrate_level, gfp_t gfp)
+{
+   struct sk_buff *msg;
+
+   trace_cfg80211_sta_mon_txrate_notify(dev, peer, txrate_event,
+txrate_level);
+
+   if (WARN_ON(txrate_event !=
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW &&
+   txrate_event !=
+   NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH))
+   return;
+
+   msg = cfg80211_prepare_sta_mon(dev, peer, gfp);
+   if (!msg)
+   return;
+
+   if (nla_put_u32(msg, NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT,
+   txrate_event))
+   goto nla_put_failure;
+
+   if (txrate_level && nla_put_u32(msg, NL80211_ATTR_STA_MON_TXRATE_LEVEL,
+   txrate_level))
+   goto nla_put_failure;
+
+   cfg80211_send_sta_mon(msg, gfp);
+
+   return;
+nla_put_failure:
+   nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_sta_mon_txrate_notify);
+
 static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
 struct net_device *netdev,
 struct cfg80211_chan_def *chandef,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index ca985c2..95f4a31 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -3355,6 +3355,31 @@
  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer),
  __entry->low_txrate_thold, __entry->high_txrate_thold)
 );
+
+TRACE_EVENT(cfg80211_sta_mon_txrate_notify,
+   TP_PROTO(struct net_device *netdev, const u8 *peer,
+enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+u32 txrate_level),
+   TP_ARGS(netdev, peer, txrate_event, txrate_level),
+   TP_STRUCT__entry(
+   NETDEV_ENTRY
+   MAC_ENTRY(peer)
+   __field(enum nl80211_sta_mon_txrate_threshold_event,
+   txrate_event)
+   __field(u32, txrate_level)
+   ),
+   TP_fast_assign(
+   NETDEV_ASSIGN;
+   MAC_ASSIGN(peer, peer);
+   __entry->txrate_event = txrate_event;
+   __entry->txrate_level = txrate_level;
+   ),
+   TP_printk(NETDEV_PR_FMT ", peer: " MAC_PR_FMT
+ ", tx_rate event: %d, txrate : %u",
+ NETDEV_PR_ARG, MAC_PR_ARG(peer),
+ __entry->txrate_event, __entry->txrate_level)
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
-- 
1.9.1



[RFCv3 0/4] cfg80211/mac80211: Add support to configure and monitor txrate threshold

2018-05-30 Thread Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring txrate threshold for the connected stations and api to
notify userspace application upon crossing the configured txrate threshold.
This will be useful for the application which requires
station's current capability change information.

Tamizh chelvam (4):
  cfg80211: Add support to configure station specific txrate threshold
  mac80211: Add api to configure low and high txrate threshold
  cfg80211: Add support to notify station's txrate crossing event
  mac80211: Implement functionality to monitor txrate cross event for a
station

Note:
  * This patch rebased on top of below patchset
[RFCv3 0/7] cfg80211/mac80211: Add support to configure and monitor rssi 
threshold

v3:
  * splitted txrate patchsets as a different patchsets.

v2:
  * fixed kbuild warnings
  * updated commit log

 include/net/cfg80211.h   | 26 +++
 include/net/mac80211.h   |  5 +++
 include/uapi/linux/nl80211.h | 34 
 net/mac80211/cfg.c   | 36 +
 net/mac80211/sta_info.h  | 17 ++
 net/mac80211/status.c| 40 ++-
 net/wireless/nl80211.c   | 76 
 net/wireless/rdev-ops.h  | 17 ++
 net/wireless/trace.h | 50 +
 9 files changed, 300 insertions(+), 1 deletion(-)

-- 
1.9.1



[RFCv3 7/7] mac80211: Add api to configure low and high RSSI threshold

2018-05-30 Thread Tamizh chelvam
Add set_sta_mon_rssi_range_config api to support
configuring low and high RSSI threshold values
for a connected station. And trigger an event if a
station's signal strength goes out of configured
range.

Signed-off-by: Tamizh chelvam 
---
 net/mac80211/cfg.c  | 40 
 net/mac80211/rx.c   | 23 +++
 net/mac80211/sta_info.h |  6 ++
 3 files changed, 69 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 80ced50..5cdd8a3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3831,12 +3831,51 @@ static int ieee80211_set_sta_mon_rssi_config(struct 
wiphy *wiphy,
 
sta->rssi_thold = rssi_thold;
sta->rssi_hyst = rssi_hyst;
+   sta->rssi_low = 0;
+   sta->rssi_high = 0;
sta->last_sta_mon_event_signal = 0;
 unlock:
mutex_unlock(>local->sta_mtx);
return 0;
 }
 
+static int ieee80211_set_sta_mon_rssi_range_cfg(struct wiphy *wiphy,
+   struct net_device *dev,
+   const u8 *peer,
+   s32 rssi_low, s32 rssi_high)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+NL80211_EXT_FEATURE_STA_MON_RSSI_LIST)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_low == rssi_low &&
+   sta->rssi_high == rssi_high)
+   goto unlock;
+
+   sta->rssi_thold = 0;
+   sta->rssi_hyst = 0;
+   sta->rssi_low = rssi_low;
+   sta->rssi_high = rssi_high;
+   sta->last_sta_mon_event_signal = 0;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3932,4 +3971,5 @@ static int ieee80211_set_sta_mon_rssi_config(struct wiphy 
*wiphy,
.tx_control_port = ieee80211_tx_control_port,
.get_txq_stats = ieee80211_get_txq_stats,
.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
+   .set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_cfg,
 };
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 06a6111..fddb5c6 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1569,6 +1569,29 @@ static void ieee80211_sta_rx_signal_thold_check(struct 
ieee80211_rx_data *rx)
sig, GFP_ATOMIC);
}
}
+
+   if (sta->rssi_low) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+   int low = sta->rssi_low;
+   int high = sta->rssi_high;
+
+   if (sig < low &&
+   (last_event == 0 || last_event >= low)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > high &&
+  (last_event == 0 || last_event <= high)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
 }
 
 static ieee80211_rx_result debug_noinline
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index e130f6d..05d68f8 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -487,6 +487,10 @@ struct ieee80211_sta_rx_stats {
  * should cause an event to be sent indicating where the current value
  * is in relation to the newly configured threshold
  * @rssi_hyst: Station's RSSI hysteresis
+ * @rssi_low: RSSI lower threshold to monitor station's signal strength, a zero
+ * value implies disabled.  This is an alternative mechanism to the single
+ * threshold event and can't be enabled simultaneously with it
+ * @rssi_high: RSSI upper threshold for station
  * @last_sta_mon_event_signal: Last signal strength average for a station
  * that triggered a sta_mon event. 0

[RFCv3 2/7] cfg80211: Add new NL command to configure peer specific rssi threshold

2018-05-30 Thread Tamizh chelvam
This patch add support to configure peer specific rssi configuration
to monitor station's signal strength variation.
New NL80211_CMD_SET_STA_MON introduced to configure rssi threshold
and hysteresis info using NL80211_ATTR_STA_MON_RSSI_THOLD and
NL80211_ATTR_STA_MON_RSSI_HYST along with NL80211_ATTR_MAC.
Driver supporting this configuration should advertise
NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG.
Monitoring station's signal strength variation will be useful
for the application like steering.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |  9 ++
 include/uapi/linux/nl80211.h | 55 +++
 net/wireless/nl80211.c   | 77 
 net/wireless/rdev-ops.h  | 16 +
 net/wireless/trace.h | 25 ++
 5 files changed, 182 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 656031e..8e4c7db 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3024,6 +3024,11 @@ struct cfg80211_external_auth_params {
  *
  * @tx_control_port: TX a control port frame (EAPoL).  The noencrypt parameter
  * tells the driver that the frame should not be encrypted.
+ * @set_sta_mon_rssi_config: Configure  RSSI threshold for a station.
+ * After configuration, the driver should (soon) send an event indicating
+ * the current level of a station is above/below the configured threshold;
+ * this may need some care when the configuration is changed
+ * (without first being disabled.)
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3329,6 +3334,10 @@ struct cfg80211_ops {
   const u8 *buf, size_t len,
   const u8 *dest, const __be16 proto,
   const bool noencrypt);
+   int (*set_sta_mon_rssi_config)(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *addr,
+  s32 rssi_thold, u32 rssi_hyst);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 28b3654..f13ad07 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1033,6 +1033,9 @@
  * _ATTR_CHANNEL_WIDTH,_ATTR_NSS attributes with its
  * address(specified in _ATTR_MAC).
  *
+ * @NL80211_CMD_SET_STA_MON: This command is used to configure station's
+ * connection monitoring notification trigger levels.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1245,6 +1248,8 @@ enum nl80211_commands {
 
NL80211_CMD_CONTROL_PORT_FRAME,
 
+   NL80211_CMD_SET_STA_MON,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -2238,6 +2243,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes
  *  a flow is assigned on each round of the DRR scheduler.
  *
+ * @NL80211_ATTR_STA_MON: Station's connection monitor configuration in a
+ * nested attribute with %NL80211_ATTR_STA_MON_* sub-attributes.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2677,6 +2685,8 @@ enum nl80211_attrs {
NL80211_ATTR_TXQ_MEMORY_LIMIT,
NL80211_ATTR_TXQ_QUANTUM,
 
+   NL80211_ATTR_STA_MON,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
@@ -4276,6 +4286,46 @@ enum nl80211_ps_state {
 };
 
 /**
+ * enum nl80211_attr_sta_mon - Attributes to monitor station's connection
+ * @NL80211_ATTR_STA_MON_RSSI_THOLD: RSSI threshold in dBm. This value 
specifies
+ * the threshold for the RSSI level at which an event will be sent. Zero
+ * to disable.  Alternatively, if %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST is
+ * set, multiple values can be supplied as a low-to-high sorted array of\
+ * threshold values in dBm.  Events will be sent when the RSSI value
+ * crosses any of the thresholds. This threshold values are station
+ * specific.
+ * @NL80211_ATTR_STA_MON_RSSI_HYST: RSSI hysteresis in dBm. This value 
specifies
+ * the minimum amount the RSSI level must change after an event before a
+ * new event may be issued (to reduce effects of RSSI oscillation).
+ * @NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT: RSSI threshold event
+ * @NL80211_ATTR_STA_MON_RSSI_LEVEL: the RSSI value in dBm that triggered the
+ * RSSI threshold event.
+ */
+enum nl80211_attr_sta_mon {
+   __NL80211_ATTR_STA_MON_INVALID,
+   NL80211_ATTR_STA_MON_RSSI_THOLD,
+   NL80211_ATTR_STA_MON_RSSI_HYST,
+   NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
+   NL80211_ATTR_STA_MON_RSSI_LEVEL,
+
+   /* keep last

[RFCv3 3/7] mac80211: Add api to support configuring station specific rssi threshold

2018-05-30 Thread Tamizh chelvam
This patch add set_sta_mon_rssi_config api to configure rssi and
hysteresis threshold value for a connected station. This configuration
will be applied only for the connected station.

Signed-off-by: Tamizh chelvam 
---
 net/mac80211/cfg.c  | 35 +++
 net/mac80211/sta_info.h | 12 
 2 files changed, 47 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bdf6fa7..80ced50 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3803,6 +3803,40 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
return ret;
 }
 
+static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *peer, s32 rssi_thold,
+u32 rssi_hyst)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+!wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_thold == rssi_thold &&
+   sta->rssi_hyst == rssi_hyst)
+   goto unlock;
+
+   sta->rssi_thold = rssi_thold;
+   sta->rssi_hyst = rssi_hyst;
+   sta->last_sta_mon_event_signal = 0;
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3897,4 +3931,5 @@ static int ieee80211_get_txq_stats(struct wiphy *wiphy,
.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
.tx_control_port = ieee80211_tx_control_port,
.get_txq_stats = ieee80211_get_txq_stats,
+   .set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 81b35f6..8c459a7 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -482,6 +482,14 @@ struct ieee80211_sta_rx_stats {
  * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
  * this (by advertising the USES_RSS hw flag)
  * @status_stats: TX status statistics
+ * @rssi_thold: RSSI threshold to monitor station's signal strength, a zero
+ * value implies disabled. As with the cfg80211 callback, a change here
+ * should cause an event to be sent indicating where the current value
+ * is in relation to the newly configured threshold
+ * @rssi_hyst: Station's RSSI hysteresis
+ * @last_sta_mon_event_signal: Last signal strength average for a station
+ * that triggered a sta_mon event. 0 indicates that no event has been
+ * generated for the current association
  */
 struct sta_info {
/* General information, mostly static */
@@ -583,6 +591,10 @@ struct sta_info {
 
struct cfg80211_chan_def tdls_chandef;
 
+   s32 rssi_thold;
+   u32 rssi_hyst;
+   int last_sta_mon_event_signal;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.9.1



[RFCv3 4/7] cfg80211: Add support to notify station's rssi level crossing

2018-05-30 Thread Tamizh chelvam
Add cfg80211_sta_mon_rssi_notify api to update user space upon
crossing the configured rssi threshold of a station.
NL80211_CMD_NOTIFY_STA_MON introduced to send this event to
userspace along with NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
NL80211_ATTR_MAC and NL80211_ATTR_STA_MON_RSSI_LEVEL info.
Userspace application can make a decision depends on this
notification.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   | 16 
 include/uapi/linux/nl80211.h |  1 +
 net/wireless/nl80211.c   | 98 
 net/wireless/trace.h | 22 ++
 4 files changed, 137 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8e4c7db..494d47f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5915,6 +5915,22 @@ void cfg80211_cqm_txe_notify(struct net_device *dev, 
const u8 *peer,
 void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_rssi_notify - Station's rssi out of range event
+ * @dev: network device
+ * @peer: Station's mac address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured rssi threshold reached event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_rssi_threshold_event rssi_event,
+   s32 rssi_level, gfp_t gfp);
+
+/**
  * cfg80211_radar_event - radar detection event
  * @wiphy: the wiphy
  * @chandef: chandef for the current channel
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f13ad07..9d47ee6 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1249,6 +1249,7 @@ enum nl80211_commands {
NL80211_CMD_CONTROL_PORT_FRAME,
 
NL80211_CMD_SET_STA_MON,
+   NL80211_CMD_NOTIFY_STA_MON,
 
/* add new commands above here */
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 587a5cb1..021e55a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -15364,6 +15364,104 @@ void cfg80211_pmksa_candidate_notify(struct 
net_device *dev, int index,
 }
 EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
 
+static struct sk_buff *cfg80211_prepare_sta_mon(struct net_device *dev,
+   const char *mac, gfp_t gfp)
+{
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+   struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+   struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+   void **cb;
+
+   if (!msg)
+   return NULL;
+
+   cb = (void **)msg->cb;
+
+   cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_STA_MON);
+   if (!cb[0]) {
+   nlmsg_free(msg);
+   return NULL;
+   }
+
+   if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+   nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
+   goto nla_put_failure;
+
+   if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
+   goto nla_put_failure;
+
+   cb[1] = nla_nest_start(msg, NL80211_ATTR_STA_MON);
+   if (!cb[1])
+   goto nla_put_failure;
+
+   cb[2] = rdev;
+
+   return msg;
+nla_put_failure:
+   nlmsg_free(msg);
+   return NULL;
+}
+
+static void cfg80211_send_sta_mon(struct sk_buff *msg, gfp_t gfp)
+{
+   void **cb = (void **)msg->cb;
+   struct cfg80211_registered_device *rdev = cb[2];
+
+   nla_nest_end(msg, cb[1]);
+   genlmsg_end(msg, cb[0]);
+
+   memset(msg->cb, 0, sizeof(msg->cb));
+
+   genlmsg_multicast_netns(_fam, wiphy_net(>wiphy), msg, 0,
+   NL80211_MCGRP_MLME, gfp);
+}
+
+void cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_rssi_threshold_event rssi_event,
+   s32 rssi_level, gfp_t gfp)
+{
+   struct sk_buff *msg;
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+   struct cfg80211_rssi_config *rssi_config;
+
+   if (WARN_ON(!peer))
+   return;
+
+   if (WARN_ON(rssi_event != NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW &&
+   rssi_event != NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH))
+   return;
+
+   trace_cfg80211_sta_mon_rssi_notify(dev, peer, rssi_event, rssi_level);
+
+   list_for_each_entry(rssi_config, >rssi_config_list, list) {
+   if (!memcmp(rssi_config->addr, peer, ETH_ALEN)) {
+   wdev->rssi_config = rssi_config;
+   wdev->rssi_config->last_rssi_event_value = rssi_level;
+   break;
+   }
+   }
+
+   msg = cfg80211_prepare_sta_mon(dev, peer, gfp);
+   if (!msg)

[RFCv3 6/7] cfg80211: Accept multiple RSSI threholds for STA_MON command

2018-05-30 Thread Tamizh chelvam
Change the NL80211_CMD_STA_MON RSSI threshold attribut to
accept any number of thresholds as a sorted array. If
user send the configuration with single RSSI threshold then
the old mechanism is enabled. Same netlink event will be
generated in both cases. This patch introduced
set_sta_mon_rssi_range_config to configure high and low
value.
Driver supporting this feature should advertise
NL80211_EXT_FEATURE_STA_MON_RSSI_LIST.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h   |  10 +++
 include/uapi/linux/nl80211.h |   4 +
 net/wireless/nl80211.c   | 176 ++-
 net/wireless/rdev-ops.h  |  15 
 net/wireless/trace.h |  26 +++
 5 files changed, 180 insertions(+), 51 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 494d47f..ffd1204 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3029,6 +3029,12 @@ struct cfg80211_external_auth_params {
  * the current level of a station is above/below the configured threshold;
  * this may need some care when the configuration is changed
  * (without first being disabled.)
+ * @set_sta_mon_rssi_range_config: Configure two RSSI thresholds in the
+ * station's rssi monitor.  An event is to be sent only when the
+ * signal level of a station is found to be outside the two values.
+ * The driver should advertise %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if
+ * this method is implemented. If it is provided then there's no point
+ * providing @set_sta_mon_rssi_config
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3338,6 +3344,10 @@ struct cfg80211_ops {
   struct net_device *dev,
   const u8 *addr,
   s32 rssi_thold, u32 rssi_hyst);
+   int (*set_sta_mon_rssi_range_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+s32 rssi_low, s32 rssi_high);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9d47ee6..8e2a84b 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -5188,6 +5188,9 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG: With this driver can set
  * rssi threshold using %NL80211_ATTR_STA_MON_RSSI_THOLD attribute
  * for a connected station.
+ * @NL80211_EXT_FEATURE_STA_MON_RSSI_LIST: With this driver the
+ * %NL80211_ATTR_STA_MON_RSSI_THOLD attribute accepts a list of zero or
+ * more RSSI threshold values to monitor rather than exactly one threshold.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5223,6 +5226,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT,
NL80211_EXT_FEATURE_TXQS,
NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_LIST,
 
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 021e55a..c0fccb4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10134,61 +10134,101 @@ static int nl80211_set_cqm_txe(struct genl_info 
*info,
 
 static const struct nla_policy
 nl80211_attr_sta_mon_policy[NL80211_ATTR_STA_MON_MAX + 1] = {
-   [NL80211_ATTR_STA_MON_RSSI_THOLD] = { .type = NLA_U32 },
+   [NL80211_ATTR_STA_MON_RSSI_THOLD] = { .type = NLA_BINARY },
[NL80211_ATTR_STA_MON_RSSI_HYST] = { .type = NLA_U32 },
[NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 },
[NL80211_ATTR_STA_MON_RSSI_LEVEL] = { .type = NLA_S32 },
 };
 
-static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
-   struct net_device *dev)
+static int cfg80211_set_rssi_range(struct cfg80211_registered_device *rdev,
+  struct net_device *dev, const u8 *mac_addr,
+  bool get_last_rssi)
 {
struct wireless_dev *wdev = dev->ieee80211_ptr;
-   s32 last, low, high;
+   s32 low, high, last;
u32 hyst;
-   int i, n;
-   int err;
-
-   /* RSSI reporting disabled? */
-   if (!wdev->rssi_config)
-   return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0);
+   int i, n, err;
 
-   /*
-* Obtain current RSSI value if possible, if not and no RSSI threshold
-* event has been received yet, we should receive an event after a
-* connection is established and enough beacons received to calculate
-* the average.
-*/
-   if (!wdev->rssi_config->last_rssi

[RFCv3 5/7] mac80211: Implement functionality to monitor station's rssi cross event

2018-05-30 Thread Tamizh chelvam
Triggers cfg80211_sta_mon_rssi_notify with the corresponding event when
station signal goes out of configured threshold. It uses rx data signal
to check against rssi threshold configured by the user.
This event will be useful for the application like steering to take
decision on any station depends on its current capability.

Signed-off-by: Tamizh chelvam 
---
 include/net/mac80211.h  |  6 ++
 net/mac80211/rx.c   | 42 +-
 net/mac80211/sta_info.h |  4 
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 851a5e1..96fb9a8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -802,6 +802,12 @@ enum mac80211_rate_control_flags {
IEEE80211_TX_RC_160_MHZ_WIDTH   = BIT(10),
 };
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
 
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 0a38cc1..06a6111 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1534,6 +1534,43 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf = >sdata->vif.bss_conf;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (sta->rssi_thold && bss_conf->enable_beacon) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int thold = sta->rssi_thold;
+   int hyst = sta->rssi_hyst;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+
+   if (sig < thold &&
+   (last_event == 0 || sig < last_event - hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > thold &&
+  (last_event == 0 || sig > last_event + hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1589,6 +1626,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -4030,9 +4068,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
/* statistics part of ieee80211_rx_h_sta_process() */
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
-   if (!fast_rx->uses_rss)
+   if (!fast_rx->uses_rss) {
ewma_signal_add(>rx_stats_avg.signal,
-status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
+   }
}
 
if (status->chains) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 8c459a7..e130f6d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -490,6 +490,9 @@ struct ieee80211_sta_rx_stats {
  * @last_sta_mon_event_signal: Last signal strength average for a station
  * that triggered a sta_mon event. 0 indicates that no event has been
  * generated for the current association
+ * @count_rx_signal: Number of data frames used in averaging station signal.
+ * This can be used to avoid generating less reliable station rssi cross
+ * events that would be based only on couple of received frames
  */
 struct sta_info {
/* General information, mostly static */
@@ -594,6 +597,7 @@ struct sta_info {
s32 rssi_thold;
   

[RFCv3 1/7] wireless: Change single cqm_config to rssi config list

2018-05-30 Thread Tamizh chelvam
This patch changes single cqm_config into mac address based
rssi config list. This way the same structure can be
utilized by AP mode as well.

Signed-off-by: Tamizh chelvam 
---
 include/net/cfg80211.h |  7 +++--
 net/wireless/core.c| 29 
 net/wireless/core.h|  6 ++--
 net/wireless/nl80211.c | 74 +-
 4 files changed, 81 insertions(+), 35 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5fbfe61..656031e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4139,7 +4139,7 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
 struct cfg80211_conn;
 struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
-struct cfg80211_cqm_config;
+struct cfg80211_rssi_config;
 
 /**
  * struct wireless_dev - wireless device state
@@ -4204,7 +4204,7 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
  * @nl_owner_dead: (private) owner socket went away
- * @cqm_config: (private) nl80211 RSSI monitor state
+ * @rssi_config: (private) nl80211 RSSI monitor state
  */
 struct wireless_dev {
struct wiphy *wiphy;
@@ -4275,7 +4275,8 @@ struct wireless_dev {
} wext;
 #endif
 
-   struct cfg80211_cqm_config *cqm_config;
+   struct cfg80211_rssi_config *rssi_config;
+   struct list_head rssi_config_list;
 };
 
 static inline u8 *wdev_address(struct wireless_dev *wdev)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5fe35aa..62e496e 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -994,10 +994,28 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool 
blocked)
 }
 EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev)
+void cfg80211_rssi_config_free(struct wireless_dev *wdev, const u8 *peer)
 {
-   kfree(wdev->cqm_config);
-   wdev->cqm_config = NULL;
+   struct cfg80211_rssi_config *rssi_config, *tmp;
+
+   if (list_empty(>rssi_config_list))
+   goto free;
+
+   list_for_each_entry_safe(rssi_config, tmp, >rssi_config_list,
+list) {
+   if (peer && memcmp(rssi_config->addr, peer, ETH_ALEN))
+   continue;
+
+   list_del(_config->list);
+   kfree(rssi_config);
+   if (list_empty(>rssi_config_list) || peer)
+   goto out;
+   }
+
+free:
+   kfree(wdev->rssi_config);
+out:
+   wdev->rssi_config = NULL;
 }
 
 void cfg80211_unregister_wdev(struct wireless_dev *wdev)
@@ -1027,7 +1045,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
break;
}
 
-   cfg80211_cqm_config_free(wdev);
+   cfg80211_rssi_config_free(wdev, NULL);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
 
@@ -1163,6 +1181,7 @@ static int cfg80211_netdev_notifier_call(struct 
notifier_block *nb,
spin_lock_init(>event_lock);
INIT_LIST_HEAD(>mgmt_registrations);
spin_lock_init(>mgmt_registrations_lock);
+   INIT_LIST_HEAD(>rssi_config_list);
 
/*
 * We get here also when the interface changes network 
namespaces,
@@ -1292,7 +1311,7 @@ static int cfg80211_netdev_notifier_call(struct 
notifier_block *nb,
kzfree(wdev->wext.keys);
 #endif
flush_work(>disconnect_wk);
-   cfg80211_cqm_config_free(wdev);
+   cfg80211_rssi_config_free(wdev, NULL);
}
/*
 * synchronise (so that we won't find this netdev
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 63eb1b5..170a31b 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -260,10 +260,12 @@ struct cfg80211_beacon_registration {
u32 nlportid;
 };
 
-struct cfg80211_cqm_config {
+struct cfg80211_rssi_config {
+   struct list_head list;
u32 rssi_hyst;
s32 last_rssi_event_value;
int n_rssi_thresholds;
+   u8 addr[ETH_ALEN];
s32 rssi_thresholds[0];
 };
 
@@ -514,6 +516,6 @@ void cfg80211_stop_nan(struct cfg80211_registered_device 
*rdev,
 #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; })
 #endif
 
-void cfg80211_cqm_config_free(struct wireless_dev *wdev);
+void cfg80211_rssi_config_free(struct wireless_dev *wdev, const u8 *peer);
 
 #endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 07514ca..2fb2e97 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3200,6 +3200,7 @@ static int nl80211_new_interface(struct sk_buff *skb, 
struct genl_info *info)
spin_lock_init(>event_lock);
INIT_LIST_HEAD(>mgmt_registration

[RFCv3 0/7] cfg80211/mac80211: Add support to configure and monitor rssi threshold

2018-05-30 Thread Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring rssi for the connected stations and api to notify
userspace application upon crossing the configured threshold.
This will be useful for the application which requires
station's current capability change information.

Tamizh chelvam (7):
  wireless: Change single cqm_config to rssi config list
  cfg80211: Add new NL command to configure peer specific rssi threshold
  mac80211: Add api to support configuring station specific rssi
threshold
  cfg80211: Add support to notify station's rssi level crossing
  mac80211: Implement functionality to monitor station's rssi cross
event
  cfg80211: Accept multiple RSSI threholds for STA_MON command
  mac80211: Add api to configure low and high RSSI threshold

v3:
  * splitted single and multiple RSSI threshold changes as different patches

v2:
  * fixed kbuild warnings
  * updated commit log

 include/net/cfg80211.h   |  42 -
 include/net/mac80211.h   |   6 +
 include/uapi/linux/nl80211.h |  60 +++
 net/mac80211/cfg.c   |  75 +
 net/mac80211/rx.c|  65 +++-
 net/mac80211/sta_info.h  |  22 +++
 net/wireless/core.c  |  29 +++-
 net/wireless/core.h  |   6 +-
 net/wireless/nl80211.c   | 377 +--
 net/wireless/rdev-ops.h  |  31 
 net/wireless/trace.h |  73 +
 11 files changed, 723 insertions(+), 63 deletions(-)

-- 
1.9.1



[RFCv2 2/6] mac80211: Add support to configure rssi threshold for AP mode

2018-04-26 Thread Tamizh chelvam
This patch add support to configure station specific single or
multi rssi thresholds using ieee80211_set_sta_mon_rssi_config and
ieee80211_set_sta_mon_rssi_range_confg APIs. This configuration
is used for tracking the connected station's signal strength.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/cfg.c  | 75 +
 net/mac80211/sta_info.h | 18 
 2 files changed, 93 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 85dbaa8..0e2047c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3705,6 +3705,79 @@ static int ieee80211_set_multicast_to_unicast(struct 
wiphy *wiphy,
return 0;
 }
 
+static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *peer, s32 rssi_thold,
+u32 rssi_hyst)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_thold == rssi_thold &&
+   sta->rssi_hyst == rssi_hyst)
+   goto unlock;
+
+   sta->rssi_thold = rssi_thold;
+   sta->rssi_hyst = rssi_hyst;
+   sta->rssi_low = 0;
+   sta->rssi_high = 0;
+   sta->last_sta_mon_event_signal = 0;
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
+static int ieee80211_set_sta_mon_rssi_range_confg(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ s32 rssi_low, s32 rssi_high)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_LIST)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_low == rssi_low &&
+   sta->rssi_high == rssi_high)
+   goto unlock;
+
+   sta->rssi_thold = 0;
+   sta->rssi_hyst = 0;
+   sta->rssi_low = rssi_low;
+   sta->rssi_high = rssi_high;
+   sta->last_sta_mon_event_signal = 0;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3798,4 +3871,6 @@ static int ieee80211_set_multicast_to_unicast(struct 
wiphy *wiphy,
.del_nan_func = ieee80211_del_nan_func,
.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
.tx_control_port = ieee80211_tx_control_port,
+   .set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
+   .set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_confg,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index f64eb86..701eb37 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -481,6 +481,18 @@ struct ieee80211_sta_rx_stats {
  * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
  * this (by advertising the USES_RSS hw flag)
  * @status_stats: TX status statistics
+ * @rssi_thold: RSSI threshold to monitor station's signal strength, a zero
+ * value implies disabled. As with the cfg80211 callback, a change here
+ * should cause an event to be sent indicating where the current value
+ * is in relation to the newly configured threshold
+ * @rssi_hyst: Station's RSSI hysteresis
+ * @rssi_low: RSSI lower threshold to monitor station's signal strength, a zero
+ * value implies disabled.  This is an alternative mechanism to the single
+ * threshold event and can't be enabled simultaneously with it
+ * @rssi_high: RSSI upper threshold for station
+ * @last_sta_mon_event_signal: Last signal strength average for a station
+ * that triggered a sta_mon event. 0 indicates that no event has been
+ *   

[RFCv2 4/6] cfg80211: Add support to configure station specific txrate threshold for AP mode

2018-04-26 Thread Tamizh chelvam
This patch add support to configure station specific txrate threshold
to monitor change in txrate for stations. This will be useful
for the user application like steering to configure and monitor the
change event of txrate for the station.

NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD and NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD
used with NL80211_CMD_STA_MON command to configure the txrate threshold and
the configuration will be represented in 100kbps.

cfg80211_sta_mon_txrate_notify introduce to notify txrate for a station
goes out of range using NL80211_CMD_NOTIFY_STA_MON command.

NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG flag needs to be advertised by the
drvier to allow and monitor txrate threshold configuration.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   | 26 
 include/uapi/linux/nl80211.h | 34 
 net/wireless/nl80211.c   | 74 
 net/wireless/rdev-ops.h  | 17 ++
 net/wireless/trace.h | 49 +
 5 files changed, 200 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7e7a0bf..4456e2e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2984,6 +2984,10 @@ struct cfg80211_external_auth_params {
  * The driver should set %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if this
  * method is implemented. If it is provided then there's no point providing
  * @set_sta_mon_rssi_config.
+ * @set_sta_mon_txrate_config: Configure low and high TXRATE threshold in 
100kbs
+ * for a connected station. The driver should(soon) send an event
+ * indicating the current attempted frame txrate level is above/below the
+ * configured threshold.
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3293,6 +3297,11 @@ struct cfg80211_ops {
 struct net_device *dev,
 const u8 *addr,
 s32 rssi_low, s32 rssi_high);
+   int (*set_sta_mon_txrate_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+u32 low_txrate_thold,
+u32 high_txrate_thold);
 };
 
 /*
@@ -5813,6 +5822,23 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_txrate_notify - txrate event for connected stations
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @txrate_event: the triggered TX RATE event
+ * @txrate_level: new TX RATE level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a average of attempted frame txrate crossed
+ * above configured high txrate or below configured low txrate event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_txrate_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+   u32 txrate_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index fa1fed1..a8b5e3d 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4266,6 +4266,15 @@ enum nl80211_attr_cqm {
  * @NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT: RSSI threshold event
  * @NL80211_ATTR_STA_MON_RSSI_LEVEL: the RSSI value in dBm that triggered the
  * RSSI threshold event.
+ * @NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the low txrate threshold. Event will be sent
+ * if the txrate for a station goes lesser than this threshold.
+ * @NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the upper txrate threshold. Event will be sent
+ * if the txrate for a station goes greater than this threshold.
+ * @NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT: TX_RATE threshold cross event
+ * @NL80211_ATTR_STA_MON_TXRATE_LEVEL: TXRATE for a station in 100kbps that
+ * triggered the TX_RATE threshold cross event.
  */
 enum nl80211_attr_sta_mon {
__NL80211_ATTR_STA_MON_INVALID,
@@ -4273,6 +4282,10 @@ enum nl80211_attr_sta_mon {
NL80211_ATTR_STA_MON_RSSI_HYST,
NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
NL80211_ATTR_STA_MON_RSSI_LEVEL,
+   NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT,
+   NL80211_ATTR_STA_MON_TXRATE_LEVEL,
 
/* keep last */
__NL80211_ATTR_STA_MON_AFTER_LAST,
@@ -

[RFCv2 3/6] mac80211: Implement functionality to monitor station's rssi threshold cross

2018-04-26 Thread Tamizh chelvam
Triggers cfg80211_sta_mon_rssi_notify with the corresponding event when
station signal goes out of configured threshold. It uses rx data signal
to check against rssi threshold configured by the user.
This event will be useful for the application like steering to take
decision on any station depends on its current capability.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h  |  7 ++
 net/mac80211/rx.c   | 65 -
 net/mac80211/sta_info.h |  4 +++
 3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d2279b2..7b3d505 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -803,6 +803,13 @@ enum mac80211_rate_control_flags {
 };
 
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 03102af..d21f5b1 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1536,6 +1536,66 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf = >sdata->vif.bss_conf;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (sta->rssi_thold && bss_conf->enable_beacon) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int thold = sta->rssi_thold;
+   int hyst = sta->rssi_hyst;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+
+   if (sig < thold &&
+   (last_event == 0 || sig < last_event - hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > thold &&
+  (last_event == 0 || sig > last_event + hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
+
+   if (sta->rssi_low) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+   int low = sta->rssi_low;
+   int high = sta->rssi_high;
+
+   if (sig < low &&
+   (last_event == 0 || last_event >= low)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > high &&
+  (last_event == 0 || last_event <= high)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1591,6 +1651,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -4032,9 +4093,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
/* statistics part of ieee80211_rx_h_sta_process() */
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status-&

[RFCv2 1/6] cfg80211: Add support to configure station specific rssi threshold for AP mode

2018-04-26 Thread Tamizh chelvam
This patch add support to configure station specific rssi threshold
to monitor station's signal strength modification. This will be useful
for the user application like steering to configure and monitor the station's
signal strength change event.

New NL80211_CMD_STA_MON command introduced to cofigure single or multi
rssi thresholds using NL80211_ATTR_STA_MON_RSSI_THOLD and
NL80211_ATTR_STA_MON_RSSI_HYST.

cfg80211_sta_mon_rssi_notify introduce to notify station's signal strength
goes out of range using NL80211_CMD_NOTIFY_STA_MON command.

NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG flag needs to be advertised by the
drvier to allow single rssi threshold and hysteresis configuration.
NL80211_EXT_FEATURE_STA_MON_RSSI_LIST needs to be advertised to allow
multi rssi thresholds.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   |  43 -
 include/uapi/linux/nl80211.h |  62 +++
 net/wireless/core.c  |  26 ++-
 net/wireless/core.h  |   6 +-
 net/wireless/nl80211.c   | 388 +--
 net/wireless/rdev-ops.h  |  31 
 net/wireless/trace.h |  74 +
 7 files changed, 567 insertions(+), 63 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 250dac3..7e7a0bf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2973,6 +2973,17 @@ struct cfg80211_external_auth_params {
  *
  * @tx_control_port: TX a control port frame (EAPoL).  The noencrypt parameter
  * tells the driver that the frame should not be encrypted.
+ * @set_sta_mon_rssi_config: Configure  RSSI threshold for a station.
+ * After configuration, the driver should (soon) send an event indicating
+ * the current level of a station is above/below the configured threshold;
+ * this may need some care when the configuration is changed
+ * (without first being disabled.)
+ * @set_sta_mon_rssi_range_config: Configure two RSSI thresholds in the
+ * station's rssi monitor.  An event is to be sent only when the
+ * signal level of a station is found to be outside the two values.
+ * The driver should set %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if this
+ * method is implemented. If it is provided then there's no point providing
+ * @set_sta_mon_rssi_config.
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3274,6 +3285,14 @@ struct cfg80211_ops {
   const u8 *buf, size_t len,
   const u8 *dest, const __be16 proto,
   const bool noencrypt);
+   int (*set_sta_mon_rssi_config)(struct wiphy *wiphy,
+   struct net_device *dev,
+   const u8 *addr,
+   s32 rssi_thold, u32 rssi_hyst);
+   int (*set_sta_mon_rssi_range_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+s32 rssi_low, s32 rssi_high);
 };
 
 /*
@@ -4076,7 +4095,7 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
 struct cfg80211_conn;
 struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
-struct cfg80211_cqm_config;
+struct cfg80211_rssi_config;
 
 /**
  * struct wireless_dev - wireless device state
@@ -4141,7 +4160,8 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
  * @nl_owner_dead: (private) owner socket went away
- * @cqm_config: (private) nl80211 RSSI monitor state
+ * @rssi_config: (private) nl80211 RSSI monitor state
+ * @rssi_config_list: list of peer address based rssi configuration
  */
 struct wireless_dev {
struct wiphy *wiphy;
@@ -4212,7 +4232,8 @@ struct wireless_dev {
} wext;
 #endif
 
-   struct cfg80211_cqm_config *cqm_config;
+   struct cfg80211_rssi_config *rssi_config;
+   struct list_head rssi_config_list;
 };
 
 static inline u8 *wdev_address(struct wireless_dev *wdev)
@@ -5776,6 +5797,22 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
  s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_rssi_notify - Station's rssi out of range event
+ * @dev: network device
+ * @peer: Station's mac address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured rssi threshold reached event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+enum nl80211_sta_mon_rssi_threshold_event rssi_event,
+s32 rssi_level, gfp

[RFCv2 5/6] mac80211: Add support to configure txrate threshold for station

2018-04-26 Thread Tamizh chelvam
This patch add support to configure station specific low and high
txrate thresholds using ieee80211_set_sta_mon_txrate_config API.
This configuration is used for tracking the txrate for connected
stations.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/cfg.c  | 35 +++
 net/mac80211/sta_info.h |  5 +
 2 files changed, 40 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0e2047c..ba2555d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3778,6 +3778,40 @@ static int ieee80211_set_sta_mon_rssi_range_confg(struct 
wiphy *wiphy,
return 0;
 }
 
+static int ieee80211_set_sta_mon_txrate_config(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *peer,
+  u32 low_txrate_thold,
+  u32 high_txrate_thold)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->txrate_low == low_txrate_thold &&
+   sta->txrate_high == high_txrate_thold)
+   goto unlock;
+
+   sta->txrate_low = low_txrate_thold;
+   sta->txrate_high = high_txrate_thold;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3873,4 +3907,5 @@ static int ieee80211_set_sta_mon_rssi_range_confg(struct 
wiphy *wiphy,
.tx_control_port = ieee80211_tx_control_port,
.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
.set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_confg,
+   .set_sta_mon_txrate_config = ieee80211_set_sta_mon_txrate_config,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 1599973..c73d010 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -496,6 +496,8 @@ struct ieee80211_sta_rx_stats {
  * @count_rx_signal: Number of data frames used in averaging station signal.
  * This can be used to avoid generating less reliable station rssi cross
  * events that would be based only on couple of received frames.
+ * @txrate_low: TXRATE lower threshold for a station to monitor
+ * @txrate_high: TXRATE upper threshold for a station to monitor
  */
 struct sta_info {
/* General information, mostly static */
@@ -603,6 +605,9 @@ struct sta_info {
int last_sta_mon_event_signal;
unsigned int count_rx_signal;
 
+   u32 txrate_low;
+   u32 txrate_high;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.9.1



[RFCv2 6/6] mac80211: Implement functionality to monitor txrate cross event for station

2018-04-26 Thread Tamizh chelvam
Trigger cfg80211_sta_mon_txrate_notify with the corresponding txrate
event when the txrate for a station goes out of configured range.
This event will be useful for the application like steering to take
decision on any station depends on its current capability.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h  |  5 +
 net/mac80211/cfg.c  |  1 +
 net/mac80211/sta_info.h | 10 ++
 net/mac80211/status.c   | 40 +++-
 4 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7b3d505..7023f40 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -809,6 +809,11 @@ enum mac80211_rate_control_flags {
  */
 #define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
 
+/* Number of txrate count need to have been used in average station's
+ * txrate before checking against the threshold
+ */
+#define IEEE80211_STA_TXRATE_AVE_MIN_COUNT 4
+
 
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ba2555d..0f06b0b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3806,6 +3806,7 @@ static int ieee80211_set_sta_mon_txrate_config(struct 
wiphy *wiphy,
 
sta->txrate_low = low_txrate_thold;
sta->txrate_high = high_txrate_thold;
+   sta->last_txrate_event = 0;
 
 unlock:
mutex_unlock(>local->sta_mtx);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index c73d010..e23d916 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -418,6 +418,8 @@ struct ieee80211_sta_rx_stats {
  */
 #define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
 
+DECLARE_EWMA(sta_txrate, 4, 4)
+
 /**
  * struct sta_info - STA information
  *
@@ -498,6 +500,11 @@ struct ieee80211_sta_rx_stats {
  * events that would be based only on couple of received frames.
  * @txrate_low: TXRATE lower threshold for a station to monitor
  * @txrate_high: TXRATE upper threshold for a station to monitor
+ * @count_sta_txrate: Number of transmitted data frames used in ave_sta_txrate
+ * @last_txrate_event: Last txrate event that triggered sta_mon event for a
+ * station
+ * @ave_sta_txrate: Average txrate to check against the txrate_low and
+ * txrate_high. Values expressed in 100kbps
  */
 struct sta_info {
/* General information, mostly static */
@@ -608,6 +615,9 @@ struct sta_info {
u32 txrate_low;
u32 txrate_high;
 
+   unsigned int count_sta_txrate;
+   enum nl80211_sta_mon_txrate_threshold_event last_txrate_event;
+   struct ewma_sta_txrate ave_sta_txrate;
/* keep last! */
struct ieee80211_sta sta;
 };
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 743e89c..6656b04 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -699,6 +699,40 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, 
struct sk_buff *skb,
dev_kfree_skb(skb);
 }
 
+static void ieee80211_sta_mon_txrate_thold_check(struct sta_info *sta)
+{
+   struct rate_info rinfo;
+   enum nl80211_sta_mon_txrate_threshold_event sta_txrate_event;
+   int txrate;
+
+   if (!sta->txrate_high)
+   return;
+
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   txrate = cfg80211_calculate_bitrate();
+   ewma_sta_txrate_add(>ave_sta_txrate, txrate);
+   sta->count_sta_txrate++;
+
+   if (sta->count_sta_txrate < IEEE80211_STA_TXRATE_AVE_MIN_COUNT)
+   return;
+
+   txrate = ewma_sta_txrate_read(>ave_sta_txrate);
+
+   if (txrate < sta->txrate_low)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW;
+   else if (txrate > sta->txrate_high)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH;
+   else
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE;
+
+   if (sta_txrate_event != sta->last_txrate_event) {
+   cfg80211_sta_mon_txrate_notify(sta->sdata->dev, sta->addr,
+  sta_txrate_event, txrate,
+  GFP_ATOMIC);
+   sta->last_txrate_event = sta_txrate_event;
+   }
+}
+
 static void __ieee80211_tx_status(struct ieee80211_hw *hw,
  struct ieee80211_tx_status *status)
 {
@@ -748,9 +782,13 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
 
if (ieee80211_hw_check(>hw, HAS_RATE_CONTROL) &&
(ieee80211_is_data(hdr->frame_control)) &&
-   (rates_idx != -1))
+   (rates_idx != -1)) {
sta->tx_stats.last_rate =
  

[RFCv2 0/6] cfg80211/mac80211: Add support to configure and monitor rssi/txrate threshold

2018-04-26 Thread Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring rssi and txrate for the connected stations.
And implemented new api to notify the threshold cross event.
This will be useful/requires for the user application like steering
to monitor station's activity change.

Tamizh chelvam (6):
  cfg80211: Add support to configure station specific rssi threshold for
AP mode
  mac80211: Add support to configure rssi threshold for AP mode
  mac80211: Implement functionality to monitor station's rssi threshold
cross
  cfg80211: Add support to configure station specific txrate threshold
for AP mode
  mac80211: Add support to configure txrate threshold for station
  mac80211: Implement functionality to monitor txrate cross event for
station

v2:
  * fixed kbuild warnings
  * updated commit log

 include/net/cfg80211.h   |  69 ++-
 include/net/mac80211.h   |  12 ++
 include/uapi/linux/nl80211.h |  96 +
 net/mac80211/cfg.c   | 111 +++
 net/mac80211/rx.c|  65 +-
 net/mac80211/sta_info.h  |  37 
 net/mac80211/status.c|  40 +++-
 net/wireless/core.c  |  26 ++-
 net/wireless/core.h  |   6 +-
 net/wireless/nl80211.c   | 462 ++-
 net/wireless/rdev-ops.h  |  48 +
 net/wireless/trace.h | 123 
 12 files changed, 1030 insertions(+), 65 deletions(-)

-- 
1.9.1



[PATCHv3] ath10k: fix kernel panic while reading tpc_stats

2018-04-22 Thread Tamizh chelvam
When attempt to read tpc_stats for the chipsets which support
more than 3 tx chain will trigger kernel panic(kernel stack is corrupted)
due to writing values on rate_code array out of range.
This patch changes the array size depends on the WMI_TPC_TX_N_CHAIN and
added check to avoid write values on the array if the num tx chain
get in tpc config event is greater than WMI_TPC_TX_N_CHAIN.

Tested on QCA9984 with firmware-5.bin_10.4-3.5.3-00057

Kernel panic log :

[  323.510944] Kernel panic - not syncing: stack-protector: Kernel stack is 
corrupted in: bf90c654
[  323.510944]
[  323.524390] CPU: 0 PID: 1908 Comm: cat Not tainted 3.14.77 #31
[  323.530224] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.537941] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.545146] [] (dump_stack) from [] (panic+0x84/0x1e4)
[  323.552000] [] (panic) from [] 
(__stack_chk_fail+0x10/0x14)
[  323.559350] [] (__stack_chk_fail) from [] 
(ath10k_wmi_event_pdev_tpc_config+0x424/0x438 [ath10k_core])
[  323.570471] [] (ath10k_wmi_event_pdev_tpc_config [ath10k_core]) 
from [] (ath10k_wmi_10_4_op_rx+0x2f0/0x39c [ath10k_core])
[  323.583047] [] (ath10k_wmi_10_4_op_rx [ath10k_core]) from 
[] (ath10k_htc_rx_completion_handler+0x170/0x1a0 [ath10k_core])
[  323.595702] [] (ath10k_htc_rx_completion_handler [ath10k_core]) 
from [] (ath10k_pci_hif_send_complete_check+0x1f0/0x220 [ath10k_pci])
[  323.609421] [] (ath10k_pci_hif_send_complete_check [ath10k_pci]) 
from [] (ath10k_ce_per_engine_service+0x74/0xc4 [ath10k_pci])
[  323.622490] [] (ath10k_ce_per_engine_service [ath10k_pci]) from 
[] (ath10k_ce_per_engine_service_any+0x74/0x80 [ath10k_pci])
[  323.635423] [] (ath10k_ce_per_engine_service_any [ath10k_pci]) 
from [] (ath10k_pci_napi_poll+0x44/0xe8 [ath10k_pci])
[  323.647665] [] (ath10k_pci_napi_poll [ath10k_pci]) from 
[] (net_rx_action+0xac/0x160)
[  323.657208] [] (net_rx_action) from [] 
(__do_softirq+0x104/0x294)
[  323.665017] [] (__do_softirq) from [] 
(irq_exit+0x9c/0x11c)
[  323.672314] [] (irq_exit) from [] (handle_IRQ+0x6c/0x90)
[  323.679341] [] (handle_IRQ) from [] 
(gic_handle_irq+0x3c/0x60)
[  323.686893] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)
[  323.694349] Exception stack(0xdd489c58 to 0xdd489ca0)
[  323.699384] 9c40:   
 a013
[  323.707547] 9c60:  dc4bce40 6013 ddc1d800 dd488000 0990 
 c085c800
[  323.715707] 9c80:  dd489d44 092d dd489ca0 c026e664 c026e668 
6013 
[  323.723877] [] (__irq_svc) from [] 
(rcu_note_context_switch+0x170/0x184)
[  323.732298] [] (rcu_note_context_switch) from [] 
(__schedule+0x50/0x4d4)
[  323.740716] [] (__schedule) from [] 
(schedule_timeout+0x148/0x178)
[  323.748611] [] (schedule_timeout) from [] 
(wait_for_common+0x114/0x154)
[  323.756972] [] (wait_for_common) from [] 
(ath10k_tpc_stats_open+0xc8/0x340 [ath10k_core])
[  323.766873] [] (ath10k_tpc_stats_open [ath10k_core]) from 
[] (do_dentry_open+0x1ac/0x274)
[  323.776741] [] (do_dentry_open) from [] 
(do_last+0x8c0/0xb08)
[  323.784201] [] (do_last) from [] 
(path_openat+0x210/0x598)
[  323.791408] [] (path_openat) from [] 
(do_filp_open+0x2c/0x78)
[  323.798873] [] (do_filp_open) from [] 
(do_sys_open+0x114/0x1b4)
[  323.806509] [] (do_sys_open) from [] 
(ret_fast_syscall+0x0/0x44)
[  323.814241] CPU1: stopping
[  323.816927] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.14.77 #31
[  323.823008] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.830731] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.837934] [] (dump_stack) from [] 
(handle_IPI+0xb8/0x140)
[  323.845224] [] (handle_IPI) from [] 
(gic_handle_irq+0x58/0x60)
[  323.852774] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)
[  323.860233] Exception stack(0xdd499fa0 to 0xdd499fe8)
[  323.865273] 9fa0: ffed  1d3c9000  dd498000 dd498030 
10c0387d c08b62c8
[  323.873432] 9fc0: 4220406a 512f04d0   0001 dd499fe8 
c021838c c0218390
[  323.881588] 9fe0: 6013 
[  323.885070] [] (__irq_svc) from [] 
(arch_cpu_idle+0x30/0x50)
[  323.892454] [] (arch_cpu_idle) from [] 
(cpu_startup_entry+0xa4/0x108)
[  323.900690] [] (cpu_startup_entry) from [<422085a4>] (0x422085a4)

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
v3:
  * Fixed kbuild error and removed complete call from wmi event

v2:
  * Removed unnecessary '\n' in the beginning of the format string 

 drivers/net/wireless/ath/ath10k/debug.c | 8 +++-
 drivers/net/wireless/ath/ath10k/wmi.c   | 6 ++
 drivers/net/wireless/ath/ath10k/wmi.h   | 2 +-
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c 
b/drivers/net/wireless/ath/ath10k/debug.c
index bac832c..442a6f3 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1519,7 +1519,13 @@ static void ath10k_tpc_stats_print(struct 
ath10k_tpc_stat

[RFC 3/6] mac80211: implement station's rssi check using rx data signal

2018-04-20 Thread Tamizh chelvam
Triggers cfg80211_sta_mon_rssi_notify with the corresponding event when
station signal goes out of configured threshold. It uses rx data signal
and compare with rssi value given by user. This rssi threshold is
station specific. This event will be useful for the user application
like steering to take decision on the particular station.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h  |  7 ++
 net/mac80211/rx.c   | 65 -
 net/mac80211/sta_info.h |  4 +++
 3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d2279b2..7b3d505 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -803,6 +803,13 @@ enum mac80211_rate_control_flags {
 };
 
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 03102af..d21f5b1 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1536,6 +1536,66 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf = >sdata->vif.bss_conf;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (sta->rssi_thold && bss_conf->enable_beacon) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int thold = sta->rssi_thold;
+   int hyst = sta->rssi_hyst;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+
+   if (sig < thold &&
+   (last_event == 0 || sig < last_event - hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > thold &&
+  (last_event == 0 || sig > last_event + hyst)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
+
+   if (sta->rssi_low) {
+   int last_event = sta->last_sta_mon_event_signal;
+   int sig = -ewma_signal_read(>rx_stats_avg.signal);
+   int low = sta->rssi_low;
+   int high = sta->rssi_high;
+
+   if (sig < low &&
+   (last_event == 0 || last_event >= low)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   } else if (sig > high &&
+  (last_event == 0 || last_event <= high)) {
+   sta->last_sta_mon_event_signal = sig;
+   cfg80211_sta_mon_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   }
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1591,6 +1651,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -4032,9 +4093,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
/* statistics part of ieee80211_rx_h_sta_process() */
if (!(status->flag & RX_FLAG_NO_SIGNAL

[RFC 4/6] cfg80211: Add support to config station tx rate threshold

2018-04-20 Thread Tamizh chelvam
This patch adds support for txrate configuration to monitor
station's current txrate strength. This will be useful for
the application like steering, which monitors/requires
station's txrate crossing event. Driver should advertise
NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG to enable this
feature. User will set the values in 100kbps using
NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD and
NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD. And
cfg80211_sta_mon_txrate_notify api introduced to notify
the txrate cross event using NL80211_CMD_NOTIFY_STA_MON.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   | 26 
 include/uapi/linux/nl80211.h | 34 
 net/wireless/nl80211.c   | 74 
 net/wireless/rdev-ops.h  | 17 ++
 net/wireless/trace.h | 49 +
 5 files changed, 200 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2f18794..e934742 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2984,6 +2984,10 @@ struct cfg80211_external_auth_params {
  * The driver should set %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if this
  * method is implemented. If it is provided then there's no point providing
  * @set_sta_mon_rssi_config.
+ * @set_sta_mon_txrate_config: Configure low and high TXRATE threshold in 
100kbs
+ * for a connected station. The driver should(soon) send an event
+ * indicating the current attempted frame txrate level is above/below the
+ * configured threshold.
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3293,6 +3297,11 @@ struct cfg80211_ops {
 struct net_device *dev,
 const u8 *addr,
 s32 rssi_low, s32 rssi_high);
+   int (*set_sta_mon_txrate_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+u32 low_txrate_thold,
+u32 high_txrate_thold);
 };
 
 /*
@@ -5812,6 +5821,23 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
 s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_txrate_notify - txrate event for connected stations
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @txrate_event: the triggered TX RATE event
+ * @txrate_level: new TX RATE level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a average of attempted frame txrate crossed
+ * above configured high txrate or below configured low txrate event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_txrate_notify(struct net_device *dev, const u8 *peer,
+   enum nl80211_sta_mon_txrate_threshold_event txrate_event,
+   u32 txrate_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 78a019c..120dfb9 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4263,6 +4263,15 @@ enum nl80211_attr_cqm {
  * @NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT: RSSI threshold event
  * @NL80211_ATTR_STA_MON_RSSI_LEVEL: the RSSI value in dBm that triggered the
  * RSSI threshold event.
+ * @NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the low txrate threshold. Event will be sent
+ * if the station's txrate goes lesser than this threshold.
+ * @NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD: TX_RATE threshold in 100kbps. This
+ * u32 attribute specifies the upper txrate threshold. Event will be sent
+ * if the station's txrate goes greater than this threshold.
+ * @NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT: TX_RATE threshold cross event
+ * @NL80211_ATTR_STA_MON_TXRATE_LEVEL: Station's tx rate value in 100kbps that
+ * triggered the TX_RATE threshold cross event.
  */
 enum nl80211_attr_sta_mon {
__NL80211_ATTR_STA_MON_INVALID,
@@ -4270,6 +4279,10 @@ enum nl80211_attr_sta_mon {
NL80211_ATTR_STA_MON_RSSI_HYST,
NL80211_ATTR_STA_MON_RSSI_THRESHOLD_EVENT,
NL80211_ATTR_STA_MON_RSSI_LEVEL,
+   NL80211_ATTR_STA_MON_LOW_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_HIGH_TXRATE_THOLD,
+   NL80211_ATTR_STA_MON_TXRATE_THRESHOLD_EVENT,
+   NL80211_ATTR_STA_MON_TXRATE_LEVEL,
 
/* keep last */
__NL80211_ATTR_STA_MON_AFTER_LAST,
@@ -4302,6 +4315,21 @@ enum nl80211_sta_mon_rssi_threshold_event {
NL80211_STA_MON_RSSI_THRESHOLD_EVENT_HIGH,
 };
 
+/**
+ * enum nl80211_sta_mon_txrate_threshold_event - TX_RATE thr

[RFC 0/6] cfg80211/mac80211: enable rssi/txrate threshold config for AP mode

2018-04-20 Thread Tamizh chelvam
This patchsets introduced new NL command and api to support
configuring rssi and txrate for the connected stations.
And implemented new api to notify the threshold cross event.
This will be useful/requires for the user application like steering
to monitor station's activity change.

Tamizh chelvam (6):
  cfg80211: enable setting rssi threshold config for AP mode
  mac80211: enable setting rssi threshold config for AP mode
  mac80211: implement station's rssi check using rx data signal
  cfg80211: Add support to config station tx rate threshold
  mac80211: Add support to configure txrate threshold for station
  mac80211: Implement cqm txrate range check for a station

 include/net/cfg80211.h   |  68 ++-
 include/net/mac80211.h   |  12 ++
 include/uapi/linux/nl80211.h |  95 +
 net/mac80211/cfg.c   | 111 +++
 net/mac80211/rx.c|  65 +-
 net/mac80211/sta_info.h  |  32 +++
 net/mac80211/status.c|  40 +++-
 net/wireless/core.c  |  26 ++-
 net/wireless/core.h  |   6 +-
 net/wireless/nl80211.c   | 462 ++-
 net/wireless/rdev-ops.h  |  48 +
 net/wireless/trace.h | 123 
 12 files changed, 1023 insertions(+), 65 deletions(-)

-- 
1.9.1



[RFC 1/6] cfg80211: enable setting rssi threshold config for AP mode

2018-04-20 Thread Tamizh chelvam
This patch enables setting rssi threshold configuration for
connected stations. This will be useful for the user application
like steering to set and monitor the stations rssi threshold change
value. New NL80211_CMD_STA_MON command introduced to set this
configuration using NL80211_ATTR_STA_MON_RSSI_THOLD and
NL80211_ATTR_STA_MON_RSSI_HYST. And introduce new api
to notify station's rssi goes out of range using
NL80211_CMD_NOTIFY_STA_MON command.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   |  42 -
 include/uapi/linux/nl80211.h |  61 +++
 net/wireless/core.c  |  26 ++-
 net/wireless/core.h  |   6 +-
 net/wireless/nl80211.c   | 388 +--
 net/wireless/rdev-ops.h  |  31 
 net/wireless/trace.h |  74 +
 7 files changed, 565 insertions(+), 63 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 250dac3..2f18794 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2973,6 +2973,17 @@ struct cfg80211_external_auth_params {
  *
  * @tx_control_port: TX a control port frame (EAPoL).  The noencrypt parameter
  * tells the driver that the frame should not be encrypted.
+ * @set_sta_mon_rssi_config: Configure  RSSI threshold for a station.
+ * After configuration, the driver should (soon) send an event indicating
+ * the current level of a station is above/below the configured threshold;
+ * this may need some care when the configuration is changed
+ * (without first being disabled.)
+ * @set_sta_mon_rssi_range_config: Configure two RSSI thresholds in the
+ * station's rssi monitor.  An event is to be sent only when the
+ * signal level of a station is found to be outside the two values.
+ * The driver should set %NL80211_EXT_FEATURE_STA_MON_RSSI_LIST if this
+ * method is implemented. If it is provided then there's no point providing
+ * @set_sta_mon_rssi_config.
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3274,6 +3285,14 @@ struct cfg80211_ops {
   const u8 *buf, size_t len,
   const u8 *dest, const __be16 proto,
   const bool noencrypt);
+   int (*set_sta_mon_rssi_config)(struct wiphy *wiphy,
+   struct net_device *dev,
+   const u8 *addr,
+   s32 rssi_thold, u32 rssi_hyst);
+   int (*set_sta_mon_rssi_range_config)(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *addr,
+s32 rssi_low, s32 rssi_high);
 };
 
 /*
@@ -4076,7 +4095,7 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
 struct cfg80211_conn;
 struct cfg80211_internal_bss;
 struct cfg80211_cached_keys;
-struct cfg80211_cqm_config;
+struct cfg80211_rssi_config;
 
 /**
  * struct wireless_dev - wireless device state
@@ -4141,7 +4160,7 @@ static inline struct wiphy *wiphy_new(const struct 
cfg80211_ops *ops,
  * @event_lock: (private) lock for event list
  * @owner_nlportid: (private) owner socket port ID
  * @nl_owner_dead: (private) owner socket went away
- * @cqm_config: (private) nl80211 RSSI monitor state
+ * @rssi_config: (private) nl80211 RSSI monitor state
  */
 struct wireless_dev {
struct wiphy *wiphy;
@@ -4212,7 +4231,8 @@ struct wireless_dev {
} wext;
 #endif
 
-   struct cfg80211_cqm_config *cqm_config;
+   struct cfg80211_rssi_config *rssi_config;
+   struct list_head rssi_config_list;
 };
 
 static inline u8 *wdev_address(struct wireless_dev *wdev)
@@ -5776,6 +5796,22 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
  s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_sta_mon_rssi_notify - Station's rssi out of range event
+ * @dev: network device
+ * @peer: Station's mac address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured rssi threshold reached event
+ * occurs for a station.
+ */
+void
+cfg80211_sta_mon_rssi_notify(struct net_device *dev, const u8 *peer,
+enum nl80211_sta_mon_rssi_threshold_event rssi_event,
+s32 rssi_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 15daf5e..78a019c 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1029,6 +1029,11 @@
  * ht opmode or vht opmode changes using any of _ATTR_SMP

[RFC 2/6] mac80211: enable setting rssi threshold config for AP mode

2018-04-20 Thread Tamizh chelvam
This patch introduce new api to set rssi single or low/high rssi
threshold value to track the connected stations signal strength.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/cfg.c  | 75 +
 net/mac80211/sta_info.h | 18 
 2 files changed, 93 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 85dbaa8..0e2047c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3705,6 +3705,79 @@ static int ieee80211_set_multicast_to_unicast(struct 
wiphy *wiphy,
return 0;
 }
 
+static int ieee80211_set_sta_mon_rssi_config(struct wiphy *wiphy,
+struct net_device *dev,
+const u8 *peer, s32 rssi_thold,
+u32 rssi_hyst)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_CONFIG)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_thold == rssi_thold &&
+   sta->rssi_hyst == rssi_hyst)
+   goto unlock;
+
+   sta->rssi_thold = rssi_thold;
+   sta->rssi_hyst = rssi_hyst;
+   sta->rssi_low = 0;
+   sta->rssi_high = 0;
+   sta->last_sta_mon_event_signal = 0;
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
+static int ieee80211_set_sta_mon_rssi_range_confg(struct wiphy *wiphy,
+ struct net_device *dev,
+ const u8 *peer,
+ s32 rssi_low, s32 rssi_high)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_RSSI_LIST)))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->rssi_low == rssi_low &&
+   sta->rssi_high == rssi_high)
+   goto unlock;
+
+   sta->rssi_thold = 0;
+   sta->rssi_hyst = 0;
+   sta->rssi_low = rssi_low;
+   sta->rssi_high = rssi_high;
+   sta->last_sta_mon_event_signal = 0;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3798,4 +3871,6 @@ static int ieee80211_set_multicast_to_unicast(struct 
wiphy *wiphy,
.del_nan_func = ieee80211_del_nan_func,
.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
.tx_control_port = ieee80211_tx_control_port,
+   .set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
+   .set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_confg,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index f64eb86..701eb37 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -481,6 +481,18 @@ struct ieee80211_sta_rx_stats {
  * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
  * this (by advertising the USES_RSS hw flag)
  * @status_stats: TX status statistics
+ * @rssi_thold: RSSI threshold to monitor station's signal strength, a zero
+ * value implies disabled. As with the cfg80211 callback, a change here
+ * should cause an event to be sent indicating where the current value
+ * is in relation to the newly configured threshold
+ * @rssi_hyst: Station's RSSI hysteresis
+ * @rssi_low: RSSI lower threshold to monitor station's signal strength, a zero
+ * value implies disabled.  This is an alternative mechanism to the single
+ * threshold event and can't be enabled simultaneously with it
+ * @rssi_high: RSSI upper threshold for station
+ * @last_sta_mon_event_signal: Last signal strength average for a station
+ * that triggered a sta_mon event. 0 indicates that no event has been
+ * generated for the current association
  */
 struct sta_info {
/* General information, mostly static */
@@ -581,

[RFC 6/6] mac80211: Implement cqm txrate range check for a station

2018-04-20 Thread Tamizh chelvam
This patch trigger cfg80211_sta_mon_txrate_notify with
the corresponding txrate event when the txrate for a station goes
out of configured range.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h  |  5 +
 net/mac80211/sta_info.h |  5 +
 net/mac80211/status.c   | 40 +++-
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7b3d505..7023f40 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -809,6 +809,11 @@ enum mac80211_rate_control_flags {
  */
 #define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
 
+/* Number of txrate count need to have been used in average station's
+ * txrate before checking against the threshold
+ */
+#define IEEE80211_STA_TXRATE_AVE_MIN_COUNT 4
+
 
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 14431c7..271267d 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -418,6 +418,8 @@ struct ieee80211_sta_rx_stats {
  */
 #define STA_SLOW_THRESHOLD 6000 /* 6 Mbps */
 
+DECLARE_EWMA(sta_txrate, 4, 4)
+
 /**
  * struct sta_info - STA information
  *
@@ -608,6 +610,9 @@ struct sta_info {
u32 txrate_low;
u32 txrate_high;
 
+   unsigned int count_sta_txrate;
+   enum nl80211_sta_mon_txrate_threshold_event last_txrate_event;
+   struct ewma_sta_txrate ave_sta_txrate;
/* keep last! */
struct ieee80211_sta sta;
 };
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 743e89c..6656b04 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -699,6 +699,40 @@ void ieee80211_tx_monitor(struct ieee80211_local *local, 
struct sk_buff *skb,
dev_kfree_skb(skb);
 }
 
+static void ieee80211_sta_mon_txrate_thold_check(struct sta_info *sta)
+{
+   struct rate_info rinfo;
+   enum nl80211_sta_mon_txrate_threshold_event sta_txrate_event;
+   int txrate;
+
+   if (!sta->txrate_high)
+   return;
+
+   sta_set_rate_info_tx(sta, >tx_stats.last_rate, );
+   txrate = cfg80211_calculate_bitrate();
+   ewma_sta_txrate_add(>ave_sta_txrate, txrate);
+   sta->count_sta_txrate++;
+
+   if (sta->count_sta_txrate < IEEE80211_STA_TXRATE_AVE_MIN_COUNT)
+   return;
+
+   txrate = ewma_sta_txrate_read(>ave_sta_txrate);
+
+   if (txrate < sta->txrate_low)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_LOW;
+   else if (txrate > sta->txrate_high)
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_EVENT_HIGH;
+   else
+   sta_txrate_event = NL80211_STA_MON_TXRATE_THRESHOLD_IN_RANGE;
+
+   if (sta_txrate_event != sta->last_txrate_event) {
+   cfg80211_sta_mon_txrate_notify(sta->sdata->dev, sta->addr,
+  sta_txrate_event, txrate,
+  GFP_ATOMIC);
+   sta->last_txrate_event = sta_txrate_event;
+   }
+}
+
 static void __ieee80211_tx_status(struct ieee80211_hw *hw,
  struct ieee80211_tx_status *status)
 {
@@ -748,9 +782,13 @@ static void __ieee80211_tx_status(struct ieee80211_hw *hw,
 
if (ieee80211_hw_check(>hw, HAS_RATE_CONTROL) &&
(ieee80211_is_data(hdr->frame_control)) &&
-   (rates_idx != -1))
+   (rates_idx != -1)) {
sta->tx_stats.last_rate =
info->status.rates[rates_idx];
+   if (wiphy_ext_feature_isset(hw->wiphy,
+   NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG))
+   ieee80211_sta_mon_txrate_thold_check(sta);
+   }
 
if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) &&
(ieee80211_is_data_qos(fc))) {
-- 
1.9.1



[RFC 5/6] mac80211: Add support to configure txrate threshold for station

2018-04-20 Thread Tamizh chelvam
This patch add new api to support to configure low and high txrate
threshold for the connected stations.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/cfg.c  | 36 
 net/mac80211/sta_info.h |  5 +
 2 files changed, 41 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0e2047c..0f06b0b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3778,6 +3778,41 @@ static int ieee80211_set_sta_mon_rssi_range_confg(struct 
wiphy *wiphy,
return 0;
 }
 
+static int ieee80211_set_sta_mon_txrate_config(struct wiphy *wiphy,
+  struct net_device *dev,
+  const u8 *peer,
+  u32 low_txrate_thold,
+  u32 high_txrate_thold)
+{
+   struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+   struct sta_info *sta;
+
+   if (sdata->vif.type == NL80211_IFTYPE_AP &&
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_STA_MON_TXRATE_CONFIG))
+   return -EOPNOTSUPP;
+
+   mutex_lock(>local->sta_mtx);
+
+   sta = sta_info_get_bss(sdata, peer);
+   if (!sta) {
+   mutex_unlock(>local->sta_mtx);
+   return -ENOENT;
+   }
+
+   if (sta->txrate_low == low_txrate_thold &&
+   sta->txrate_high == high_txrate_thold)
+   goto unlock;
+
+   sta->txrate_low = low_txrate_thold;
+   sta->txrate_high = high_txrate_thold;
+   sta->last_txrate_event = 0;
+
+unlock:
+   mutex_unlock(>local->sta_mtx);
+   return 0;
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3873,4 +3908,5 @@ static int ieee80211_set_sta_mon_rssi_range_confg(struct 
wiphy *wiphy,
.tx_control_port = ieee80211_tx_control_port,
.set_sta_mon_rssi_config = ieee80211_set_sta_mon_rssi_config,
.set_sta_mon_rssi_range_config = ieee80211_set_sta_mon_rssi_range_confg,
+   .set_sta_mon_txrate_config = ieee80211_set_sta_mon_txrate_config,
 };
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5d6b763..14431c7 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -496,6 +496,8 @@ struct ieee80211_sta_rx_stats {
  * @count_rx_signal: Number of data frames used in ave_sta_signal. This can be
  * used to avoid generating less reliable station rssi cross events that
  * would be based only on couple of received frames.
+ * @txrate_low: Lower txrate threshold for a station to monitor
+ * @txrate_high: Upper txrate threshold for a station to monitor
  */
 struct sta_info {
/* General information, mostly static */
@@ -603,6 +605,9 @@ struct sta_info {
int last_sta_mon_event_signal;
unsigned int count_rx_signal;
 
+   u32 txrate_low;
+   u32 txrate_high;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.9.1



[PATCH 3/3] mac80211: Use proper chan_width enum in sta opmode event

2018-03-27 Thread Tamizh chelvam
Bandwidth change value reported via nl80211 contains mac80211
specific enum value(ieee80211_sta_rx_bw) and which is not
understand by userspace application. Map the mac80211 specific
value to nl80211_chan_width enum value to avoid using wrong value
in the userspace application. And used station's ht/vht capability
to map IEEE80211_STA_RX_BW_20 and IEEE80211_STA_RX_BW_160 with
proper nl80211 value.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/rx.c  |  3 ++-
 net/mac80211/vht.c | 32 +++-
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9237ffb..6c341d8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1816,6 +1816,8 @@ void ieee80211_apply_vhtcap_overrides(struct 
ieee80211_sub_if_data *sdata,
  struct ieee80211_sta_vht_cap *vht_cap);
 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
 u16 vht_mask[NL80211_VHT_NSS_MAX]);
+enum nl80211_chan_width
+ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta);
 
 /* Spectrum management */
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index f8c69ac..3a9f0c0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2922,7 +2922,8 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
 
rx->sta->sta.bandwidth = new_bw;
sband = rx->local->hw.wiphy->bands[status->band];
-   sta_opmode.bw = new_bw;
+   sta_opmode.bw =
+   ieee80211_sta_rx_bw_to_chan_width(rx->sta);
sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
 
rate_control_rate_update(local, sband, rx->sta,
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 5714dee..259325c 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -358,6 +358,36 @@ enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct 
sta_info *sta)
return NL80211_CHAN_WIDTH_80;
 }
 
+enum nl80211_chan_width
+ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta)
+{
+   enum ieee80211_sta_rx_bandwidth cur_bw = sta->sta.bandwidth;
+   struct ieee80211_sta_vht_cap *vht_cap = >sta.vht_cap;
+   u32 cap_width;
+
+   switch (cur_bw) {
+   case IEEE80211_STA_RX_BW_20:
+   if (!sta->sta.ht_cap.ht_supported)
+   return NL80211_CHAN_WIDTH_20_NOHT;
+   else
+   return NL80211_CHAN_WIDTH_20;
+   case IEEE80211_STA_RX_BW_40:
+   return NL80211_CHAN_WIDTH_40;
+   case IEEE80211_STA_RX_BW_80:
+   return NL80211_CHAN_WIDTH_80;
+   case IEEE80211_STA_RX_BW_160:
+   cap_width =
+   vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+
+   if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
+   return NL80211_CHAN_WIDTH_160;
+
+   return NL80211_CHAN_WIDTH_80P80;
+   default:
+   return NL80211_CHAN_WIDTH_20;
+   }
+}
+
 enum ieee80211_sta_rx_bandwidth
 ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
 {
@@ -484,7 +514,7 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
new_bw = ieee80211_sta_cur_vht_bw(sta);
if (new_bw != sta->sta.bandwidth) {
sta->sta.bandwidth = new_bw;
-   sta_opmode.bw = new_bw;
+   sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta);
changed |= IEEE80211_RC_BW_CHANGED;
sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
}
-- 
1.9.1



[PATCH 1/3] cfg80211: fix data type of sta_opmode_info parameter

2018-03-27 Thread Tamizh chelvam
Currently bw and smps_mode are u8 type value in sta_opmode_info
structure. This values filled in mac80211 from ieee80211_sta_rx_bandwidth
and ieee80211_smps_mode. These enum values are specific to mac80211 and
userspace/cfg80211 doesn't know about that. This will lead to incorrect
result/assumption by the user space application.
Change bw and smps_mode parameters to their respective enums in nl80211.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc40843..4341508 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3572,15 +3572,15 @@ enum wiphy_opmode_flag {
 /**
  * struct sta_opmode_info - Station's ht/vht operation mode information
  * @changed: contains value from  wiphy_opmode_flag
- * @smps_mode: New SMPS mode of a station
- * @bw: new max bandwidth value of a station
+ * @smps_mode: New SMPS mode value from  nl80211_smps_mode of a station
+ * @bw: new max bandwidth value from  nl80211_chan_width of a station
  * @rx_nss: new rx_nss value of a station
  */
 
 struct sta_opmode_info {
u32 changed;
-   u8 smps_mode;
-   u8 bw;
+   enum nl80211_smps_mode smps_mode;
+   enum nl80211_chan_width bw;
u8 rx_nss;
 };
 
-- 
1.9.1



[PATCH 2/3] mac80211: Use proper smps_mode enum in sta opmode event

2018-03-27 Thread Tamizh chelvam
SMPS_MODE change value notified via nl80211 contains mac80211
specific value(ieee80211_smps_mode) and user space application
will not know those values. This patch add support to map
the mac80211 enum value to nl80211_smps_mode which will be
understood by the userspace application.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/ht.c  | 15 +++
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/rx.c  |  3 ++-
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index d752353..c78036a 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -466,6 +466,21 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data 
*sdata,
__ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_PEER_REQUEST);
 }
 
+enum nl80211_smps_mode
+ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps)
+{
+   switch (smps) {
+   case IEEE80211_SMPS_OFF:
+   return NL80211_SMPS_OFF;
+   case IEEE80211_SMPS_STATIC:
+   return NL80211_SMPS_STATIC;
+   case IEEE80211_SMPS_DYNAMIC:
+   return NL80211_SMPS_DYNAMIC;
+   default:
+   return NL80211_SMPS_OFF;
+   }
+}
+
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
   enum ieee80211_smps_mode smps, const u8 *da,
   const u8 *bssid)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ae9c33c..9237ffb 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1788,6 +1788,8 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int 
tid,
 void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
 
 u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs);
+enum nl80211_smps_mode
+ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps);
 
 /* VHT */
 void
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 27bb1f0..f8c69ac 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2883,7 +2883,8 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
if (rx->sta->sta.smps_mode == smps_mode)
goto handled;
rx->sta->sta.smps_mode = smps_mode;
-   sta_opmode.smps_mode = smps_mode;
+   sta_opmode.smps_mode =
+   ieee80211_smps_mode_to_smps_mode(smps_mode);
sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED;
 
sband = rx->local->hw.wiphy->bands[status->band];
-- 
1.9.1



[PATCH 0/3] cfg80211/mac80211: Notify proper sta opmode change value

2018-03-27 Thread Tamizh chelvam
Currently bw and smps_mode are u8 type value in sta_opmode_info
structure. This values filled in mac80211 from ieee80211_sta_rx_bandwidth
and ieee80211_smps_mode. These enum values are specific to mac80211 and
userspace/cfg80211 doesn't know about that. This patchset change its
data type in the sta_opmode_info structure and mapping from mac80211
specific enum to nl80211 enum value.

Tamizh chelvam (3):
  cfg80211: fix data type of sta_opmode_info parameter
  mac80211: Use proper smps_mode enum in sta opmode event
  mac80211: Use proper chan_width enum in sta opmode event

 include/net/cfg80211.h |  8 
 net/mac80211/ht.c  | 15 +++
 net/mac80211/ieee80211_i.h |  4 
 net/mac80211/rx.c  |  6 --
 net/mac80211/vht.c | 32 +++-
 5 files changed, 58 insertions(+), 7 deletions(-)

-- 
1.9.1



Re: [RFC 0/3] cfg80211/mac80211: Notify proper sta opmode change value

2018-03-27 Thread Tamizh chelvam

On 2018-03-27 18:26, Johannes Berg wrote:

On Tue, 2018-03-27 at 12:18 +0530, Tamizh chelvam wrote:

Currently bw and smps_mode are u8 type value in sta_opmode_info
structure. This values filled in mac80211 from 
ieee80211_sta_rx_bandwidth
and ieee80211_smps_mode. These enum values are specific to mac80211 
and

userspace/cfg80211 doesn't know about that. This patchset change its
data type in the sta_opmode_info structure and mapping from mac80211
specific enum to nl80211 enum value.


Good catch.


Tamizh chelvam (3):
  cfg80211: fix data type of sta_opmode_info parameter
  mac80211: Use proper smps_mode enum in sta opmode event
  mac80211: Use proper chan_width enum in sta opmode event

Note :
  * Is this mac80211 approach sufficient ? or whether some more
complete cleanup would be preferred ?


Not sure what you mean? The patches look good to me.

I just wanted to confirm is this approach fine or not! I'll send a patch 
format


[RFC 1/3] cfg80211: fix data type of sta_opmode_info parameter

2018-03-27 Thread Tamizh chelvam
Currently bw and smps_mode are u8 type value in sta_opmode_info
structure. This values filled in mac80211 from ieee80211_sta_rx_bandwidth
and ieee80211_smps_mode. These enum values are specific to mac80211 and
userspace/cfg80211 doesn't know about that. This will lead to incorrect
result/assumption by the user space application.
Change bw and smps_mode parameters to their respective enums in nl80211.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc40843..4341508 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3572,15 +3572,15 @@ enum wiphy_opmode_flag {
 /**
  * struct sta_opmode_info - Station's ht/vht operation mode information
  * @changed: contains value from  wiphy_opmode_flag
- * @smps_mode: New SMPS mode of a station
- * @bw: new max bandwidth value of a station
+ * @smps_mode: New SMPS mode value from  nl80211_smps_mode of a station
+ * @bw: new max bandwidth value from  nl80211_chan_width of a station
  * @rx_nss: new rx_nss value of a station
  */
 
 struct sta_opmode_info {
u32 changed;
-   u8 smps_mode;
-   u8 bw;
+   enum nl80211_smps_mode smps_mode;
+   enum nl80211_chan_width bw;
u8 rx_nss;
 };
 
-- 
1.9.1



[RFC 2/3] mac80211: Use proper smps_mode enum in sta opmode event

2018-03-27 Thread Tamizh chelvam
SMPS_MODE change value notified via nl80211 contains mac80211
specific value(ieee80211_smps_mode) and user space application
will not know those values. This patch add support to map
the mac80211 enum value to nl80211_smps_mode which will be
understood by the userspace application.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/ht.c  | 15 +++
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/rx.c  |  3 ++-
 3 files changed, 19 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index d752353..c78036a 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -466,6 +466,21 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data 
*sdata,
__ieee80211_stop_tx_ba_session(sta, tid, AGG_STOP_PEER_REQUEST);
 }
 
+enum nl80211_smps_mode
+ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps)
+{
+   switch (smps) {
+   case IEEE80211_SMPS_OFF:
+   return NL80211_SMPS_OFF;
+   case IEEE80211_SMPS_STATIC:
+   return NL80211_SMPS_STATIC;
+   case IEEE80211_SMPS_DYNAMIC:
+   return NL80211_SMPS_DYNAMIC;
+   default:
+   return NL80211_SMPS_OFF;
+   }
+}
+
 int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
   enum ieee80211_smps_mode smps, const u8 *da,
   const u8 *bssid)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ae9c33c..9237ffb 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1788,6 +1788,8 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int 
tid,
 void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
 
 u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs);
+enum nl80211_smps_mode
+ieee80211_smps_mode_to_smps_mode(enum ieee80211_smps_mode smps);
 
 /* VHT */
 void
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 27bb1f0..f8c69ac 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2883,7 +2883,8 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
if (rx->sta->sta.smps_mode == smps_mode)
goto handled;
rx->sta->sta.smps_mode = smps_mode;
-   sta_opmode.smps_mode = smps_mode;
+   sta_opmode.smps_mode =
+   ieee80211_smps_mode_to_smps_mode(smps_mode);
sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED;
 
sband = rx->local->hw.wiphy->bands[status->band];
-- 
1.9.1



[RFC 0/3] cfg80211/mac80211: Notify proper sta opmode change value

2018-03-27 Thread Tamizh chelvam
Currently bw and smps_mode are u8 type value in sta_opmode_info
structure. This values filled in mac80211 from ieee80211_sta_rx_bandwidth
and ieee80211_smps_mode. These enum values are specific to mac80211 and
userspace/cfg80211 doesn't know about that. This patchset change its
data type in the sta_opmode_info structure and mapping from mac80211
specific enum to nl80211 enum value.

Tamizh chelvam (3):
  cfg80211: fix data type of sta_opmode_info parameter
  mac80211: Use proper smps_mode enum in sta opmode event
  mac80211: Use proper chan_width enum in sta opmode event

Note :
  * Is this mac80211 approach sufficient ? or whether some more
complete cleanup would be preferred ?

 include/net/cfg80211.h |  8 
 net/mac80211/ht.c  | 15 +++
 net/mac80211/ieee80211_i.h |  4 
 net/mac80211/rx.c  |  6 --
 net/mac80211/vht.c | 32 +++-
 5 files changed, 58 insertions(+), 7 deletions(-)

-- 
1.9.1



[RFC 3/3] mac80211: Use proper chan_width enum in sta opmode event

2018-03-27 Thread Tamizh chelvam
Bandwidth change value reported via nl80211 contains mac80211
specific enum value(ieee80211_sta_rx_bw) and which is not
understand by userspace application. Map the mac80211 specific
value to nl80211_chan_width enum value to avoid using wrong value
in the userspace application. And used station's ht/vht capability
to map IEEE80211_STA_RX_BW_20 and IEEE80211_STA_RX_BW_160 with
proper nl80211 value.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/ieee80211_i.h |  2 ++
 net/mac80211/rx.c  |  3 ++-
 net/mac80211/vht.c | 32 +++-
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9237ffb..6c341d8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1816,6 +1816,8 @@ void ieee80211_apply_vhtcap_overrides(struct 
ieee80211_sub_if_data *sdata,
  struct ieee80211_sta_vht_cap *vht_cap);
 void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
 u16 vht_mask[NL80211_VHT_NSS_MAX]);
+enum nl80211_chan_width
+ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta);
 
 /* Spectrum management */
 void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index f8c69ac..3a9f0c0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2922,7 +2922,8 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
 
rx->sta->sta.bandwidth = new_bw;
sband = rx->local->hw.wiphy->bands[status->band];
-   sta_opmode.bw = new_bw;
+   sta_opmode.bw =
+   ieee80211_sta_rx_bw_to_chan_width(rx->sta);
sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
 
rate_control_rate_update(local, sband, rx->sta,
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 5714dee..259325c 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -358,6 +358,36 @@ enum nl80211_chan_width ieee80211_sta_cap_chan_bw(struct 
sta_info *sta)
return NL80211_CHAN_WIDTH_80;
 }
 
+enum nl80211_chan_width
+ieee80211_sta_rx_bw_to_chan_width(struct sta_info *sta)
+{
+   enum ieee80211_sta_rx_bandwidth cur_bw = sta->sta.bandwidth;
+   struct ieee80211_sta_vht_cap *vht_cap = >sta.vht_cap;
+   u32 cap_width;
+
+   switch (cur_bw) {
+   case IEEE80211_STA_RX_BW_20:
+   if (!sta->sta.ht_cap.ht_supported)
+   return NL80211_CHAN_WIDTH_20_NOHT;
+   else
+   return NL80211_CHAN_WIDTH_20;
+   case IEEE80211_STA_RX_BW_40:
+   return NL80211_CHAN_WIDTH_40;
+   case IEEE80211_STA_RX_BW_80:
+   return NL80211_CHAN_WIDTH_80;
+   case IEEE80211_STA_RX_BW_160:
+   cap_width =
+   vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+
+   if (cap_width == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)
+   return NL80211_CHAN_WIDTH_160;
+
+   return NL80211_CHAN_WIDTH_80P80;
+   default:
+   return NL80211_CHAN_WIDTH_20;
+   }
+}
+
 enum ieee80211_sta_rx_bandwidth
 ieee80211_chan_width_to_rx_bw(enum nl80211_chan_width width)
 {
@@ -484,7 +514,7 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
new_bw = ieee80211_sta_cur_vht_bw(sta);
if (new_bw != sta->sta.bandwidth) {
sta->sta.bandwidth = new_bw;
-   sta_opmode.bw = new_bw;
+   sta_opmode.bw = ieee80211_sta_rx_bw_to_chan_width(sta);
changed |= IEEE80211_RC_BW_CHANGED;
sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
}
-- 
1.9.1



Re: [PATCHv2] ath10k: fix kernel panic while reading tpc_stats

2018-03-27 Thread Tamizh chelvam

On 2018-03-26 21:19, Kalle Valo wrote:

Tamizh chelvam <tami...@codeaurora.org> writes:


When attempt to read tpc_stats for the chipsets which support
more than 3 tx chain will trigger kernel panic(kernel stack is 
corrupted)

due to writing values on rate_code array out of range.
This patch changes the array size depends on the WMI_TPC_TX_N_CHAIN 
and

added check to avoid write values on the array if the num tx chain
get in tpc config event is greater than WMI_TPC_TX_N_CHAIN.

Tested on QCA9984 with firmware-5.bin_10.4-3.5.3-00057

Kernel panic log :

[  323.510944] Kernel panic - not syncing: stack-protector: Kernel 
stack is corrupted in: bf90c654

[  323.510944]
[  323.524390] CPU: 0 PID: 1908 Comm: cat Not tainted 3.14.77 #31
[  323.530224] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.537941] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.545146] [] (dump_stack) from [] 
(panic+0x84/0x1e4)
[  323.552000] [] (panic) from [] 
(__stack_chk_fail+0x10/0x14)
[  323.559350] [] (__stack_chk_fail) from [] 
(ath10k_wmi_event_pdev_tpc_config+0x424/0x438 [ath10k_core])
[  323.570471] [] (ath10k_wmi_event_pdev_tpc_config 
[ath10k_core]) from [] (ath10k_wmi_10_4_op_rx+0x2f0/0x39c 
[ath10k_core])
[  323.583047] [] (ath10k_wmi_10_4_op_rx [ath10k_core]) from 
[] (ath10k_htc_rx_completion_handler+0x170/0x1a0 
[ath10k_core])
[  323.595702] [] (ath10k_htc_rx_completion_handler 
[ath10k_core]) from [] 
(ath10k_pci_hif_send_complete_check+0x1f0/0x220 [ath10k_pci])
[  323.609421] [] (ath10k_pci_hif_send_complete_check 
[ath10k_pci]) from [] 
(ath10k_ce_per_engine_service+0x74/0xc4 [ath10k_pci])
[  323.622490] [] (ath10k_ce_per_engine_service 
[ath10k_pci]) from [] 
(ath10k_ce_per_engine_service_any+0x74/0x80 [ath10k_pci])
[  323.635423] [] (ath10k_ce_per_engine_service_any 
[ath10k_pci]) from [] (ath10k_pci_napi_poll+0x44/0xe8 
[ath10k_pci])
[  323.647665] [] (ath10k_pci_napi_poll [ath10k_pci]) from 
[] (net_rx_action+0xac/0x160)
[  323.657208] [] (net_rx_action) from [] 
(__do_softirq+0x104/0x294)
[  323.665017] [] (__do_softirq) from [] 
(irq_exit+0x9c/0x11c)
[  323.672314] [] (irq_exit) from [] 
(handle_IRQ+0x6c/0x90)
[  323.679341] [] (handle_IRQ) from [] 
(gic_handle_irq+0x3c/0x60)
[  323.686893] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)

[  323.694349] Exception stack(0xdd489c58 to 0xdd489ca0)
[  323.699384] 9c40:   
 a013
[  323.707547] 9c60:  dc4bce40 6013 ddc1d800 dd488000 
0990  c085c800
[  323.715707] 9c80:  dd489d44 092d dd489ca0 c026e664 
c026e668 6013 
[  323.723877] [] (__irq_svc) from [] 
(rcu_note_context_switch+0x170/0x184)
[  323.732298] [] (rcu_note_context_switch) from 
[] (__schedule+0x50/0x4d4)
[  323.740716] [] (__schedule) from [] 
(schedule_timeout+0x148/0x178)
[  323.748611] [] (schedule_timeout) from [] 
(wait_for_common+0x114/0x154)
[  323.756972] [] (wait_for_common) from [] 
(ath10k_tpc_stats_open+0xc8/0x340 [ath10k_core])
[  323.766873] [] (ath10k_tpc_stats_open [ath10k_core]) from 
[] (do_dentry_open+0x1ac/0x274)
[  323.776741] [] (do_dentry_open) from [] 
(do_last+0x8c0/0xb08)
[  323.784201] [] (do_last) from [] 
(path_openat+0x210/0x598)
[  323.791408] [] (path_openat) from [] 
(do_filp_open+0x2c/0x78)
[  323.798873] [] (do_filp_open) from [] 
(do_sys_open+0x114/0x1b4)
[  323.806509] [] (do_sys_open) from [] 
(ret_fast_syscall+0x0/0x44)

[  323.814241] CPU1: stopping
[  323.816927] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.14.77 #31
[  323.823008] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.830731] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.837934] [] (dump_stack) from [] 
(handle_IPI+0xb8/0x140)
[  323.845224] [] (handle_IPI) from [] 
(gic_handle_irq+0x58/0x60)
[  323.852774] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)

[  323.860233] Exception stack(0xdd499fa0 to 0xdd499fe8)
[  323.865273] 9fa0: ffed  1d3c9000  dd498000 
dd498030 10c0387d c08b62c8
[  323.873432] 9fc0: 4220406a 512f04d0   0001 
dd499fe8 c021838c c0218390

[  323.881588] 9fe0: 6013 
[  323.885070] [] (__irq_svc) from [] 
(arch_cpu_idle+0x30/0x50)
[  323.892454] [] (arch_cpu_idle) from [] 
(cpu_startup_entry+0xa4/0x108)
[  323.900690] [] (cpu_startup_entry) from [<422085a4>] 
(0x422085a4)


Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>


In v1 kbuild reported this warning:

drivers/net/wireless/ath/ath10k/wmi.c:4465:14: error: 'struct ath10k'
has no member named 'debug'

Did you fix it?


oops:( sorry, I'll send next version of the patch by fixing it.

@@ -4455,6 +4461,8 @@ void ath10k_wmi_event_pdev_tpc_config(struct 
ath10k *ar, struct sk_buff *skb)

   __le32_to_cpu(ev->twice_max_rd_power) / 2,
   __le32_to_cpu(ev->num_tx_chain),
   __le32_to_cpu(ev->rate_max));
+exit:
+   complete(>debug.tpc_

[PATCHv2] ath10k: fix kernel panic while reading tpc_stats

2018-03-22 Thread Tamizh chelvam
When attempt to read tpc_stats for the chipsets which support
more than 3 tx chain will trigger kernel panic(kernel stack is corrupted)
due to writing values on rate_code array out of range.
This patch changes the array size depends on the WMI_TPC_TX_N_CHAIN and
added check to avoid write values on the array if the num tx chain
get in tpc config event is greater than WMI_TPC_TX_N_CHAIN.

Tested on QCA9984 with firmware-5.bin_10.4-3.5.3-00057

Kernel panic log :

[  323.510944] Kernel panic - not syncing: stack-protector: Kernel stack is 
corrupted in: bf90c654
[  323.510944]
[  323.524390] CPU: 0 PID: 1908 Comm: cat Not tainted 3.14.77 #31
[  323.530224] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.537941] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.545146] [] (dump_stack) from [] (panic+0x84/0x1e4)
[  323.552000] [] (panic) from [] 
(__stack_chk_fail+0x10/0x14)
[  323.559350] [] (__stack_chk_fail) from [] 
(ath10k_wmi_event_pdev_tpc_config+0x424/0x438 [ath10k_core])
[  323.570471] [] (ath10k_wmi_event_pdev_tpc_config [ath10k_core]) 
from [] (ath10k_wmi_10_4_op_rx+0x2f0/0x39c [ath10k_core])
[  323.583047] [] (ath10k_wmi_10_4_op_rx [ath10k_core]) from 
[] (ath10k_htc_rx_completion_handler+0x170/0x1a0 [ath10k_core])
[  323.595702] [] (ath10k_htc_rx_completion_handler [ath10k_core]) 
from [] (ath10k_pci_hif_send_complete_check+0x1f0/0x220 [ath10k_pci])
[  323.609421] [] (ath10k_pci_hif_send_complete_check [ath10k_pci]) 
from [] (ath10k_ce_per_engine_service+0x74/0xc4 [ath10k_pci])
[  323.622490] [] (ath10k_ce_per_engine_service [ath10k_pci]) from 
[] (ath10k_ce_per_engine_service_any+0x74/0x80 [ath10k_pci])
[  323.635423] [] (ath10k_ce_per_engine_service_any [ath10k_pci]) 
from [] (ath10k_pci_napi_poll+0x44/0xe8 [ath10k_pci])
[  323.647665] [] (ath10k_pci_napi_poll [ath10k_pci]) from 
[] (net_rx_action+0xac/0x160)
[  323.657208] [] (net_rx_action) from [] 
(__do_softirq+0x104/0x294)
[  323.665017] [] (__do_softirq) from [] 
(irq_exit+0x9c/0x11c)
[  323.672314] [] (irq_exit) from [] (handle_IRQ+0x6c/0x90)
[  323.679341] [] (handle_IRQ) from [] 
(gic_handle_irq+0x3c/0x60)
[  323.686893] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)
[  323.694349] Exception stack(0xdd489c58 to 0xdd489ca0)
[  323.699384] 9c40:   
 a013
[  323.707547] 9c60:  dc4bce40 6013 ddc1d800 dd488000 0990 
 c085c800
[  323.715707] 9c80:  dd489d44 092d dd489ca0 c026e664 c026e668 
6013 
[  323.723877] [] (__irq_svc) from [] 
(rcu_note_context_switch+0x170/0x184)
[  323.732298] [] (rcu_note_context_switch) from [] 
(__schedule+0x50/0x4d4)
[  323.740716] [] (__schedule) from [] 
(schedule_timeout+0x148/0x178)
[  323.748611] [] (schedule_timeout) from [] 
(wait_for_common+0x114/0x154)
[  323.756972] [] (wait_for_common) from [] 
(ath10k_tpc_stats_open+0xc8/0x340 [ath10k_core])
[  323.766873] [] (ath10k_tpc_stats_open [ath10k_core]) from 
[] (do_dentry_open+0x1ac/0x274)
[  323.776741] [] (do_dentry_open) from [] 
(do_last+0x8c0/0xb08)
[  323.784201] [] (do_last) from [] 
(path_openat+0x210/0x598)
[  323.791408] [] (path_openat) from [] 
(do_filp_open+0x2c/0x78)
[  323.798873] [] (do_filp_open) from [] 
(do_sys_open+0x114/0x1b4)
[  323.806509] [] (do_sys_open) from [] 
(ret_fast_syscall+0x0/0x44)
[  323.814241] CPU1: stopping
[  323.816927] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.14.77 #31
[  323.823008] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.830731] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.837934] [] (dump_stack) from [] 
(handle_IPI+0xb8/0x140)
[  323.845224] [] (handle_IPI) from [] 
(gic_handle_irq+0x58/0x60)
[  323.852774] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)
[  323.860233] Exception stack(0xdd499fa0 to 0xdd499fe8)
[  323.865273] 9fa0: ffed  1d3c9000  dd498000 dd498030 
10c0387d c08b62c8
[  323.873432] 9fc0: 4220406a 512f04d0   0001 dd499fe8 
c021838c c0218390
[  323.881588] 9fe0: 6013 
[  323.885070] [] (__irq_svc) from [] 
(arch_cpu_idle+0x30/0x50)
[  323.892454] [] (arch_cpu_idle) from [] 
(cpu_startup_entry+0xa4/0x108)
[  323.900690] [] (cpu_startup_entry) from [<422085a4>] (0x422085a4)

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
v2:
  * Removed unnecessary '\n' in the beginning of the format string 

 drivers/net/wireless/ath/ath10k/debug.c |  8 +++-
 drivers/net/wireless/ath/ath10k/wmi.c   | 10 +-
 drivers/net/wireless/ath/ath10k/wmi.h   |  2 +-
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c 
b/drivers/net/wireless/ath/ath10k/debug.c
index 554cd78..d816299 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1506,7 +1506,13 @@ static void ath10k_tpc_stats_print(struct 
ath10k_tpc_stats *tpc_stats,
*len += scnprintf(buf + *len, bu

[PATCH] ath10k: fix kernel panic while reading tpc_stats

2018-03-22 Thread Tamizh chelvam
When attempt to read tpc_stats for the chipsets which support
more than 3 tx chain will trigger kernel panic(kernel stack is corrupted)
due to writing values on rate_code array out of range.
This patch changes the array size depends on the WMI_TPC_TX_N_CHAIN and
added check to avoid write values on the array if the num tx chain
get in tpc config event is greater than WMI_TPC_TX_N_CHAIN.

Tested on QCA9984 with firmware-5.bin_10.4-3.5.3-00057

Kernel panic log :

[  323.510944] Kernel panic - not syncing: stack-protector: Kernel stack is 
corrupted in: bf90c654
[  323.510944]
[  323.524390] CPU: 0 PID: 1908 Comm: cat Not tainted 3.14.77 #31
[  323.530224] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.537941] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.545146] [] (dump_stack) from [] (panic+0x84/0x1e4)
[  323.552000] [] (panic) from [] 
(__stack_chk_fail+0x10/0x14)
[  323.559350] [] (__stack_chk_fail) from [] 
(ath10k_wmi_event_pdev_tpc_config+0x424/0x438 [ath10k_core])
[  323.570471] [] (ath10k_wmi_event_pdev_tpc_config [ath10k_core]) 
from [] (ath10k_wmi_10_4_op_rx+0x2f0/0x39c [ath10k_core])
[  323.583047] [] (ath10k_wmi_10_4_op_rx [ath10k_core]) from 
[] (ath10k_htc_rx_completion_handler+0x170/0x1a0 [ath10k_core])
[  323.595702] [] (ath10k_htc_rx_completion_handler [ath10k_core]) 
from [] (ath10k_pci_hif_send_complete_check+0x1f0/0x220 [ath10k_pci])
[  323.609421] [] (ath10k_pci_hif_send_complete_check [ath10k_pci]) 
from [] (ath10k_ce_per_engine_service+0x74/0xc4 [ath10k_pci])
[  323.622490] [] (ath10k_ce_per_engine_service [ath10k_pci]) from 
[] (ath10k_ce_per_engine_service_any+0x74/0x80 [ath10k_pci])
[  323.635423] [] (ath10k_ce_per_engine_service_any [ath10k_pci]) 
from [] (ath10k_pci_napi_poll+0x44/0xe8 [ath10k_pci])
[  323.647665] [] (ath10k_pci_napi_poll [ath10k_pci]) from 
[] (net_rx_action+0xac/0x160)
[  323.657208] [] (net_rx_action) from [] 
(__do_softirq+0x104/0x294)
[  323.665017] [] (__do_softirq) from [] 
(irq_exit+0x9c/0x11c)
[  323.672314] [] (irq_exit) from [] (handle_IRQ+0x6c/0x90)
[  323.679341] [] (handle_IRQ) from [] 
(gic_handle_irq+0x3c/0x60)
[  323.686893] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)
[  323.694349] Exception stack(0xdd489c58 to 0xdd489ca0)
[  323.699384] 9c40:   
 a013
[  323.707547] 9c60:  dc4bce40 6013 ddc1d800 dd488000 0990 
 c085c800
[  323.715707] 9c80:  dd489d44 092d dd489ca0 c026e664 c026e668 
6013 
[  323.723877] [] (__irq_svc) from [] 
(rcu_note_context_switch+0x170/0x184)
[  323.732298] [] (rcu_note_context_switch) from [] 
(__schedule+0x50/0x4d4)
[  323.740716] [] (__schedule) from [] 
(schedule_timeout+0x148/0x178)
[  323.748611] [] (schedule_timeout) from [] 
(wait_for_common+0x114/0x154)
[  323.756972] [] (wait_for_common) from [] 
(ath10k_tpc_stats_open+0xc8/0x340 [ath10k_core])
[  323.766873] [] (ath10k_tpc_stats_open [ath10k_core]) from 
[] (do_dentry_open+0x1ac/0x274)
[  323.776741] [] (do_dentry_open) from [] 
(do_last+0x8c0/0xb08)
[  323.784201] [] (do_last) from [] 
(path_openat+0x210/0x598)
[  323.791408] [] (path_openat) from [] 
(do_filp_open+0x2c/0x78)
[  323.798873] [] (do_filp_open) from [] 
(do_sys_open+0x114/0x1b4)
[  323.806509] [] (do_sys_open) from [] 
(ret_fast_syscall+0x0/0x44)
[  323.814241] CPU1: stopping
[  323.816927] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.14.77 #31
[  323.823008] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  323.830731] [] (show_stack) from [] 
(dump_stack+0x80/0xa0)
[  323.837934] [] (dump_stack) from [] 
(handle_IPI+0xb8/0x140)
[  323.845224] [] (handle_IPI) from [] 
(gic_handle_irq+0x58/0x60)
[  323.852774] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x70)
[  323.860233] Exception stack(0xdd499fa0 to 0xdd499fe8)
[  323.865273] 9fa0: ffed  1d3c9000  dd498000 dd498030 
10c0387d c08b62c8
[  323.873432] 9fc0: 4220406a 512f04d0   0001 dd499fe8 
c021838c c0218390
[  323.881588] 9fe0: 6013 
[  323.885070] [] (__irq_svc) from [] 
(arch_cpu_idle+0x30/0x50)
[  323.892454] [] (arch_cpu_idle) from [] 
(cpu_startup_entry+0xa4/0x108)
[  323.900690] [] (cpu_startup_entry) from [<422085a4>] (0x422085a4)

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 drivers/net/wireless/ath/ath10k/debug.c | 12 +---
 drivers/net/wireless/ath/ath10k/wmi.c   | 10 +-
 drivers/net/wireless/ath/ath10k/wmi.h   |  2 +-
 3 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/debug.c 
b/drivers/net/wireless/ath/ath10k/debug.c
index 554cd78..8c41c81 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1506,18 +1506,24 @@ static void ath10k_tpc_stats_print(struct 
ath10k_tpc_stats *tpc_stats,
*len += scnprintf(buf + *len, buf_len - *len,
  "*

[PATCH 2/2] mac80211: Add support to enable or disable btcoex

2018-03-01 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

This patch introduces a new driver call back drv_set_btcoex
to enable/disable btcoex.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h|2 ++
 net/mac80211/cfg.c|8 
 net/mac80211/driver-ops.h |   13 +
 net/mac80211/trace.h  |   17 +
 4 files changed, 40 insertions(+)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2fd59ed..45d4281 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3487,6 +3487,7 @@ enum ieee80211_reconfig_type {
  * @del_nan_func: Remove a NAN function. The driver must call
  * ieee80211_nan_func_terminated() with
  * NL80211_NAN_FUNC_TERM_REASON_USER_REQUEST reason code upon removal.
+ * @set_btcoex: To enable/disable btcoex. Returns 0 on success.
  */
 struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3768,6 +3769,7 @@ struct ieee80211_ops {
void (*del_nan_func)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u8 instance_id);
+   int (*set_btcoex)(struct ieee80211_hw *hw, bool enabled);
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index fd68f6f..1a939c1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3694,6 +3694,13 @@ static int ieee80211_set_multicast_to_unicast(struct 
wiphy *wiphy,
return 0;
 }
 
+static int ieee80211_set_btcoex(struct wiphy *wiphy, bool enabled)
+{
+   struct ieee80211_local *local = wiphy_priv(wiphy);
+
+   return drv_set_btcoex(local, enabled);
+}
+
 const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3786,4 +3793,5 @@ static int ieee80211_set_multicast_to_unicast(struct 
wiphy *wiphy,
.add_nan_func = ieee80211_add_nan_func,
.del_nan_func = ieee80211_del_nan_func,
.set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
+   .set_btcoex = ieee80211_set_btcoex,
 };
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 4d82fe7..c424e17 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1250,4 +1250,17 @@ static inline void drv_del_nan_func(struct 
ieee80211_local *local,
trace_drv_return_void(local);
 }
 
+static inline int drv_set_btcoex(struct ieee80211_local *local, bool enabled)
+{
+   int ret = -EOPNOTSUPP;
+
+   trace_drv_set_btcoex(local, enabled);
+   if (local->ops->set_btcoex)
+   ret = local->ops->set_btcoex(>hw, enabled);
+
+   trace_drv_return_int(local, ret);
+
+   return ret;
+}
+
 #endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 591ad02..e30e0b1 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -746,6 +746,23 @@
TP_ARGS(local, value)
 );
 
+TRACE_EVENT(drv_set_btcoex,
+   TP_PROTO(struct ieee80211_local *local, bool enabled),
+   TP_ARGS(local, enabled),
+   TP_STRUCT__entry(
+   LOCAL_ENTRY
+   __field(bool, enabled)
+   ),
+   TP_fast_assign(
+   LOCAL_ASSIGN;
+   __entry->enabled = enabled;
+   ),
+   TP_printk(
+   LOCAL_PR_FMT " enabled:%d ",
+   LOCAL_PR_ARG, __entry->enabled
+   )
+);
+
 TRACE_EVENT(drv_set_coverage_class,
TP_PROTO(struct ieee80211_local *local, s16 value),
 
-- 
1.7.9.5



[PATCH 1/2] cfg80211: Add support to enable or disable btcoex

2018-03-01 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

This patch introduces NL80211_CMD_SET_BTCOEX command and
NL80211_ATTR_BTCOEX_OP attribute to enable or disable btcoex.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   |4 
 include/uapi/linux/nl80211.h |   10 ++
 net/wireless/nl80211.c   |   28 
 net/wireless/rdev-ops.h  |   11 +++
 net/wireless/trace.h |   15 +++
 5 files changed, 68 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fc40843..b0e8bf6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2960,6 +2960,9 @@ struct cfg80211_external_auth_params {
  *
  * @external_auth: indicates result of offloaded authentication processing from
  * user space
+ *
+ * @set_btcoex: This callback used to Enable/disable btcoex
+ *
  */
 struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3255,6 +3258,7 @@ struct cfg80211_ops {
   const u8 *aa);
int (*external_auth)(struct wiphy *wiphy, struct net_device *dev,
 struct cfg80211_external_auth_params *params);
+   int (*set_btcoex)(struct wiphy *wiphy, bool enabled);
 };
 
 /*
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c13c843..3fb45b2 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1018,6 +1018,8 @@
  * _ATTR_CHANNEL_WIDTH,_ATTR_NSS attributes with its
  * address(specified in _ATTR_MAC).
  *
+ * @NL80211_CMD_SET_BTCOEX: Enable/Disable btcoex using 
%NL80211_ATTR_BTCOEX_OP.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1228,6 +1230,8 @@ enum nl80211_commands {
 
NL80211_CMD_STA_OPMODE_CHANGED,
 
+   NL80211_CMD_SET_BTCOEX,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -2196,6 +2200,10 @@ enum nl80211_commands {
  * @NL80211_ATTR_NSS: Station's New/updated  RX_NSS value notified using this
  * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
  *
+ * @NL80211_ATTR_BTCOEX_OP: u8 attribute for driver supporting
+ * the btcoex feature. This will be used with %NL80211_CMD_SET_BTCOEX
+ * to enable/disable btcoex.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2628,6 +2636,8 @@ enum nl80211_attrs {
NL80211_ATTR_NSS,
NL80211_ATTR_ACK_SIGNAL,
 
+   NL80211_ATTR_BTCOEX_OP,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a910150..ebd119b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -422,6 +422,7 @@ enum nl80211_multicast_groups {
[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
[NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
+   [NL80211_ATTR_BTCOEX_OP] = { .type = NLA_U8 },
 };
 
 /* policy for the key attributes */
@@ -12517,6 +12518,25 @@ static int nl80211_external_auth(struct sk_buff *skb, 
struct genl_info *info)
return rdev_external_auth(rdev, dev, );
 }
 
+static int nl80211_set_btcoex(struct sk_buff *skb, struct genl_info *info)
+{
+   struct cfg80211_registered_device *rdev = info->user_ptr[0];
+   u8 val = 0;
+
+   if (!rdev->ops->set_btcoex)
+   return -ENOTSUPP;
+
+   if (!info->attrs[NL80211_ATTR_BTCOEX_OP])
+   return -EINVAL;
+
+   val = nla_get_u8(info->attrs[NL80211_ATTR_BTCOEX_OP]);
+
+   if (val > 1)
+   return -EINVAL;
+
+   return rdev_set_btcoex(rdev, val);
+}
+
 #define NL80211_FLAG_NEED_WIPHY0x01
 #define NL80211_FLAG_NEED_NETDEV   0x02
 #define NL80211_FLAG_NEED_RTNL 0x04
@@ -13420,6 +13440,14 @@ static void nl80211_post_doit(const struct genl_ops 
*ops, struct sk_buff *skb,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
  NL80211_FLAG_NEED_RTNL,
},
+   {
+   .cmd = NL80211_CMD_SET_BTCOEX,
+   .doit = nl80211_set_btcoex,
+   .policy = nl80211_policy,
+   .flags = GENL_UNS_ADMIN_PERM,
+   .internal_flags = NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL,
+   },
 
 };
 
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 84f23ae..4002f2c 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1205,4 +1205,15 @@ static inline int rdev_del_pmk(struct 
cfg80211_registered_device *rdev,
retur

[PATCHv4 0/3] cfg80211/mac80211: cqm rssi config for AP mode

2018-02-24 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

Currently station mode has the support of rssi based cqm. This patchsets
extended the support for AP mode as well. Already netlink accepts mac
address in cqm notification event. We can use that to pass mac address of
the station to specify its rssi change event. This patchsets introduce
new api cfg80211_ap_sta_cqm_notify and multicast group to notify the event.

Pradeep Kumar Chitrapu (1):
  mac80211: enable setting cqm rssi config for AP mode

Tamizh chelvam (2):
  cfg80211: enable setting cqm rssi config for AP mode
  mac80211: implement cqm rssi check using rx data signal

v4:
  * Fixed compilation warning of missing description for count_rx_signal
and last_cqm_event_signal.

v3:
  * Added vif type check to avoid enable this feature for all mode.

V2:
  * Removed changing existing ieee80211_cqm_rssi_notify api changes.
  * Introduced new ext feature bit and multicast group id to support this
feature.

 include/net/cfg80211.h   |   15 +
 include/net/mac80211.h   |7 +
 include/uapi/linux/nl80211.h |6 
 net/mac80211/cfg.c   |   31 --
 net/mac80211/rx.c|   46 ++-
 net/mac80211/sta_info.h  |9 ++
 net/wireless/nl80211.c   |   71 --
 7 files changed, 164 insertions(+), 21 deletions(-)

-- 
1.7.9.5



[PATCHv4 2/3] mac80211: enable setting cqm rssi config for AP mode

2018-02-24 Thread Tamizh chelvam
From: Pradeep Kumar Chitrapu <prade...@codeaurora.org>

Enable connection monitoring for AP mode which makes it possible to
track signal strength of connected stations.

Co-Developed-by: Tamizh Chelvam <tami...@codeaurora.org>
Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
Signed-off-by: Pradeep Kumar Chitrapu <prade...@codeaurora.org>
---
 net/mac80211/cfg.c |   31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6f9d5be..74092cb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2690,6 +2690,25 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, 
struct net_device *dev,
return 0;
 }
 
+static void ieee80211_update_rssi_config(struct ieee80211_sub_if_data *sdata)
+{
+   if (!(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
+   return;
+
+   /* tell the driver upon association, unless already associated */
+   if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+   !sdata->u.mgd.associated)
+   return;
+
+   /* if AP, always tell the driver by checking beacon status */
+   if (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG))
+   return;
+
+   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+}
+
 static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 struct net_device *dev,
 s32 rssi_thold, u32 rssi_hyst)
@@ -2712,11 +2731,7 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy 
*wiphy,
bss_conf->cqm_rssi_high = 0;
sdata->u.mgd.last_cqm_event_signal = 0;
 
-   /* tell the driver upon association, unless already associated */
-   if (sdata->u.mgd.associated &&
-   sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
-
+   ieee80211_update_rssi_config(sdata);
return 0;
 }
 
@@ -2737,11 +2752,7 @@ static int ieee80211_set_cqm_rssi_range_config(struct 
wiphy *wiphy,
bss_conf->cqm_rssi_hyst = 0;
sdata->u.mgd.last_cqm_event_signal = 0;
 
-   /* tell the driver upon association, unless already associated */
-   if (sdata->u.mgd.associated &&
-   sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
-
+   ieee80211_update_rssi_config(sdata);
return 0;
 }
 
-- 
1.7.9.5



[PATCHv4 3/3] mac80211: implement cqm rssi check using rx data signal

2018-02-24 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

Triggers cfg80211_ap_sta_cqm_rssi_notify with the corresponding event
when station signal goes lower than the configured rssi threshold. And
notify back to user space once the station signal becomes greater than
the configured value. It uses rx data signal and compare with rssi value
given by user. This rssi threshold is bss specific and it is common for
all the stations.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h  |7 +++
 net/mac80211/rx.c   |   46 +-
 net/mac80211/sta_info.h |9 +
 3 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index dc3e9d9..e973bcd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -800,6 +800,13 @@ enum mac80211_rate_control_flags {
 };
 
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2783c5c..611dea5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1536,6 +1536,47 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf =
+   >sdata->vif.bss_conf;
+   int sig, last_event, thold;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (!bss_conf->cqm_rssi_thold || !bss_conf->enable_beacon) {
+   sta->count_rx_signal = 0;
+   return;
+   }
+
+   sig = -ewma_signal_read(>rx_stats_avg.signal);
+   last_event = sta->last_cqm_event_signal;
+   thold = bss_conf->cqm_rssi_thold;
+
+   if (sig < thold && last_event == 0) {
+   sta->last_cqm_event_signal = sig;
+   cfg80211_ap_sta_cqm_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   sta->count_rx_signal = 0;
+   } else if (last_event && sig > thold) {
+   sta->last_cqm_event_signal = 0;
+   cfg80211_ap_sta_cqm_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   sta->count_rx_signal = 0;
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1591,6 +1632,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -4000,9 +4042,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
 
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
-   if (!fast_rx->uses_rss)
+   if (!fast_rx->uses_rss) {
ewma_signal_add(>rx_stats_avg.signal,
-status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
+   }
}
 
if (status->chains) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index f64eb86..2127803 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -481,6 +481,12 @@ struct ieee80211_sta_rx_stats {
  * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
  * this (by advertising the USES_RSS hw flag)
  * @status_stats: TX status statistics
+ * @last_cqm_event_signal: Last data frame signal strength average that
+ * triggered a cqm event for a connected station. 0 indicates that no
+ * event has been generated for the station.
+ * @count_rx_signal: Number of data frames used in avg signal for a station.
+ * This can be used to avoid generating less reliable cqm events for
+ * the station.
  */
 struct sta_info {
/* Gene

[PATCHv4 1/3] cfg80211: enable setting cqm rssi config for AP mode

2018-02-24 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

This patch extend cqm rssi config and notifier feature to AP mode
by introducing NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG ext
feature bit. And this patch introduces NL80211_MCGRP_AP_STA_CQM
for notifying station's low/high rssi event to userspace application.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   |   15 +
 include/uapi/linux/nl80211.h |6 
 net/wireless/nl80211.c   |   71 --
 3 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 56e905c..d19fd5c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5706,6 +5706,21 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
  s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_ap_sta_cqm_rssi_notify - CQM rssi event for connected stations
+ * @dev: network device
+ * @mac: peer's MAC address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured connection quality monitoring
+ * rssi threshold reached event occurs for a station.
+ */
+void cfg80211_ap_sta_cqm_rssi_notify(struct net_device *dev, const u8 *mac,
+   enum nl80211_cqm_rssi_threshold_event rssi_event,
+   s32 rssi_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c13c843..81a60dc 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -49,6 +49,7 @@
 #define NL80211_MULTICAST_GROUP_MLME   "mlme"
 #define NL80211_MULTICAST_GROUP_VENDOR "vendor"
 #define NL80211_MULTICAST_GROUP_NAN"nan"
+#define NL80211_MULTICAST_GROUP_AP_STA_CQM "apstacqm"
 #define NL80211_MULTICAST_GROUP_TESTMODE   "testmode"
 
 /**
@@ -4999,6 +5000,10 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_LOW_SPAN_SCAN: Driver supports low span scan.
  * @NL80211_EXT_FEATURE_LOW_POWER_SCAN: Driver supports low power scan.
  * @NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN: Driver supports high accuracy scan.
+ * @NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG: With this driver will accept
+ * %NL80211_ATTR_CQM_RSSI_THOLD and %NL80211_ATTR_CQM_RSSI_HYST attributes
+ * for AP/AP_VLAN/P2P_GO interface to monitor rssi values of connected
+ * client.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5029,6 +5034,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_LOW_SPAN_SCAN,
NL80211_EXT_FEATURE_LOW_POWER_SCAN,
NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG,
 
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a910150..0ece819 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -44,6 +44,7 @@ enum nl80211_multicast_groups {
NL80211_MCGRP_MLME,
NL80211_MCGRP_VENDOR,
NL80211_MCGRP_NAN,
+   NL80211_MCGRP_AP_STA_CQM,
NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
 };
 
@@ -54,6 +55,8 @@ enum nl80211_multicast_groups {
[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
[NL80211_MCGRP_NAN] = { .name = NL80211_MULTICAST_GROUP_NAN },
+   [NL80211_MCGRP_AP_STA_CQM] = {
+   .name = NL80211_MULTICAST_GROUP_AP_STA_CQM },
 #ifdef CONFIG_NL80211_TESTMODE
[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
 #endif
@@ -9905,8 +9908,13 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
prev = thresholds[i];
}
 
-   if (wdev->iftype != NL80211_IFTYPE_STATION &&
-   wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+   if ((wdev->iftype != NL80211_IFTYPE_STATION &&
+wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) &&
+   ((wdev->iftype == NL80211_IFTYPE_AP ||
+ wdev->iftype == NL80211_IFTYPE_AP_VLAN ||
+ wdev->iftype == NL80211_IFTYPE_P2P_GO) &&
+!wiphy_ext_feature_isset(>wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG)))
return -EOPNOTSUPP;
 
wdev_lock(wdev);
@@ -14587,9 +14595,24 @@ static void cfg80211_send_cqm(struct sk_buff *msg, 
gfp_t gfp)
NL80211_MCGRP_MLME, gfp);
 }
 
-void cfg80211_cqm_rssi_notify(struct net_device *dev,
- 

[PATCHv3 1/3] cfg80211: enable setting cqm rssi config for AP mode

2018-02-21 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

This patch extend cqm rssi config and notifier feature to AP mode
by introducing NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG ext
feature bit. And this patch introduces NL80211_MCGRP_AP_STA_CQM
for notifying station's low/high rssi event to userspace application.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   |   15 +
 include/uapi/linux/nl80211.h |6 
 net/wireless/nl80211.c   |   71 --
 3 files changed, 82 insertions(+), 10 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 56e905c..d19fd5c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5706,6 +5706,21 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
  s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_ap_sta_cqm_rssi_notify - CQM rssi event for connected stations
+ * @dev: network device
+ * @mac: peer's MAC address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured connection quality monitoring
+ * rssi threshold reached event occurs for a station.
+ */
+void cfg80211_ap_sta_cqm_rssi_notify(struct net_device *dev, const u8 *mac,
+   enum nl80211_cqm_rssi_threshold_event rssi_event,
+   s32 rssi_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c13c843..81a60dc 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -49,6 +49,7 @@
 #define NL80211_MULTICAST_GROUP_MLME   "mlme"
 #define NL80211_MULTICAST_GROUP_VENDOR "vendor"
 #define NL80211_MULTICAST_GROUP_NAN"nan"
+#define NL80211_MULTICAST_GROUP_AP_STA_CQM "apstacqm"
 #define NL80211_MULTICAST_GROUP_TESTMODE   "testmode"
 
 /**
@@ -4999,6 +5000,10 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_LOW_SPAN_SCAN: Driver supports low span scan.
  * @NL80211_EXT_FEATURE_LOW_POWER_SCAN: Driver supports low power scan.
  * @NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN: Driver supports high accuracy scan.
+ * @NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG: With this driver will accept
+ * %NL80211_ATTR_CQM_RSSI_THOLD and %NL80211_ATTR_CQM_RSSI_HYST attributes
+ * for AP/AP_VLAN/P2P_GO interface to monitor rssi values of connected
+ * client.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5029,6 +5034,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_LOW_SPAN_SCAN,
NL80211_EXT_FEATURE_LOW_POWER_SCAN,
NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG,
 
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 050ff61..96ce1dd 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -43,6 +43,7 @@ enum nl80211_multicast_groups {
NL80211_MCGRP_MLME,
NL80211_MCGRP_VENDOR,
NL80211_MCGRP_NAN,
+   NL80211_MCGRP_AP_STA_CQM,
NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
 };
 
@@ -53,6 +54,8 @@ enum nl80211_multicast_groups {
[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
[NL80211_MCGRP_NAN] = { .name = NL80211_MULTICAST_GROUP_NAN },
+   [NL80211_MCGRP_AP_STA_CQM] = {
+   .name = NL80211_MULTICAST_GROUP_AP_STA_CQM },
 #ifdef CONFIG_NL80211_TESTMODE
[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
 #endif
@@ -9902,8 +9905,13 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
prev = thresholds[i];
}
 
-   if (wdev->iftype != NL80211_IFTYPE_STATION &&
-   wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+   if ((wdev->iftype != NL80211_IFTYPE_STATION &&
+wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) &&
+   ((wdev->iftype == NL80211_IFTYPE_AP ||
+ wdev->iftype == NL80211_IFTYPE_AP_VLAN ||
+ wdev->iftype == NL80211_IFTYPE_P2P_GO) &&
+!wiphy_ext_feature_isset(>wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG)))
return -EOPNOTSUPP;
 
wdev_lock(wdev);
@@ -14584,9 +14592,24 @@ static void cfg80211_send_cqm(struct sk_buff *msg, 
gfp_t gfp)
NL80211_MCGRP_MLME, gfp);
 }
 
-void cfg80211_cqm_rssi_notify(struct net_device *dev,
- 

[PATCHv3 2/3] mac80211: enable setting cqm rssi config for AP mode

2018-02-21 Thread Tamizh chelvam
From: Pradeep Kumar Chitrapu <prade...@codeaurora.org>

Enable connection monitoring for AP mode which makes it possible to
track signal strength of connected stations.

Co-Developed-by: Tamizh Chelvam <tami...@codeaurora.org>
Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
Signed-off-by: Pradeep Kumar Chitrapu <prade...@codeaurora.org>
---
 net/mac80211/cfg.c |   31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 46028e1..ca95733 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2689,6 +2689,25 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, 
struct net_device *dev,
return 0;
 }
 
+static void ieee80211_update_rssi_config(struct ieee80211_sub_if_data *sdata)
+{
+   if (!(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
+   return;
+
+   /* tell the driver upon association, unless already associated */
+   if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+   !sdata->u.mgd.associated)
+   return;
+
+   /* if AP, always tell the driver by checking beacon status */
+   if (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG))
+   return;
+
+   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+}
+
 static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 struct net_device *dev,
 s32 rssi_thold, u32 rssi_hyst)
@@ -2711,11 +2730,7 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy 
*wiphy,
bss_conf->cqm_rssi_high = 0;
sdata->u.mgd.last_cqm_event_signal = 0;
 
-   /* tell the driver upon association, unless already associated */
-   if (sdata->u.mgd.associated &&
-   sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
-
+   ieee80211_update_rssi_config(sdata);
return 0;
 }
 
@@ -2736,11 +2751,7 @@ static int ieee80211_set_cqm_rssi_range_config(struct 
wiphy *wiphy,
bss_conf->cqm_rssi_hyst = 0;
sdata->u.mgd.last_cqm_event_signal = 0;
 
-   /* tell the driver upon association, unless already associated */
-   if (sdata->u.mgd.associated &&
-   sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
-
+   ieee80211_update_rssi_config(sdata);
return 0;
 }
 
-- 
1.7.9.5



[PATCHv3 0/3] cfg80211/mac80211: cqm rssi config for AP mode

2018-02-21 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

Currently station mode has the support of rssi based cqm. This patchsets
extended the support for AP mode as well. Already netlink accepts mac
address in cqm notification event. We can use that to pass mac address of
the station to specify its rssi change event. This patchsets introduce
new api cfg80211_ap_sta_cqm_notify and multicast group to notify the event.

Pradeep Kumar Chitrapu (1):
  mac80211: enable setting cqm rssi config for AP mode

Tamizh chelvam (2):
  cfg80211: enable setting cqm rssi config for AP mode
  mac80211: implement cqm rssi check using rx data signal

v3:
  * Added vif type check to avoid enable this feature for all mode.

V2:
  * Removed changing existing ieee80211_cqm_rssi_notify api changes.
  * Introduced new ext feature bit and multicast group id to support this
feature.

 include/net/cfg80211.h   |   15 +
 include/net/mac80211.h   |7 +
 include/uapi/linux/nl80211.h |6 
 net/mac80211/cfg.c   |   31 --
 net/mac80211/rx.c|   46 ++-
 net/mac80211/sta_info.h  |3 ++
 net/wireless/nl80211.c   |   71 --
 7 files changed, 158 insertions(+), 21 deletions(-)

-- 
1.7.9.5



[PATCHv3 3/3] mac80211: implement cqm rssi check using rx data signal

2018-02-21 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

Triggers cfg80211_ap_sta_cqm_rssi_notify with the corresponding event
when station signal goes lower than the configured rssi threshold. And
notify back to user space once the station signal becomes greater than
the configured value. It uses rx data signal and compare with rssi value
given by user. This rssi threshold is bss specific and it is common for
all the stations.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h  |7 +++
 net/mac80211/rx.c   |   46 +-
 net/mac80211/sta_info.h |3 +++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index dc3e9d9..e973bcd 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -800,6 +800,13 @@ enum mac80211_rate_control_flags {
 };
 
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 3fa15b0..7b60008 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1536,6 +1536,47 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf =
+   >sdata->vif.bss_conf;
+   int sig, last_event, thold;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (!bss_conf->cqm_rssi_thold || !bss_conf->enable_beacon) {
+   sta->count_rx_signal = 0;
+   return;
+   }
+
+   sig = -ewma_signal_read(>rx_stats_avg.signal);
+   last_event = sta->last_cqm_event_signal;
+   thold = bss_conf->cqm_rssi_thold;
+
+   if (sig < thold && last_event == 0) {
+   sta->last_cqm_event_signal = sig;
+   cfg80211_ap_sta_cqm_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   sta->count_rx_signal = 0;
+   } else if (last_event && sig > thold) {
+   sta->last_cqm_event_signal = 0;
+   cfg80211_ap_sta_cqm_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   sta->count_rx_signal = 0;
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1591,6 +1632,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -3985,9 +4027,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
 
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
-   if (!fast_rx->uses_rss)
+   if (!fast_rx->uses_rss) {
ewma_signal_add(>rx_stats_avg.signal,
-status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
+   }
}
 
if (status->chains) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index f64eb86..6aa1071 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -581,6 +581,9 @@ struct sta_info {
 
struct cfg80211_chan_def tdls_chandef;
 
+   int last_cqm_event_signal;
+   unsigned int count_rx_signal;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.7.9.5



Re: [PATCHv2 1/3] cfg80211: enable setting cqm rssi config for AP mode

2018-02-21 Thread Tamizh chelvam

On 2018-02-19 18:44, Johannes Berg wrote:

On Tue, 2018-02-13 at 14:50 +0530, Tamizh chelvam wrote:


@@ -9903,8 +9906,10 @@ static int nl80211_set_cqm_rssi(struct 
genl_info *info,

prev = thresholds[i];
}

-   if (wdev->iftype != NL80211_IFTYPE_STATION &&
-   wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+   if ((wdev->iftype != NL80211_IFTYPE_STATION &&
+wdev->iftype != NL80211_IFTYPE_P2P_CLIENT &&
+!wiphy_ext_feature_isset(>wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG)))
return -EOPNOTSUPP;


This enables for everything though - not sure we want that?


I'll add vif type(AP, AP_VLAN and P2P_GO) check in the next version to 
avoid enable this for all.


[PATCHv2 3/3] mac80211: implement cqm rssi check using rx data signal

2018-02-13 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

Triggers cfg80211_ap_sta_cqm_rssi_notify with the corresponding event
when station signal goes lower than the configured rssi threshold. And
notify back to user space once the station signal becomes greater than
the configured value. It uses rx data signal and compare with rssi value
given by user. This rssi threshold is bss specific and it is common for
all the stations.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/mac80211.h  |7 +++
 net/mac80211/rx.c   |   46 +-
 net/mac80211/sta_info.h |3 +++
 3 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 906e902..8fbf633 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -799,6 +799,13 @@ enum mac80211_rate_control_flags {
 };
 
 
+/*
+ * How many frames need to have been used in average station's
+ * signal strength before checking against the threshold
+ */
+#define IEEE80211_STA_SIGNAL_AVE_MIN_COUNT 4
+
+
 /* there are 40 bytes if you don't need the rateset to be kept */
 #define IEEE80211_TX_INFO_DRIVER_DATA_SIZE 40
 
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index e755f93..0a385a1 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1534,6 +1534,47 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
return RX_CONTINUE;
 }
 
+static void ieee80211_sta_rx_signal_thold_check(struct ieee80211_rx_data *rx)
+{
+   struct sta_info *sta = rx->sta;
+   struct ieee80211_bss_conf *bss_conf =
+   >sdata->vif.bss_conf;
+   int sig, last_event, thold;
+
+   if (!wiphy_ext_feature_isset(rx->local->hw.wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG))
+   return;
+
+   sta->count_rx_signal++;
+   if (sta->count_rx_signal < IEEE80211_STA_SIGNAL_AVE_MIN_COUNT)
+   return;
+
+   if (!bss_conf->cqm_rssi_thold || !bss_conf->enable_beacon) {
+   sta->count_rx_signal = 0;
+   return;
+   }
+
+   sig = -ewma_signal_read(>rx_stats_avg.signal);
+   last_event = sta->last_cqm_event_signal;
+   thold = bss_conf->cqm_rssi_thold;
+
+   if (sig < thold && last_event == 0) {
+   sta->last_cqm_event_signal = sig;
+   cfg80211_ap_sta_cqm_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+   sig, GFP_ATOMIC);
+   sta->count_rx_signal = 0;
+   } else if (last_event && sig > thold) {
+   sta->last_cqm_event_signal = 0;
+   cfg80211_ap_sta_cqm_rssi_notify(
+   rx->sdata->dev, sta->addr,
+   NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+   sig, GFP_ATOMIC);
+   sta->count_rx_signal = 0;
+   }
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
@@ -1589,6 +1630,7 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta 
*pubsta, u8 tid)
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
sta->rx_stats.last_signal = status->signal;
ewma_signal_add(>rx_stats_avg.signal, -status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
}
 
if (status->chains) {
@@ -3981,9 +4023,11 @@ static bool ieee80211_invoke_fast_rx(struct 
ieee80211_rx_data *rx,
 
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
stats->last_signal = status->signal;
-   if (!fast_rx->uses_rss)
+   if (!fast_rx->uses_rss) {
ewma_signal_add(>rx_stats_avg.signal,
-status->signal);
+   ieee80211_sta_rx_signal_thold_check(rx);
+   }
}
 
if (status->chains) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index cd53619..76e8877 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -579,6 +579,9 @@ struct sta_info {
 
struct cfg80211_chan_def tdls_chandef;
 
+   int last_cqm_event_signal;
+   unsigned int count_rx_signal;
+
/* keep last! */
struct ieee80211_sta sta;
 };
-- 
1.7.9.5



[PATCHv2 2/3] mac80211: enable setting cqm rssi config for AP mode

2018-02-13 Thread Tamizh chelvam
From: Pradeep Kumar Chitrapu <prade...@codeaurora.org>

Enable connection monitoring for AP mode which makes it possible to
track signal strength of connected stations.

Co-Developed-by: Tamizh Chelvam <tami...@codeaurora.org>
Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/cfg.c |   31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 46028e1..ca95733 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2689,6 +2689,25 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, 
struct net_device *dev,
return 0;
 }
 
+static void ieee80211_update_rssi_config(struct ieee80211_sub_if_data *sdata)
+{
+   if (!(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
+   return;
+
+   /* tell the driver upon association, unless already associated */
+   if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+   !sdata->u.mgd.associated)
+   return;
+
+   /* if AP, always tell the driver by checking beacon status */
+   if (!sdata->vif.bss_conf.enable_beacon ||
+   !wiphy_ext_feature_isset(sdata->local->hw.wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG))
+   return;
+
+   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
+}
+
 static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
 struct net_device *dev,
 s32 rssi_thold, u32 rssi_hyst)
@@ -2711,11 +2730,7 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy 
*wiphy,
bss_conf->cqm_rssi_high = 0;
sdata->u.mgd.last_cqm_event_signal = 0;
 
-   /* tell the driver upon association, unless already associated */
-   if (sdata->u.mgd.associated &&
-   sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
-
+   ieee80211_update_rssi_config(sdata);
return 0;
 }
 
@@ -2736,11 +2751,7 @@ static int ieee80211_set_cqm_rssi_range_config(struct 
wiphy *wiphy,
bss_conf->cqm_rssi_hyst = 0;
sdata->u.mgd.last_cqm_event_signal = 0;
 
-   /* tell the driver upon association, unless already associated */
-   if (sdata->u.mgd.associated &&
-   sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
-   ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
-
+   ieee80211_update_rssi_config(sdata);
return 0;
 }
 
-- 
1.7.9.5



[PATCHv2 1/3] cfg80211: enable setting cqm rssi config for AP mode

2018-02-13 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

This patch extend cqm rssi config and notifier feature to AP mode
by introducing NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG ext
feature bit. And this patch introduces NL80211_MCGRP_AP_STA_CQM
for notifying station's low/high rssi event to userspace application.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 include/net/cfg80211.h   |   15 ++
 include/uapi/linux/nl80211.h |6 
 net/wireless/nl80211.c   |   68 +++---
 3 files changed, 79 insertions(+), 10 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7d49cd0..179904f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -5704,6 +5704,21 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
  s32 rssi_level, gfp_t gfp);
 
 /**
+ * cfg80211_ap_sta_cqm_rssi_notify - CQM rssi event for connected stations
+ * @dev: network device
+ * @mac: peer's MAC address
+ * @rssi_event: the triggered RSSI event
+ * @rssi_level: new RSSI level value or 0 if not available
+ * @gfp: context flags
+ *
+ * This function is called when a configured connection quality monitoring
+ * rssi threshold reached event occurs for a station.
+ */
+void cfg80211_ap_sta_cqm_rssi_notify(struct net_device *dev, const u8 *mac,
+   enum nl80211_cqm_rssi_threshold_event rssi_event,
+   s32 rssi_level, gfp_t gfp);
+
+/**
  * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
  * @dev: network device
  * @peer: peer's MAC address
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index ca3d5a6..9448bba 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -49,6 +49,7 @@
 #define NL80211_MULTICAST_GROUP_MLME   "mlme"
 #define NL80211_MULTICAST_GROUP_VENDOR "vendor"
 #define NL80211_MULTICAST_GROUP_NAN"nan"
+#define NL80211_MULTICAST_GROUP_AP_STA_CQM "apstacqm"
 #define NL80211_MULTICAST_GROUP_TESTMODE   "testmode"
 
 /**
@@ -4996,6 +4997,10 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_LOW_SPAN_SCAN: Driver supports low span scan.
  * @NL80211_EXT_FEATURE_LOW_POWER_SCAN: Driver supports low power scan.
  * @NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN: Driver supports high accuracy scan.
+ * @NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG: With this driver the
+ * non P2P/STA interface accept %NL80211_ATTR_CQM_RSSI_THOLD  and
+ * %NL80211_ATTR_CQM_RSSI_HYST attributes to monitor connected clients
+ * rssi values.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -5026,6 +5031,7 @@ enum nl80211_ext_feature_index {
NL80211_EXT_FEATURE_LOW_SPAN_SCAN,
NL80211_EXT_FEATURE_LOW_POWER_SCAN,
NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG,
 
/* add new features before the definition below */
NUM_NL80211_EXT_FEATURES,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index cc6ec5b..68627a7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -43,6 +43,7 @@ enum nl80211_multicast_groups {
NL80211_MCGRP_MLME,
NL80211_MCGRP_VENDOR,
NL80211_MCGRP_NAN,
+   NL80211_MCGRP_AP_STA_CQM,
NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
 };
 
@@ -53,6 +54,8 @@ enum nl80211_multicast_groups {
[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
[NL80211_MCGRP_NAN] = { .name = NL80211_MULTICAST_GROUP_NAN },
+   [NL80211_MCGRP_AP_STA_CQM] = {
+   .name = NL80211_MULTICAST_GROUP_AP_STA_CQM },
 #ifdef CONFIG_NL80211_TESTMODE
[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
 #endif
@@ -9903,8 +9906,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info,
prev = thresholds[i];
}
 
-   if (wdev->iftype != NL80211_IFTYPE_STATION &&
-   wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)
+   if ((wdev->iftype != NL80211_IFTYPE_STATION &&
+wdev->iftype != NL80211_IFTYPE_P2P_CLIENT &&
+!wiphy_ext_feature_isset(>wiphy,
+   NL80211_EXT_FEATURE_AP_STA_CQM_RSSI_CONFIG)))
return -EOPNOTSUPP;
 
wdev_lock(wdev);
@@ -14601,9 +14606,24 @@ static void cfg80211_send_cqm(struct sk_buff *msg, 
gfp_t gfp)
NL80211_MCGRP_MLME, gfp);
 }
 
-void cfg80211_cqm_rssi_notify(struct net_device *dev,
- enum nl80211_cqm_rssi_threshold_event rssi_event,
- s32 rssi_level, gfp_t gfp)
+static void cfg80211_send_ap_sta_cqm(struct sk_buff *msg, gfp

[PATCHv2 0/3] cfg80211/mac80211: cqm rssi config for AP mode

2018-02-13 Thread Tamizh chelvam
From: Tamizh chelvam <tami...@codeaurora.org>

Currently station mode has the support of rssi based cqm. This patchsets
extended the support for AP mode as well. Already netlink accepts mac
address in cqm notification event. We can use that to pass mac address of
the station to specify its rssi change event. This patchsets introduce
new api cfg80211_ap_sta_cqm_notify and multicast group to notify the event.

Pradeep Kumar Chitrapu (1):
  mac80211: enable setting cqm rssi c onfig for AP mode

Tamizh chelvam (2):
  cfg80211: enable setting cqm rssi config for AP mode
  mac80211: implement cqm rssi check using rx data signal

V2:
  * Removed changing existing ieee80211_cqm_rssi_notify api changes.
  * Introduced new ext feature bit and multicast group id to support this
feature.

 include/net/cfg80211.h   |   15 ++
 include/net/mac80211.h   |7 +
 include/uapi/linux/nl80211.h |6 
 net/mac80211/cfg.c   |   31 ---
 net/mac80211/rx.c|   46 +++-
 net/mac80211/sta_info.h  |3 ++
 net/wireless/nl80211.c   |   68 +++---
 7 files changed, 155 insertions(+), 21 deletions(-)

-- 
1.7.9.5



[PATCHv3 2/2] mac80211: Add support to notify ht/vht opmode modification.

2018-01-31 Thread Tamizh chelvam
This will add support to send an event to a userspace application
whenever station advertise its ht/vht opmode modification through
an action frame.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
v3:
  * Initialized the sta_opmode_info structure variable before using

 net/mac80211/rx.c  | 14 ++
 net/mac80211/vht.c |  9 +
 2 files changed, 23 insertions(+)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index fd58061..e755f93 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2848,6 +2848,7 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
case WLAN_HT_ACTION_SMPS: {
struct ieee80211_supported_band *sband;
enum ieee80211_smps_mode smps_mode;
+   struct sta_opmode_info sta_opmode = {};
 
/* convert to HT capability */
switch (mgmt->u.action.u.ht_smps.smps_control) {
@@ -2868,17 +2869,24 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
if (rx->sta->sta.smps_mode == smps_mode)
goto handled;
rx->sta->sta.smps_mode = smps_mode;
+   sta_opmode.smps_mode = smps_mode;
+   sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED;
 
sband = rx->local->hw.wiphy->bands[status->band];
 
rate_control_rate_update(local, sband, rx->sta,
 IEEE80211_RC_SMPS_CHANGED);
+   cfg80211_sta_opmode_change_notify(sdata->dev,
+ rx->sta->addr,
+ _opmode,
+ GFP_KERNEL);
goto handled;
}
case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
struct ieee80211_supported_band *sband;
u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
enum ieee80211_sta_rx_bandwidth max_bw, new_bw;
+   struct sta_opmode_info sta_opmode = {};
 
/* If it doesn't support 40 MHz it can't change ... */
if (!(rx->sta->sta.ht_cap.cap &
@@ -2899,9 +2907,15 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
 
rx->sta->sta.bandwidth = new_bw;
sband = rx->local->hw.wiphy->bands[status->band];
+   sta_opmode.bw = new_bw;
+   sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
 
rate_control_rate_update(local, sband, rx->sta,
 IEEE80211_RC_BW_CHANGED);
+   cfg80211_sta_opmode_change_notify(sdata->dev,
+ rx->sta->addr,
+ _opmode,
+ GFP_KERNEL);
goto handled;
}
default:
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index b9276ac..5714dee 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -447,6 +447,7 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
  enum nl80211_band band)
 {
enum ieee80211_sta_rx_bandwidth new_bw;
+   struct sta_opmode_info sta_opmode = {};
u32 changed = 0;
u8 nss;
 
@@ -460,7 +461,9 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
 
if (sta->sta.rx_nss != nss) {
sta->sta.rx_nss = nss;
+   sta_opmode.rx_nss = nss;
changed |= IEEE80211_RC_NSS_CHANGED;
+   sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
}
 
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
@@ -481,9 +484,15 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
new_bw = ieee80211_sta_cur_vht_bw(sta);
if (new_bw != sta->sta.bandwidth) {
sta->sta.bandwidth = new_bw;
+   sta_opmode.bw = new_bw;
changed |= IEEE80211_RC_BW_CHANGED;
+   sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
}
 
+   if (sta_opmode.changed)
+   cfg80211_sta_opmode_change_notify(sdata->dev, sta->addr,
+ _opmode, GFP_KERNEL);
+
return changed;
 }
 
-- 
1.9.1



[PATCHv3 1/2] cfg80211: Add support to notify station's opmode change to userspace

2018-01-31 Thread Tamizh chelvam
ht/vht action frames will be sent to AP from station to notify
change of its ht/vht opmode(max bandwidth, smps mode or nss) modified
values. Currently these valuse used by driver/firmware for rate control
algorithm. This patch introduces NL80211_CMD_STA_OPMODE_CHANGED
command to notify those modified/current supported values(max bandwidth,
smps mode, max nss) to userspace application. This will be useful for the
application like steering, which closely monitoring station's capability
changes. Since the application has taken these values during station
association.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
v3:
  * Initialized the sta_opmode_info structure variable before using
v2:
  * Addressed Johannes's comments

 include/net/cfg80211.h   | 43 ++
 include/uapi/linux/nl80211.h | 12 ++
 net/wireless/nl80211.c   | 55 
 3 files changed, 110 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 81174f9..81caf86 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3517,6 +3517,35 @@ enum wiphy_vendor_command_flags {
 };
 
 /**
+ * enum wiphy_opmode_flag - Station's ht/vht operation mode information flags
+ *
+ * @STA_OPMODE_MAX_BW_CHANGED: Max Bandwidth changed
+ * @STA_OPMODE_SMPS_MODE_CHANGED: SMPS mode changed
+ * @STA_OPMODE_N_SS_CHANGED: max N_SS (number of spatial streams) changed
+ *
+ */
+enum wiphy_opmode_flag {
+   STA_OPMODE_MAX_BW_CHANGED   = BIT(0),
+   STA_OPMODE_SMPS_MODE_CHANGED= BIT(1),
+   STA_OPMODE_N_SS_CHANGED = BIT(2),
+};
+
+/**
+ * struct sta_opmode_info - Station's ht/vht operation mode information
+ * @changed: contains value from  wiphy_opmode_flag
+ * @smps_mode: New SMPS mode of a station
+ * @bw: new max bandwidth value of a station
+ * @rx_nss: new rx_nss value of a station
+ */
+
+struct sta_opmode_info {
+   u32 changed;
+   u8 smps_mode;
+   u8 bw;
+   u8 rx_nss;
+};
+
+/**
  * struct wiphy_vendor_command - vendor command definition
  * @info: vendor command identifying information, as used in nl80211
  * @flags: flags, see  wiphy_vendor_command_flags
@@ -5685,6 +5714,20 @@ void cfg80211_radar_event(struct wiphy *wiphy,
  struct cfg80211_chan_def *chandef, gfp_t gfp);
 
 /**
+ * cfg80211_sta_opmode_change_notify - STA's ht/vht operation mode change event
+ * @dev: network device
+ * @mac: MAC address of a station which opmode got modified
+ * @sta_opmode: station's current opmode value
+ * @gfp: context flags
+ *
+ * Driver should call this function when station's opmode modified via action
+ * frame.
+ */
+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
+  struct sta_opmode_info *sta_opmode,
+  gfp_t gfp);
+
+/**
  * cfg80211_cac_event - Channel availability check (CAC) event
  * @netdev: network device
  * @chandef: chandef for the current channel
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c587a61..b3b449f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -992,6 +992,11 @@
  *
  * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
  *
+ * @NL80211_CMD_STA_OPMODE_CHANGED: An event that notify station's
+ * ht opmode or vht opmode changes using any of _ATTR_SMPS_MODE,
+ * _ATTR_CHANNEL_WIDTH,_ATTR_NSS attributes with its
+ * address(specified in _ATTR_MAC).
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1198,6 +1203,8 @@ enum nl80211_commands {
 
NL80211_CMD_RELOAD_REGDB,
 
+   NL80211_CMD_STA_OPMODE_CHANGED,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -2153,6 +2160,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
  * @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
  *
+ * @NL80211_ATTR_NSS: Station's New/updated  RX_NSS value notified using this
+ * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2579,6 +2589,8 @@ enum nl80211_attrs {
NL80211_ATTR_PMKR0_NAME,
NL80211_ATTR_PORT_AUTHORIZED,
 
+   NL80211_ATTR_NSS,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ab0c687..733259f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14887,6 +14887,61 @@ void cfg80211_ch_switch_started_notify(struct 
net_device *dev,
nlmsg_free(msg);
 }
 
+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u

[PATCHv2 2/2] mac80211: Add support to notify ht/vht opmode modification.

2018-01-25 Thread Tamizh chelvam
This will add support to send an event to a userspace application
whenever station advertise its ht/vht opmode modification through
an action frame.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
 net/mac80211/rx.c  | 14 ++
 net/mac80211/vht.c |  9 +
 2 files changed, 23 insertions(+)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index fd58061..d1efe8a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2848,6 +2848,7 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
case WLAN_HT_ACTION_SMPS: {
struct ieee80211_supported_band *sband;
enum ieee80211_smps_mode smps_mode;
+   struct sta_opmode_info sta_opmode;
 
/* convert to HT capability */
switch (mgmt->u.action.u.ht_smps.smps_control) {
@@ -2868,17 +2869,24 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
if (rx->sta->sta.smps_mode == smps_mode)
goto handled;
rx->sta->sta.smps_mode = smps_mode;
+   sta_opmode.smps_mode = smps_mode;
+   sta_opmode.changed = STA_OPMODE_SMPS_MODE_CHANGED;
 
sband = rx->local->hw.wiphy->bands[status->band];
 
rate_control_rate_update(local, sband, rx->sta,
 IEEE80211_RC_SMPS_CHANGED);
+   cfg80211_sta_opmode_change_notify(sdata->dev,
+ rx->sta->addr,
+ _opmode,
+ GFP_KERNEL);
goto handled;
}
case WLAN_HT_ACTION_NOTIFY_CHANWIDTH: {
struct ieee80211_supported_band *sband;
u8 chanwidth = mgmt->u.action.u.ht_notify_cw.chanwidth;
enum ieee80211_sta_rx_bandwidth max_bw, new_bw;
+   struct sta_opmode_info sta_opmode;
 
/* If it doesn't support 40 MHz it can't change ... */
if (!(rx->sta->sta.ht_cap.cap &
@@ -2899,9 +2907,15 @@ static void ieee80211_process_sa_query_req(struct 
ieee80211_sub_if_data *sdata,
 
rx->sta->sta.bandwidth = new_bw;
sband = rx->local->hw.wiphy->bands[status->band];
+   sta_opmode.bw = new_bw;
+   sta_opmode.changed = STA_OPMODE_MAX_BW_CHANGED;
 
rate_control_rate_update(local, sband, rx->sta,
 IEEE80211_RC_BW_CHANGED);
+   cfg80211_sta_opmode_change_notify(sdata->dev,
+ rx->sta->addr,
+ _opmode,
+ GFP_KERNEL);
goto handled;
}
default:
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index b9276ac..5f5db8e 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -447,6 +447,7 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
  enum nl80211_band band)
 {
enum ieee80211_sta_rx_bandwidth new_bw;
+   struct sta_opmode_info sta_opmode;
u32 changed = 0;
u8 nss;
 
@@ -460,7 +461,9 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
 
if (sta->sta.rx_nss != nss) {
sta->sta.rx_nss = nss;
+   sta_opmode.rx_nss = nss;
changed |= IEEE80211_RC_NSS_CHANGED;
+   sta_opmode.changed |= STA_OPMODE_N_SS_CHANGED;
}
 
switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) {
@@ -481,9 +484,15 @@ u32 __ieee80211_vht_handle_opmode(struct 
ieee80211_sub_if_data *sdata,
new_bw = ieee80211_sta_cur_vht_bw(sta);
if (new_bw != sta->sta.bandwidth) {
sta->sta.bandwidth = new_bw;
+   sta_opmode.bw = new_bw;
changed |= IEEE80211_RC_BW_CHANGED;
+   sta_opmode.changed |= STA_OPMODE_MAX_BW_CHANGED;
}
 
+   if (sta_opmode.changed)
+   cfg80211_sta_opmode_change_notify(sdata->dev, sta->addr,
+ _opmode, GFP_KERNEL);
+
return changed;
 }
 
-- 
1.9.1



[PATCHv2 1/2] cfg80211: Add support to notify station's opmode change to userspace

2018-01-25 Thread Tamizh chelvam
ht/vht action frames will be sent to AP from station to notify
change of its ht/vht opmode(max bandwidth, smps mode or nss) modified
values. Currently these valuse used by driver/firmware for rate control
algorithm. This patch introduces NL80211_CMD_STA_OPMODE_CHANGED
command to notify those modified/current supported values(max bandwidth,
smps mode, max nss) to userspace application. This will be useful for the
application like steering, which closely monitoring station's capability
changes. Since the application has taken these values during station
association.

Signed-off-by: Tamizh chelvam <tami...@codeaurora.org>
---
v2:
  * Address Johannes comments.

 include/net/cfg80211.h   | 43 ++
 include/uapi/linux/nl80211.h | 12 ++
 net/wireless/nl80211.c   | 55 
 3 files changed, 110 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 81174f9..81caf86 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3517,6 +3517,35 @@ enum wiphy_vendor_command_flags {
 };
 
 /**
+ * enum wiphy_opmode_flag - Station's ht/vht operation mode information flags
+ *
+ * @STA_OPMODE_MAX_BW_CHANGED: Max Bandwidth changed
+ * @STA_OPMODE_SMPS_MODE_CHANGED: SMPS mode changed
+ * @STA_OPMODE_N_SS_CHANGED: max N_SS (number of spatial streams) changed
+ *
+ */
+enum wiphy_opmode_flag {
+   STA_OPMODE_MAX_BW_CHANGED   = BIT(0),
+   STA_OPMODE_SMPS_MODE_CHANGED= BIT(1),
+   STA_OPMODE_N_SS_CHANGED = BIT(2),
+};
+
+/**
+ * struct sta_opmode_info - Station's ht/vht operation mode information
+ * @changed: contains value from  wiphy_opmode_flag
+ * @smps_mode: New SMPS mode of a station
+ * @bw: new max bandwidth value of a station
+ * @rx_nss: new rx_nss value of a station
+ */
+
+struct sta_opmode_info {
+   u32 changed;
+   u8 smps_mode;
+   u8 bw;
+   u8 rx_nss;
+};
+
+/**
  * struct wiphy_vendor_command - vendor command definition
  * @info: vendor command identifying information, as used in nl80211
  * @flags: flags, see  wiphy_vendor_command_flags
@@ -5685,6 +5714,20 @@ void cfg80211_radar_event(struct wiphy *wiphy,
  struct cfg80211_chan_def *chandef, gfp_t gfp);
 
 /**
+ * cfg80211_sta_opmode_change_notify - STA's ht/vht operation mode change event
+ * @dev: network device
+ * @mac: MAC address of a station which opmode got modified
+ * @sta_opmode: station's current opmode value
+ * @gfp: context flags
+ *
+ * Driver should call this function when station's opmode modified via action
+ * frame.
+ */
+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
+  struct sta_opmode_info *sta_opmode,
+  gfp_t gfp);
+
+/**
  * cfg80211_cac_event - Channel availability check (CAC) event
  * @netdev: network device
  * @chandef: chandef for the current channel
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index c587a61..b3b449f 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -992,6 +992,11 @@
  *
  * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
  *
+ * @NL80211_CMD_STA_OPMODE_CHANGED: An event that notify station's
+ * ht opmode or vht opmode changes using any of _ATTR_SMPS_MODE,
+ * _ATTR_CHANNEL_WIDTH,_ATTR_NSS attributes with its
+ * address(specified in _ATTR_MAC).
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1198,6 +1203,8 @@ enum nl80211_commands {
 
NL80211_CMD_RELOAD_REGDB,
 
+   NL80211_CMD_STA_OPMODE_CHANGED,
+
/* add new commands above here */
 
/* used to define NL80211_CMD_MAX below */
@@ -2153,6 +2160,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
  * @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
  *
+ * @NL80211_ATTR_NSS: Station's New/updated  RX_NSS value notified using this
+ * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2579,6 +2589,8 @@ enum nl80211_attrs {
NL80211_ATTR_PMKR0_NAME,
NL80211_ATTR_PORT_AUTHORIZED,
 
+   NL80211_ATTR_NSS,
+
/* add attributes here, update the policy in nl80211.c */
 
__NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ab0c687..733259f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14887,6 +14887,61 @@ void cfg80211_ch_switch_started_notify(struct 
net_device *dev,
nlmsg_free(msg);
 }
 
+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const u8 *mac,
+  struct sta_opmode_info *sta_

Re: [PATCH 1/2] cfg80211: Add support to notify station's opmode change to userspace

2018-01-23 Thread Tamizh chelvam

Hi Johannes,

Thanks for the code review comments, I'll address these comments and 
send V2 patchset.




 /**
+ * enum wiphy_opmode_info_flag - opmode information flags
+ *
+ * @MAX_BW_CHANGED: Max Bandwidth changed
+ * @SMPS_MODE_CHANGED: SMPS mode changed
+ * @N_SS_CHANGED: max N_SS (number of spatial streams) changed
+ *
+ */
+enum wiphy_opmode_info_flag {
+   MAX_BW_CHANGED  = BIT(0),
+   SMPS_MODE_CHANGED   = BIT(1),
+   N_SS_CHANGED= BIT(2),
+};


These need to have some kind of common prefix, e.g.
STA_OPMODE_{BW,SMPS,NSS}_CHANGED



 /**
+ * cfg80211_sta_opmode_change_notify - Station's SMPS mode, rx_nss 
and

+ * max bandwidth change event


need to find a shorter description - must fit on one line


+ * @dev: network device
+ * @mac: MAC address of a station which opmode got modified
+ * @changed: contains value from  wiphy_opmode_info_flag
+ * @smps_mode: New SMPS mode of a station
+ * @bw: new max bandwidth value of a station
+ * @rx_nss: new rx_nss value of a station
+ * @gfp: context flags
+ *
+ * This function is called when station's opmode modified via action 
frame.


Rephrase, say "Drivers should call this function when ..."

+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const 
u8 *mac,

+  enum wiphy_opmode_info_flag changed,
+  u8 smps_mode, u8 bw, u8 rx_nss,
+  gfp_t gfp);


We may not want to add more, but pulling out those parameters "changed,
smps_mode, bw, rx_nss" into a small structure would IMHO be a good
idea.


+ * @NL80211_CMD_STA_OPMODE_CHANGED: An event that notify station's
+ *	ht opmode or vht opmode changes. This will use 
_ATTR_SMPS_MODE,
+ *	_ATTR_CHANNEL_WIDTH, _ATTR_NSS to send the event 
to

+ * userspace.


Should document that not all of those attributes may be included at all
times.

+void cfg80211_sta_opmode_change_notify(struct net_device *dev, const 
u8 *mac,

+  enum wiphy_opmode_info_flag changed,
+  u8 smps, u8 bw, u8 rx_nss, gfp_t gfp)
+{
+   struct sk_buff *msg;
+   struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = 
wiphy_to_rdev(wdev->wiphy);

+   void *hdr;
+
+   if (!mac)
+   return;


WARN_ON(), perhaps


+   if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
+   goto nla_put_failure;


no need to check mac != NULL again


+nla_put_failure:
+   genlmsg_cancel(msg, hdr);


no need for cancel when you're going to free the message

johannes


RE: [PATCHv4 0/2] cfg80211: mac80211: BTCOEX feature support

2017-04-12 Thread Tamizh Chelvam Raja
> + linux-bluetooth, Marcel
> 
> On 11-4-2017 12:15, c_tr...@qti.qualcomm.com wrote:
> > From: Tamizh chelvam <c_tr...@qti.qualcomm.com>
> >
> > This patchset add support for BTCOEX feature to enable/disable and
> > modifying btcoex priority value via nl80211
> 
> So you make a distinction between WMM ACs, but what about the different
> types/profiles of BT traffic?
>
[Tamizh] There will be BT high and BT low traffic. It will be decided by BT 
module. Firmware internally checks BT low traffic with wlan traffic. If we 
enable some of
wlan frames as high priority, those frames will have more priority than BT low 
traffic.
 
> Regards,
> Arend
> 
> > Tamizh chelvam (2):
> >   cfg80211: Add support to enable or disable btcoex and set
> > btcoex_priority
> >   mac80211: Add support to enable or disable btcoex and set btcoex
> > priority value
> >
> > v4 :
> >   * Moved btcoex_priority_support_flag enum to nl80211.h and renamed it.
> >   * fixed typo.
> >
> > v3 :
> >   * Introduced NL80211_EXT_FEATURE_BTCOEX_PRIORITY to expose
> > btcoex priority support and removed bool variable.
> >
> > v2 :
> >   * Introduced NL80211_CMD_SET_BTCOEX to enable/disable btcoex and
> > to set/modify btcoex_priority.
> >   * Added bool variable in wiphy structure to advertise btcoex_priority
> > feature and removed BITMAP calculation for btcoex_priority value.
> >
> >  include/net/cfg80211.h   |6 +
> >  include/net/mac80211.h   |5 +
> >  include/uapi/linux/nl80211.h |   50
> ++
> >  net/mac80211/cfg.c   |9 
> >  net/mac80211/driver-ops.h|   15 +
> >  net/mac80211/trace.h |   20 +
> >  net/wireless/nl80211.c   |   45
> +
> >  net/wireless/rdev-ops.h  |   13 +++
> >  net/wireless/trace.h |   17 ++
> >  9 files changed, 180 insertions(+)
> >


RE: [PATCHv2 3/4] cfg80211: Add Support set btcoex priority value

2017-03-02 Thread Raja, Tamizh Chelvam

> 
> > > I think you need to define the bits somewhere in an enum - i.e.
> > > which one is VO,
> > > VI, ...
> > >
> >
> > [Tamizh] ok sure. Is this for documentation purpose or do you want me
> > to use that  enum for something else?
> 
> Well I think you should check in cfg80211 that no bits not defined in the enum
> are used, 
[Tamizh] I'm planning to do this check in iw itself and converting into a 
value, 

iw command will looks like below

iw btcoex enable []

If anything other than this given by user will be rejected and will not forward 
to cfg80211.
Do you have any concern on this?

>and then in the driver you need to use that enum to translate to the
> firmware API, right?
> 
[Tamizh] Yes, we can have this for checking invalid or the value is greater the 
driver support value


RE: [PATCHv2 1/4] cfg80211: Add support to enable or disable btcoex

2017-03-02 Thread Raja, Tamizh Chelvam
Hi Johannes,

Thanks for the comments.

> You need to fix the build-bot warning, it's legitimate (though hard to
> spot):
> 
> > +   TP_printk(WIPHY_PR_FMT, ", enabled=%d",
> > +     WIPHY_PR_ARG, __entry->enabled)
> > +);
> 
> You have a stray comma there after WIPHY_PR_FMT.
> 
[Tamizh] Yes:( Will fix it in the next version.


RE: [PATCHv2 3/4] cfg80211: Add Support set btcoex priority value

2017-03-02 Thread Raja, Tamizh Chelvam
> Is there much point in having 4 rather than just 2 patches?
>
[Tamizh] Yes, I agree to it. 
> 
> > +   int (*set_btcoex)(struct wiphy *wiphy, bool enabled,
> > +     int btcoex_priority);
> 
> Shouldn't that be u32 as a bitmap?
> 
[Tamizh] Yes.

> > +   bool btcoex_priority_support;
> 
> Why not use an extended nl80211 feature flag directly?
> 
[Tamizh] Ok sure. I'll use extended nl80211 feature flag.

> > + * @NL80211_ATTR_BTCOEX_PRIORITY: This is for the driver which
> > + * support btcoex priority feature. It used with
> > %NL80211_CMD_SET_BTCOEX.
> > + * This will have u32 BITMAP value which represents
> > + * frame(bk, be, vi, vo, mgmt, beacon) type and that will have
> > more
> > + * priority than a BT traffic.
> 
> I think you need to define the bits somewhere in an enum - i.e. which one is 
> VO,
> VI, ...
>
[Tamizh] ok sure. Is this for documentation purpose or do you want me to use 
that 
enum for something else?
 
> > +   int btcoex_priority = -1;
> 
> That -1 is pretty useless, if the driver doesn't support it, hopefully it 
> won't look
> at the value at all?
> 
[Tamizh] Ok sure


RE: [PATCHv2 0/4] cfg80211: mac80211: BTCOEX feature support

2017-02-27 Thread Raja, Tamizh Chelvam
Hi Arend,

> >
> > This patchset add support for BTCOEX feature to enable/disable and
> > modifying btcoex priority value via nl80211
> >
> > Tamizh chelvam (4):
> >   ath10k: Add support to enable or disable btcoex via nl80211
> >   ath10k: Add support to update btcoex priority value via nl80211
> >   dt: bindings: add new dt entry for BTCOEX feature in qcom,ath10k.txt
> >   ath10k: Add support to read btcoex related data from DT
> 
> This cover letter does not seem to reflect the other patches that were sent to
> the wireless list as those are about cfg80211/mac80211; not ath10k?

[Tamizh] ath10k patches are under progress, will send it soon.

> 
> Regards,
> Arend
> 
> > v2 :
> >   * Introduced NL80211_CMD_SET_BTCOEX to enable/disable btcoex and
> > to set/modify btcoex_priority.
> >   * Added bool variable in wiphy structure to advertise btcoex_priority
> > feature and removed BITMAP calculation for btcoex_priority value.
> >
> >  .../bindings/net/wireless/qcom,ath10k.txt  |4 +
> >  drivers/net/wireless/ath/ath10k/core.c |   44 -
> >  drivers/net/wireless/ath/ath10k/core.h |9 ++
> >  drivers/net/wireless/ath/ath10k/debug.c|   40 ++---
> >  drivers/net/wireless/ath/ath10k/mac.c  |   94
> +++-
> >  drivers/net/wireless/ath/ath10k/mac.h  |1 +
> >  drivers/net/wireless/ath/ath10k/wmi-ops.h  |   19 
> >  drivers/net/wireless/ath/ath10k/wmi.c  |   20 +
> >  drivers/net/wireless/ath/ath10k/wmi.h  |   20 +
> >  9 files changed, 215 insertions(+), 36 deletions(-)
> >


RE: [PATCHv2] ath10k: Update available channel list for 5G radio

2017-02-19 Thread Raja, Tamizh Chelvam
Please ignore this patch:(

> -Original Message-
> From: Raja, Tamizh Chelvam
> Sent: Monday, February 20, 2017 10:37 AM
> To: ath...@lists.infradead.org
> Cc: linux-wireless@vger.kernel.org; Raja, Tamizh Chelvam
> <c_tr...@qti.qualcomm.com>
> Subject: [PATCHv2] ath10k: Update available channel list for 5G radio
> 
> From: Tamizh chelvam <c_tr...@qti.qualcomm.com>
> 
> If a 5 GHz radio is calibrated for operation in both the low band (channels 
> 36 to
> 64) and high band(channels 100 to 169), hardware allows operations in all the
> listed channels. However, if the chip has been calibrated only for the 
> low/high
> band and a high/low band channel is configured, due to lack of calibration
> there will be potentially invalid signal on those non calibrated channels.
> To avoid this problem this patch introduces ath10k_low_5ghz_channel and
> ath10k_high_5ghz_channel lists as separate arrays.
> The channel list will be initialized depending on the low_5ghz_chan and
> high_5ghz_chan values which we get from target through wmi service ready
> event.
> 
> Signed-off-by: Tamizh chelvam <c_tr...@qti.qualcomm.com>
> ---
> v2:
>   * Addressed Jouni and Kalle's comments
> 
>  drivers/net/wireless/ath/ath10k/core.h |2 ++
>  drivers/net/wireless/ath/ath10k/mac.c  |   55
> +---
>  drivers/net/wireless/ath/ath10k/wmi.c  |6 
>  drivers/net/wireless/ath/ath10k/wmi.h  |2 ++
>  4 files changed, 61 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/wireless/ath/ath10k/core.h
> b/drivers/net/wireless/ath/ath10k/core.h
> index 88d14be..d07d567 100644
> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -774,6 +774,8 @@ struct ath10k {
>   u32 vht_cap_info;
>   u32 num_rf_chains;
>   u32 max_spatial_stream;
> + u32 low_5ghz_chan;
> + u32 high_5ghz_chan;
>   /* protected by conf_mutex */
>   bool ani_enabled;
> 
> diff --git a/drivers/net/wireless/ath/ath10k/mac.c
> b/drivers/net/wireless/ath/ath10k/mac.c
> index 3029f25..0840efb 100644
> --- a/drivers/net/wireless/ath/ath10k/mac.c
> +++ b/drivers/net/wireless/ath/ath10k/mac.c
> @@ -7623,6 +7623,38 @@ static void
> ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
>   CHAN2G(14, 2484, 0),
>  };
> 
> +static const struct ieee80211_channel ath10k_low_5ghz_channels[] = {
> + CHAN5G(36, 5180, 0),
> + CHAN5G(40, 5200, 0),
> + CHAN5G(44, 5220, 0),
> + CHAN5G(48, 5240, 0),
> + CHAN5G(52, 5260, 0),
> + CHAN5G(56, 5280, 0),
> + CHAN5G(60, 5300, 0),
> + CHAN5G(64, 5320, 0),
> +};
> +
> +static const struct ieee80211_channel ath10k_high_5ghz_channels[] = {
> + CHAN5G(100, 5500, 0),
> + CHAN5G(104, 5520, 0),
> + CHAN5G(108, 5540, 0),
> + CHAN5G(112, 5560, 0),
> + CHAN5G(116, 5580, 0),
> + CHAN5G(120, 5600, 0),
> + CHAN5G(124, 5620, 0),
> + CHAN5G(128, 5640, 0),
> + CHAN5G(132, 5660, 0),
> + CHAN5G(136, 5680, 0),
> + CHAN5G(140, 5700, 0),
> + CHAN5G(144, 5720, 0),
> + CHAN5G(149, 5745, 0),
> + CHAN5G(153, 5765, 0),
> + CHAN5G(157, 5785, 0),
> + CHAN5G(161, 5805, 0),
> + CHAN5G(165, 5825, 0),
> + CHAN5G(169, 5845, 0),
> +};
> +
>  static const struct ieee80211_channel ath10k_5ghz_channels[] = {
>   CHAN5G(36, 5180, 0),
>   CHAN5G(40, 5200, 0),
> @@ -8014,6 +8046,7 @@ int ath10k_mac_register(struct ath10k *ar)
>   };
>   struct ieee80211_supported_band *band;
>   void *channels;
> + int n_channels;
>   int ret;
> 
>   SET_IEEE80211_PERM_ADDR(ar->hw, ar->mac_addr); @@ -8049,16
> +8082,30 @@ int ath10k_mac_register(struct ath10k *ar)
>   }
> 
>   if (ar->phy_capability & WHAL_WLAN_11A_CAPABILITY) {
> - channels = kmemdup(ath10k_5ghz_channels,
> -sizeof(ath10k_5ghz_channels),
> -GFP_KERNEL);
> + if (ar->high_5ghz_chan <= 5350) {
> + channels = kmemdup(ath10k_low_5ghz_channels,
> +sizeof(ath10k_low_5ghz_channels),
> +GFP_KERNEL);
> + n_channels = ARRAY_SIZE(ath10k_low_5ghz_channels);
> + } else if (ar->low_5ghz_chan >= 5490 &&
> +ar->high_5ghz_chan <= 5885) {
> + channels = kmemdup(ath10k_high_5ghz_channels,
> +sizeof(ath10k_high_5ghz_channels),
> +GFP_KERNEL);
&

Re: [PATCH 2/4] cfg80211: Add new NL80211_CMD_SET_BTCOEX_PRIORITY to support BTCOEX

2017-01-19 Thread Tamizh chelvam

Hi Johannes,

Sorry for the late response:(

On 2017-01-09 16:06, Johannes Berg wrote:

Is it fine to have something like this

1) We can have this btcoex_priority value as a optional value in
btcoex enable command like below

iw phyX btcoex_state  [prirority(vendor spcific
value)]

2) Or we can have seperate command for btcoex_priority as below

iw phyX set btcoex_priority 

Hopefully this will get rid off all the nl80211 bits.


That makes no sense.

If the bits are vendor specific, then there's no value in having this
as an nl80211 command (rather than a vendor command) to start with.

You need to understand that I'm differentiating between *capability*
bits and actual *priority setting* bits - please re-read the thread
with that in mind.

Those are for priority and not for capability purpose. Hardware is 
capable of
transmitting all the frames when there is a bt traffic. This is just 
setting priority for the wlan
frame, when there is a contention with BT traffic which one has to go 
out first.

Other than that hardware has the capability of sending all the frames.

This priority field is optional, if users does not want to set any 
priority then driver will force the

default priorities when bt_coex is enabled

iw phyX btcoex_state  [prirority]


Re: [PATCH 2/4] cfg80211: Add new NL80211_CMD_SET_BTCOEX_PRIORITY to support BTCOEX

2017-01-09 Thread Tamizh chelvam

Hi Johannes,

Thank you for the reply.

On 2017-01-05 19:08, Johannes Berg wrote:

> IOW - why have all these bits rather than just one?

Hardware supports data across all the access categories, this is
just  meant for prioritising the traffic. f.e, If the fw/target has
both wlan and bt traffic queued and if VO is  set as priority, then
wlan VO packets will be pushed out of the radio first and then the bt
traffic.


Exactly. So as far as *capabilities* are concerned, why do we need so
many bits?


Is it fine to have something like this

1) We can have this btcoex_priority value as a optional value in btcoex 
enable command like below


iw phyX btcoex_state  [prirority(vendor spcific value)]

2) Or we can have seperate command for btcoex_priority as below

iw phyX set btcoex_priority 

Hopefully this will get rid off all the nl80211 bits.

Kindly suggest your thoughts.

Thanks,
Tamizh.


Re: [PATCH 2/4] cfg80211: Add new NL80211_CMD_SET_BTCOEX_PRIORITY to support BTCOEX

2017-01-05 Thread Tamizh chelvam

On 2017-01-02 16:18, Johannes Berg wrote:

> 1) does it even make sense to split it out per AC? wouldn't it be
> weird
> if you supported this only for VO and BK, and not the others, or
> something like that?
>

It has support for BE, VI, management and beacon frames also.
Or do you meant to say like support only for VO and BK?


I mean - does it make sense for a piece of hardware to support only
VO/BK, without the others? I don't really see how that would make
sense, but maybe I'm missing something?

IOW - why have all these bits rather than just one?


Hardware supports data across all the access categories, this is just 
meant for prioritising the traffic.
f.e, If the fw/target has both wlan and bt traffic queued and if VO is 
set as priority, then wlan VO packets

will be pushed out of the radio first and then the bt traffic.

Here we do not block traffic either from wlan or BT, packets will 
definitely go out of the radio but traffic

arbitration will happen based on the priorities set.




> 2) Wouldn't it make more sense to define this in nl80211 and just
> pass the bitmap through to userspace? That would save quite a bit
> of netlink mangling complexity.
>

Please let me know if the below design/thought is fine to you.

iw phyX set btcoex_priority <[vi, vo, be, bk, mgmt, beacon]>


That seems fine, but I don't see how the iw command line is relevant to
the question of whether we pass flag attributes or a bitmap??


By this command user should give one or more than one frame types
for 
this btcoex priority,
we will parse that in "iw" and send as a single bitmap(less than
0x64)  to the driver?


Right, and also to nl80211. Why not?


Yes user space to nl80211 and to driver



johannes


  1   2   >