forked from Minki/linux
mac80211: correct MU-MIMO monitor follow functionality
The MU-MIMO monitor follow functionality is broken because it doesn't clear the MU-MIMO owner even if both follow features are disabled. Fix that, and while at it move the code into a new helper function. Call this also when creating a new monitor interface to prepare for an upcoming cfg80211 change allowing that. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
b0265024b8
commit
8c5e688944
@ -22,6 +22,49 @@
|
|||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "wme.h"
|
#include "wme.h"
|
||||||
|
|
||||||
|
static int ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
|
||||||
|
struct vif_params *params)
|
||||||
|
{
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
struct ieee80211_sub_if_data *monitor_sdata;
|
||||||
|
bool mu_mimo_groups = false;
|
||||||
|
bool mu_mimo_follow = false;
|
||||||
|
|
||||||
|
monitor_sdata = rtnl_dereference(local->monitor_sdata);
|
||||||
|
|
||||||
|
if (!monitor_sdata)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (params->vht_mumimo_groups) {
|
||||||
|
u64 membership;
|
||||||
|
|
||||||
|
BUILD_BUG_ON(sizeof(membership) != WLAN_MEMBERSHIP_LEN);
|
||||||
|
|
||||||
|
memcpy(monitor_sdata->vif.bss_conf.mu_group.membership,
|
||||||
|
params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN);
|
||||||
|
memcpy(monitor_sdata->vif.bss_conf.mu_group.position,
|
||||||
|
params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
|
||||||
|
WLAN_USER_POSITION_LEN);
|
||||||
|
ieee80211_bss_info_change_notify(monitor_sdata,
|
||||||
|
BSS_CHANGED_MU_GROUPS);
|
||||||
|
/* don't care about endianness - just check for 0 */
|
||||||
|
memcpy(&membership, params->vht_mumimo_groups,
|
||||||
|
WLAN_MEMBERSHIP_LEN);
|
||||||
|
mu_mimo_groups = membership != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->vht_mumimo_follow_addr) {
|
||||||
|
mu_mimo_follow =
|
||||||
|
is_valid_ether_addr(params->vht_mumimo_follow_addr);
|
||||||
|
ether_addr_copy(monitor_sdata->u.mntr.mu_follow_addr,
|
||||||
|
params->vht_mumimo_follow_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor_sdata->vif.mu_mimo_owner = mu_mimo_groups || mu_mimo_follow;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
|
static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
|
||||||
const char *name,
|
const char *name,
|
||||||
unsigned char name_assign_type,
|
unsigned char name_assign_type,
|
||||||
@ -38,9 +81,17 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
|
|||||||
if (err)
|
if (err)
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(err);
|
||||||
|
|
||||||
if (type == NL80211_IFTYPE_MONITOR && flags) {
|
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||||
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
|
||||||
sdata->u.mntr.flags = *flags;
|
if (type == NL80211_IFTYPE_MONITOR) {
|
||||||
|
err = ieee80211_set_mu_mimo_follow(sdata, params);
|
||||||
|
if (err) {
|
||||||
|
ieee80211_if_remove(sdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
sdata->u.mntr.flags = *flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
return wdev;
|
return wdev;
|
||||||
@ -76,24 +127,11 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
|
|||||||
|
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct ieee80211_sub_if_data *monitor_sdata;
|
int err;
|
||||||
u32 mu_mntr_cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER;
|
|
||||||
|
|
||||||
monitor_sdata = rtnl_dereference(local->monitor_sdata);
|
err = ieee80211_set_mu_mimo_follow(sdata, params);
|
||||||
if (monitor_sdata && params->vht_mumimo_groups) {
|
if (err)
|
||||||
memcpy(monitor_sdata->vif.bss_conf.mu_group.membership,
|
return err;
|
||||||
params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN);
|
|
||||||
memcpy(monitor_sdata->vif.bss_conf.mu_group.position,
|
|
||||||
params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
|
|
||||||
WLAN_USER_POSITION_LEN);
|
|
||||||
monitor_sdata->vif.mu_mimo_owner = true;
|
|
||||||
ieee80211_bss_info_change_notify(monitor_sdata,
|
|
||||||
BSS_CHANGED_MU_GROUPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (monitor_sdata && params->vht_mumimo_follow_addr)
|
|
||||||
ether_addr_copy(monitor_sdata->u.mntr.mu_follow_addr,
|
|
||||||
params->vht_mumimo_follow_addr);
|
|
||||||
|
|
||||||
if (!flags)
|
if (!flags)
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user