mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 03:27:44 -04:00
Here's a big pile of changes for this round.
We have
* a lot of regulatory code changes to deal with the
way newer Intel devices handle this
* a change to drop packets while disconnecting from
an AP instead of trying to wait for them
* a new attempt at improving the tailroom accounting
to not kick in too much for performance reasons
* improvements in wireless link statistics
* many other small improvements and small fixes that
didn't seem necessary for 3.19 (e.g. in hwsim which
is testing only code)
-----BEGIN PGP SIGNATURE-----
iQIcBAABCAAGBQJUt7WEAAoJEDBSmw7B7bqrVBoP/2EViE62HMmXdqG1SZWz8q9o
Iigq8STC/sT2WCx1pYm+tKuVW4LD2O3mCriGNP8A3RwzDZ6H7sKJYb1gV6QCPV6f
4+yT5VSAB3D3lHmp/bbyNsmKCBQ5uS4LVgDrokrkbGpacDu94PYS5Wv9t3x6PBVB
5Xjky6g6A/pSuxTIstSO9k5xkzNjaB1TxvVRz/gJrGcFQVkDFSlVbuTHUVxs8p+p
k6mwY/2WYijZkswWZVQTJLQlF9vRI7PYkKs5m8gz4pjNU48oFJoyu4IP3Z1Xj/Sm
zgT1C9rgp0Du74HYO2niGAvLWgKajAZuW5hIacDndUPjYQQBLgGs/bCJGSntM+x9
XoOdPixdFPT/58ijyYZlmHc8rxPOd2kHsVbwGplp8f195S4VO04D+ejfOaoAUFwX
v/kMvO3XIFmEH1jjkDAC3OTcRMYVMuENyWl7pFzxHIzPeRiEpQUd9iSdM4yol0F2
ZyWvKud4U75Sh+aCiDIIBETtdfCRFe12hgKs4COYbI/UYkGPTPrNei/uisopdubT
JC+7pZOYdSgoX12yVi6ds6DmKE/ZpIQyhIK4wTWgVoszbnfdb9Mw7mJEThwNRjeK
JJPsbuty7u8HWjXzEqHLoTV3BFv1cgRSJc5Wt0zfME+LzD7iQpEpv+QBAguwwChD
Osn55Z3FnKEmBdGcOIje
=vaEW
-----END PGP SIGNATURE-----
Merge tag 'mac80211-next-for-davem-2015-01-15' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Here's a big pile of changes for this round.
We have
* a lot of regulatory code changes to deal with the
way newer Intel devices handle this
* a change to drop packets while disconnecting from
an AP instead of trying to wait for them
* a new attempt at improving the tailroom accounting
to not kick in too much for performance reasons
* improvements in wireless link statistics
* many other small improvements and small fixes that
didn't seem necessary for 3.19 (e.g. in hwsim which
is testing only code)
Conflicts:
drivers/staging/rtl8723au/os_dep/ioctl_cfg80211.c
Minor overlapping changes.
Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
commit
27f097177d
72 changed files with 1617 additions and 766 deletions
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/sched.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include "nl80211.h"
|
||||
#include "core.h"
|
||||
#include "sysfs.h"
|
||||
|
|
@ -320,6 +321,20 @@ static void cfg80211_destroy_iface_wk(struct work_struct *work)
|
|||
rtnl_unlock();
|
||||
}
|
||||
|
||||
static void cfg80211_sched_scan_stop_wk(struct work_struct *work)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
rdev = container_of(work, struct cfg80211_registered_device,
|
||||
sched_scan_stop_wk);
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
/* exported functions */
|
||||
|
||||
struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
|
||||
|
|
@ -406,6 +421,7 @@ use_default_name:
|
|||
INIT_LIST_HEAD(&rdev->destroy_list);
|
||||
spin_lock_init(&rdev->destroy_list_lock);
|
||||
INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk);
|
||||
INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk);
|
||||
|
||||
#ifdef CONFIG_CFG80211_DEFAULT_PS
|
||||
rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
|
@ -560,6 +576,14 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
BIT(NL80211_IFTYPE_MONITOR)))
|
||||
wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
|
||||
|
||||
if (WARN_ON((wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) &&
|
||||
(wiphy->regulatory_flags &
|
||||
(REGULATORY_CUSTOM_REG |
|
||||
REGULATORY_STRICT_REG |
|
||||
REGULATORY_COUNTRY_IE_FOLLOW_POWER |
|
||||
REGULATORY_COUNTRY_IE_IGNORE))))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(wiphy->coalesce &&
|
||||
(!wiphy->coalesce->n_rules ||
|
||||
!wiphy->coalesce->n_patterns) &&
|
||||
|
|
@ -778,6 +802,7 @@ void wiphy_unregister(struct wiphy *wiphy)
|
|||
flush_work(&rdev->event_work);
|
||||
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
|
||||
flush_work(&rdev->destroy_work);
|
||||
flush_work(&rdev->sched_scan_stop_wk);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
|
||||
|
|
@ -858,6 +883,7 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
struct wireless_dev *wdev)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
|
||||
ASSERT_RTNL();
|
||||
ASSERT_WDEV_LOCK(wdev);
|
||||
|
|
@ -868,7 +894,8 @@ void __cfg80211_leave(struct cfg80211_registered_device *rdev,
|
|||
break;
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (rdev->sched_scan_req && dev == rdev->sched_scan_req->dev)
|
||||
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
||||
if (sched_scan_req && dev == sched_scan_req->dev)
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
|
|
@ -937,12 +964,17 @@ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_stop_iface);
|
||||
|
||||
static const struct rtnl_link_ops wireless_link_ops = {
|
||||
.kind = "wlan",
|
||||
};
|
||||
|
||||
static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
||||
unsigned long state, void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
|
||||
if (!wdev)
|
||||
return NOTIFY_DONE;
|
||||
|
|
@ -954,6 +986,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
switch (state) {
|
||||
case NETDEV_POST_INIT:
|
||||
SET_NETDEV_DEVTYPE(dev, &wiphy_type);
|
||||
dev->rtnl_link_ops = &wireless_link_ops;
|
||||
break;
|
||||
case NETDEV_REGISTER:
|
||||
/*
|
||||
|
|
@ -1007,8 +1040,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
|||
___cfg80211_scan_done(rdev, false);
|
||||
}
|
||||
|
||||
if (WARN_ON(rdev->sched_scan_req &&
|
||||
rdev->sched_scan_req->dev == wdev->netdev)) {
|
||||
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
||||
if (WARN_ON(sched_scan_req &&
|
||||
sched_scan_req->dev == wdev->netdev)) {
|
||||
__cfg80211_stop_sched_scan(rdev, false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,13 @@ struct cfg80211_registered_device {
|
|||
* the country on the country IE changed. */
|
||||
char country_ie_alpha2[2];
|
||||
|
||||
/*
|
||||
* the driver requests the regulatory core to set this regulatory
|
||||
* domain as the wiphy's. Only used for %REGULATORY_WIPHY_SELF_MANAGED
|
||||
* devices using the regulatory_set_wiphy_regd() API
|
||||
*/
|
||||
const struct ieee80211_regdomain *requested_regd;
|
||||
|
||||
/* If a Country IE has been received this tells us the environment
|
||||
* which its telling us its in. This defaults to ENVIRON_ANY */
|
||||
enum environment_cap env;
|
||||
|
|
@ -63,7 +70,7 @@ struct cfg80211_registered_device {
|
|||
u32 bss_generation;
|
||||
struct cfg80211_scan_request *scan_req; /* protected by RTNL */
|
||||
struct sk_buff *scan_msg;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
struct cfg80211_sched_scan_request __rcu *sched_scan_req;
|
||||
unsigned long suspend_at;
|
||||
struct work_struct scan_done_wk;
|
||||
struct work_struct sched_scan_results_wk;
|
||||
|
|
@ -84,6 +91,8 @@ struct cfg80211_registered_device {
|
|||
struct list_head destroy_list;
|
||||
struct work_struct destroy_work;
|
||||
|
||||
struct work_struct sched_scan_stop_wk;
|
||||
|
||||
/* must be last because of the way we do wiphy_priv(),
|
||||
* and it should at least be aligned to NETDEV_ALIGN */
|
||||
struct wiphy wiphy __aligned(NETDEV_ALIGN);
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ enum nl80211_multicast_groups {
|
|||
};
|
||||
|
||||
static const struct genl_multicast_group nl80211_mcgrps[] = {
|
||||
[NL80211_MCGRP_CONFIG] = { .name = "config", },
|
||||
[NL80211_MCGRP_SCAN] = { .name = "scan", },
|
||||
[NL80211_MCGRP_REGULATORY] = { .name = "regulatory", },
|
||||
[NL80211_MCGRP_MLME] = { .name = "mlme", },
|
||||
[NL80211_MCGRP_VENDOR] = { .name = "vendor", },
|
||||
[NL80211_MCGRP_CONFIG] = { .name = NL80211_MULTICAST_GROUP_CONFIG },
|
||||
[NL80211_MCGRP_SCAN] = { .name = NL80211_MULTICAST_GROUP_SCAN },
|
||||
[NL80211_MCGRP_REGULATORY] = { .name = NL80211_MULTICAST_GROUP_REG },
|
||||
[NL80211_MCGRP_MLME] = { .name = NL80211_MULTICAST_GROUP_MLME },
|
||||
[NL80211_MCGRP_VENDOR] = { .name = NL80211_MULTICAST_GROUP_VENDOR },
|
||||
#ifdef CONFIG_NL80211_TESTMODE
|
||||
[NL80211_MCGRP_TESTMODE] = { .name = "testmode", }
|
||||
[NL80211_MCGRP_TESTMODE] = { .name = NL80211_MULTICAST_GROUP_TESTMODE }
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -396,6 +396,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
|
|||
[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
|
||||
[NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
|
||||
[NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
|
||||
[NL80211_ATTR_WIPHY_SELF_MANAGED_REG] = { .type = NLA_FLAG },
|
||||
};
|
||||
|
||||
/* policy for the key attributes */
|
||||
|
|
@ -1087,6 +1088,11 @@ static int nl80211_send_wowlan(struct sk_buff *msg,
|
|||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
if ((rdev->wiphy.wowlan->flags & WIPHY_WOWLAN_NET_DETECT) &&
|
||||
nla_put_u32(msg, NL80211_WOWLAN_TRIG_NET_DETECT,
|
||||
rdev->wiphy.wowlan->max_nd_match_sets))
|
||||
return -ENOBUFS;
|
||||
|
||||
if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
|
||||
return -ENOBUFS;
|
||||
|
||||
|
|
@ -1701,6 +1707,15 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
rdev->wiphy.max_num_csa_counters))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
|
||||
nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put(msg, NL80211_ATTR_EXT_FEATURES,
|
||||
sizeof(rdev->wiphy.ext_features),
|
||||
rdev->wiphy.ext_features))
|
||||
goto nla_put_failure;
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
|
|
@ -3640,8 +3655,8 @@ static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
int flags,
|
||||
static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
|
||||
u32 seq, int flags,
|
||||
struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
const u8 *mac_addr, struct station_info *sinfo)
|
||||
|
|
@ -3649,7 +3664,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
void *hdr;
|
||||
struct nlattr *sinfoattr, *bss_param;
|
||||
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION);
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
|
||||
if (!hdr)
|
||||
return -1;
|
||||
|
||||
|
|
@ -3661,115 +3676,77 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
|
||||
if (!sinfoattr)
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_CONNECTED_TIME) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_CONNECTED_TIME,
|
||||
sinfo->connected_time))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_INACTIVE_TIME) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_INACTIVE_TIME,
|
||||
sinfo->inactive_time))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & (STATION_INFO_RX_BYTES |
|
||||
STATION_INFO_RX_BYTES64)) &&
|
||||
|
||||
#define PUT_SINFO(attr, memb, type) do { \
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_ ## attr) && \
|
||||
nla_put_ ## type(msg, NL80211_STA_INFO_ ## attr, \
|
||||
sinfo->memb)) \
|
||||
goto nla_put_failure; \
|
||||
} while (0)
|
||||
|
||||
PUT_SINFO(CONNECTED_TIME, connected_time, u32);
|
||||
PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
|
||||
|
||||
if (sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_RX_BYTES64)) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_RX_BYTES,
|
||||
(u32)sinfo->rx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & (STATION_INFO_TX_BYTES |
|
||||
STATION_INFO_TX_BYTES64)) &&
|
||||
|
||||
if (sinfo->filled & (BIT(NL80211_STA_INFO_TX_BYTES) |
|
||||
BIT(NL80211_STA_INFO_TX_BYTES64)) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
|
||||
(u32)sinfo->tx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_RX_BYTES64) &&
|
||||
nla_put_u64(msg, NL80211_STA_INFO_RX_BYTES64,
|
||||
sinfo->rx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_BYTES64) &&
|
||||
nla_put_u64(msg, NL80211_STA_INFO_TX_BYTES64,
|
||||
sinfo->tx_bytes))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_LLID) &&
|
||||
nla_put_u16(msg, NL80211_STA_INFO_LLID, sinfo->llid))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_PLID) &&
|
||||
nla_put_u16(msg, NL80211_STA_INFO_PLID, sinfo->plid))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_PLINK_STATE) &&
|
||||
nla_put_u8(msg, NL80211_STA_INFO_PLINK_STATE,
|
||||
sinfo->plink_state))
|
||||
goto nla_put_failure;
|
||||
|
||||
PUT_SINFO(RX_BYTES64, rx_bytes, u64);
|
||||
PUT_SINFO(TX_BYTES64, tx_bytes, u64);
|
||||
PUT_SINFO(LLID, llid, u16);
|
||||
PUT_SINFO(PLID, plid, u16);
|
||||
PUT_SINFO(PLINK_STATE, plink_state, u8);
|
||||
|
||||
switch (rdev->wiphy.signal_type) {
|
||||
case CFG80211_SIGNAL_TYPE_MBM:
|
||||
if ((sinfo->filled & STATION_INFO_SIGNAL) &&
|
||||
nla_put_u8(msg, NL80211_STA_INFO_SIGNAL,
|
||||
sinfo->signal))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_SIGNAL_AVG) &&
|
||||
nla_put_u8(msg, NL80211_STA_INFO_SIGNAL_AVG,
|
||||
sinfo->signal_avg))
|
||||
goto nla_put_failure;
|
||||
PUT_SINFO(SIGNAL, signal, u8);
|
||||
PUT_SINFO(SIGNAL_AVG, signal_avg, u8);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL)) {
|
||||
if (!nl80211_put_signal(msg, sinfo->chains,
|
||||
sinfo->chain_signal,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)) {
|
||||
if (!nl80211_put_signal(msg, sinfo->chains,
|
||||
sinfo->chain_signal_avg,
|
||||
NL80211_STA_INFO_CHAIN_SIGNAL_AVG))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_TX_BITRATE) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_TX_BITRATE)) {
|
||||
if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
|
||||
NL80211_STA_INFO_TX_BITRATE))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_RX_BITRATE) {
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_RX_BITRATE)) {
|
||||
if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
|
||||
NL80211_STA_INFO_RX_BITRATE))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if ((sinfo->filled & STATION_INFO_RX_PACKETS) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_RX_PACKETS,
|
||||
sinfo->rx_packets))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_PACKETS) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_PACKETS,
|
||||
sinfo->tx_packets))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_RETRIES) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_RETRIES,
|
||||
sinfo->tx_retries))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_TX_FAILED) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_TX_FAILED,
|
||||
sinfo->tx_failed))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_EXPECTED_THROUGHPUT) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_EXPECTED_THROUGHPUT,
|
||||
sinfo->expected_throughput))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_BEACON_LOSS_COUNT) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_BEACON_LOSS,
|
||||
sinfo->beacon_loss_count))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_LOCAL_PM) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_LOCAL_PM,
|
||||
sinfo->local_pm))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_PEER_PM) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_PEER_PM,
|
||||
sinfo->peer_pm))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_NONPEER_PM) &&
|
||||
nla_put_u32(msg, NL80211_STA_INFO_NONPEER_PM,
|
||||
sinfo->nonpeer_pm))
|
||||
goto nla_put_failure;
|
||||
if (sinfo->filled & STATION_INFO_BSS_PARAM) {
|
||||
|
||||
PUT_SINFO(RX_PACKETS, rx_packets, u32);
|
||||
PUT_SINFO(TX_PACKETS, tx_packets, u32);
|
||||
PUT_SINFO(TX_RETRIES, tx_retries, u32);
|
||||
PUT_SINFO(TX_FAILED, tx_failed, u32);
|
||||
PUT_SINFO(EXPECTED_THROUGHPUT, expected_throughput, u32);
|
||||
PUT_SINFO(BEACON_LOSS, beacon_loss_count, u32);
|
||||
PUT_SINFO(LOCAL_PM, local_pm, u32);
|
||||
PUT_SINFO(PEER_PM, peer_pm, u32);
|
||||
PUT_SINFO(NONPEER_PM, nonpeer_pm, u32);
|
||||
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_BSS_PARAM)) {
|
||||
bss_param = nla_nest_start(msg, NL80211_STA_INFO_BSS_PARAM);
|
||||
if (!bss_param)
|
||||
goto nla_put_failure;
|
||||
|
|
@ -3788,18 +3765,62 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
|
||||
nla_nest_end(msg, bss_param);
|
||||
}
|
||||
if ((sinfo->filled & STATION_INFO_STA_FLAGS) &&
|
||||
if ((sinfo->filled & BIT(NL80211_STA_INFO_STA_FLAGS)) &&
|
||||
nla_put(msg, NL80211_STA_INFO_STA_FLAGS,
|
||||
sizeof(struct nl80211_sta_flag_update),
|
||||
&sinfo->sta_flags))
|
||||
goto nla_put_failure;
|
||||
if ((sinfo->filled & STATION_INFO_T_OFFSET) &&
|
||||
nla_put_u64(msg, NL80211_STA_INFO_T_OFFSET,
|
||||
sinfo->t_offset))
|
||||
goto nla_put_failure;
|
||||
|
||||
PUT_SINFO(T_OFFSET, t_offset, u64);
|
||||
PUT_SINFO(RX_DROP_MISC, rx_dropped_misc, u64);
|
||||
PUT_SINFO(BEACON_RX, rx_beacon, u64);
|
||||
PUT_SINFO(BEACON_SIGNAL_AVG, rx_beacon_signal_avg, u8);
|
||||
|
||||
#undef PUT_SINFO
|
||||
|
||||
if (sinfo->filled & BIT(NL80211_STA_INFO_TID_STATS)) {
|
||||
struct nlattr *tidsattr;
|
||||
int tid;
|
||||
|
||||
tidsattr = nla_nest_start(msg, NL80211_STA_INFO_TID_STATS);
|
||||
if (!tidsattr)
|
||||
goto nla_put_failure;
|
||||
|
||||
for (tid = 0; tid < IEEE80211_NUM_TIDS + 1; tid++) {
|
||||
struct cfg80211_tid_stats *tidstats;
|
||||
struct nlattr *tidattr;
|
||||
|
||||
tidstats = &sinfo->pertid[tid];
|
||||
|
||||
if (!tidstats->filled)
|
||||
continue;
|
||||
|
||||
tidattr = nla_nest_start(msg, tid + 1);
|
||||
if (!tidattr)
|
||||
goto nla_put_failure;
|
||||
|
||||
#define PUT_TIDVAL(attr, memb, type) do { \
|
||||
if (tidstats->filled & BIT(NL80211_TID_STATS_ ## attr) && \
|
||||
nla_put_ ## type(msg, NL80211_TID_STATS_ ## attr, \
|
||||
tidstats->memb)) \
|
||||
goto nla_put_failure; \
|
||||
} while (0)
|
||||
|
||||
PUT_TIDVAL(RX_MSDU, rx_msdu, u64);
|
||||
PUT_TIDVAL(TX_MSDU, tx_msdu, u64);
|
||||
PUT_TIDVAL(TX_MSDU_RETRIES, tx_msdu_retries, u64);
|
||||
PUT_TIDVAL(TX_MSDU_FAILED, tx_msdu_failed, u64);
|
||||
|
||||
#undef PUT_TIDVAL
|
||||
nla_nest_end(msg, tidattr);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, tidsattr);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, sinfoattr);
|
||||
|
||||
if ((sinfo->filled & STATION_INFO_ASSOC_REQ_IES) &&
|
||||
if (sinfo->assoc_req_ies_len &&
|
||||
nla_put(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len,
|
||||
sinfo->assoc_req_ies))
|
||||
goto nla_put_failure;
|
||||
|
|
@ -3844,7 +3865,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|||
if (err)
|
||||
goto out_err;
|
||||
|
||||
if (nl80211_send_station(skb,
|
||||
if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
||||
rdev, wdev->netdev, mac_addr,
|
||||
|
|
@ -3891,7 +3912,8 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
|
|||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
if (nl80211_send_station(msg, info->snd_portid, info->snd_seq, 0,
|
||||
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
|
||||
info->snd_portid, info->snd_seq, 0,
|
||||
rdev, dev, mac_addr, &sinfo) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return -ENOBUFS;
|
||||
|
|
@ -5327,42 +5349,20 @@ static int nl80211_update_mesh_config(struct sk_buff *skb,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
static int nl80211_put_regdom(const struct ieee80211_regdomain *regdom,
|
||||
struct sk_buff *msg)
|
||||
{
|
||||
const struct ieee80211_regdomain *regdom;
|
||||
struct sk_buff *msg;
|
||||
void *hdr = NULL;
|
||||
struct nlattr *nl_reg_rules;
|
||||
unsigned int i;
|
||||
|
||||
if (!cfg80211_regdomain)
|
||||
return -EINVAL;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOBUFS;
|
||||
|
||||
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
|
||||
NL80211_CMD_GET_REG);
|
||||
if (!hdr)
|
||||
goto put_failure;
|
||||
|
||||
if (reg_last_request_cell_base() &&
|
||||
nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
|
||||
NL80211_USER_REG_HINT_CELL_BASE))
|
||||
goto nla_put_failure;
|
||||
|
||||
rcu_read_lock();
|
||||
regdom = rcu_dereference(cfg80211_regdomain);
|
||||
|
||||
if (nla_put_string(msg, NL80211_ATTR_REG_ALPHA2, regdom->alpha2) ||
|
||||
(regdom->dfs_region &&
|
||||
nla_put_u8(msg, NL80211_ATTR_DFS_REGION, regdom->dfs_region)))
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
|
||||
if (!nl_reg_rules)
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
for (i = 0; i < regdom->n_reg_rules; i++) {
|
||||
struct nlattr *nl_reg_rule;
|
||||
|
|
@ -5377,7 +5377,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
nl_reg_rule = nla_nest_start(msg, i);
|
||||
if (!nl_reg_rule)
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
max_bandwidth_khz = freq_range->max_bandwidth_khz;
|
||||
if (!max_bandwidth_khz)
|
||||
|
|
@ -5398,13 +5398,74 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
power_rule->max_eirp) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME,
|
||||
reg_rule->dfs_cac_ms))
|
||||
goto nla_put_failure_rcu;
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nl_reg_rule);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
nla_nest_end(msg, nl_reg_rules);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_get_reg_do(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
const struct ieee80211_regdomain *regdom = NULL;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy = NULL;
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return -ENOBUFS;
|
||||
|
||||
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
|
||||
NL80211_CMD_GET_REG);
|
||||
if (!hdr)
|
||||
goto put_failure;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_WIPHY]) {
|
||||
bool self_managed;
|
||||
|
||||
rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
|
||||
if (IS_ERR(rdev)) {
|
||||
nlmsg_free(msg);
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
|
||||
wiphy = &rdev->wiphy;
|
||||
self_managed = wiphy->regulatory_flags &
|
||||
REGULATORY_WIPHY_SELF_MANAGED;
|
||||
regdom = get_wiphy_regdom(wiphy);
|
||||
|
||||
/* a self-managed-reg device must have a private regdom */
|
||||
if (WARN_ON(!regdom && self_managed)) {
|
||||
nlmsg_free(msg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (regdom &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (!wiphy && reg_last_request_cell_base() &&
|
||||
nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
|
||||
NL80211_USER_REG_HINT_CELL_BASE))
|
||||
goto nla_put_failure;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
if (!regdom)
|
||||
regdom = rcu_dereference(cfg80211_regdomain);
|
||||
|
||||
if (nl80211_put_regdom(regdom, msg))
|
||||
goto nla_put_failure_rcu;
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
return genlmsg_reply(msg, info);
|
||||
|
|
@ -5418,6 +5479,83 @@ put_failure:
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_send_regdom(struct sk_buff *msg, struct netlink_callback *cb,
|
||||
u32 seq, int flags, struct wiphy *wiphy,
|
||||
const struct ieee80211_regdomain *regdom)
|
||||
{
|
||||
void *hdr = nl80211hdr_put(msg, NETLINK_CB(cb->skb).portid, seq, flags,
|
||||
NL80211_CMD_GET_REG);
|
||||
|
||||
if (!hdr)
|
||||
return -1;
|
||||
|
||||
genl_dump_check_consistent(cb, hdr, &nl80211_fam);
|
||||
|
||||
if (nl80211_put_regdom(regdom, msg))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (!wiphy && reg_last_request_cell_base() &&
|
||||
nla_put_u32(msg, NL80211_ATTR_USER_REG_HINT_TYPE,
|
||||
NL80211_USER_REG_HINT_CELL_BASE))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (wiphy &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, get_wiphy_idx(wiphy)))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (wiphy && wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
|
||||
nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
|
||||
goto nla_put_failure;
|
||||
|
||||
return genlmsg_end(msg, hdr);
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_get_reg_dump(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
{
|
||||
const struct ieee80211_regdomain *regdom = NULL;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
int err, reg_idx, start = cb->args[2];
|
||||
|
||||
rtnl_lock();
|
||||
|
||||
if (cfg80211_regdomain && start == 0) {
|
||||
err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI, NULL,
|
||||
rtnl_dereference(cfg80211_regdomain));
|
||||
if (err < 0)
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
/* the global regdom is idx 0 */
|
||||
reg_idx = 1;
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
regdom = get_wiphy_regdom(&rdev->wiphy);
|
||||
if (!regdom)
|
||||
continue;
|
||||
|
||||
if (++reg_idx <= start)
|
||||
continue;
|
||||
|
||||
err = nl80211_send_regdom(skb, cb, cb->nlh->nlmsg_seq,
|
||||
NLM_F_MULTI, &rdev->wiphy, regdom);
|
||||
if (err < 0) {
|
||||
reg_idx--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cb->args[2] = reg_idx;
|
||||
err = skb->len;
|
||||
out_err:
|
||||
rtnl_unlock();
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
|
||||
|
|
@ -6069,6 +6207,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
struct net_device *dev = info->user_ptr[1];
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
int err;
|
||||
|
||||
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
|
||||
|
|
@ -6078,27 +6217,32 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
|
|||
if (rdev->sched_scan_req)
|
||||
return -EINPROGRESS;
|
||||
|
||||
rdev->sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
|
||||
info->attrs);
|
||||
err = PTR_ERR_OR_ZERO(rdev->sched_scan_req);
|
||||
sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
|
||||
info->attrs);
|
||||
|
||||
err = PTR_ERR_OR_ZERO(sched_scan_req);
|
||||
if (err)
|
||||
goto out_err;
|
||||
|
||||
err = rdev_sched_scan_start(rdev, dev, rdev->sched_scan_req);
|
||||
err = rdev_sched_scan_start(rdev, dev, sched_scan_req);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
rdev->sched_scan_req->dev = dev;
|
||||
rdev->sched_scan_req->wiphy = &rdev->wiphy;
|
||||
sched_scan_req->dev = dev;
|
||||
sched_scan_req->wiphy = &rdev->wiphy;
|
||||
|
||||
if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
|
||||
sched_scan_req->owner_nlportid = info->snd_portid;
|
||||
|
||||
rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req);
|
||||
|
||||
nl80211_send_sched_scan(rdev, dev,
|
||||
NL80211_CMD_START_SCHED_SCAN);
|
||||
return 0;
|
||||
|
||||
out_free:
|
||||
kfree(rdev->sched_scan_req);
|
||||
kfree(sched_scan_req);
|
||||
out_err:
|
||||
rdev->sched_scan_req = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -6481,12 +6625,17 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
}
|
||||
|
||||
static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
||||
int flags, struct net_device *dev,
|
||||
struct survey_info *survey)
|
||||
int flags, struct net_device *dev,
|
||||
bool allow_radio_stats,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
void *hdr;
|
||||
struct nlattr *infoattr;
|
||||
|
||||
/* skip radio stats if userspace didn't request them */
|
||||
if (!survey->channel && !allow_radio_stats)
|
||||
return 0;
|
||||
|
||||
hdr = nl80211hdr_put(msg, portid, seq, flags,
|
||||
NL80211_CMD_NEW_SURVEY_RESULTS);
|
||||
if (!hdr)
|
||||
|
|
@ -6499,7 +6648,8 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
if (!infoattr)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
|
||||
if (survey->channel &&
|
||||
nla_put_u32(msg, NL80211_SURVEY_INFO_FREQUENCY,
|
||||
survey->channel->center_freq))
|
||||
goto nla_put_failure;
|
||||
|
||||
|
|
@ -6509,25 +6659,29 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
if ((survey->filled & SURVEY_INFO_IN_USE) &&
|
||||
nla_put_flag(msg, NL80211_SURVEY_INFO_IN_USE))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME,
|
||||
survey->channel_time))
|
||||
if ((survey->filled & SURVEY_INFO_TIME) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME,
|
||||
survey->time))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY,
|
||||
survey->channel_time_busy))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_BUSY,
|
||||
survey->time_busy))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY,
|
||||
survey->channel_time_ext_busy))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_EXT_BUSY) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_EXT_BUSY,
|
||||
survey->time_ext_busy))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX,
|
||||
survey->channel_time_rx))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_RX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_RX,
|
||||
survey->time_rx))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX,
|
||||
survey->channel_time_tx))
|
||||
if ((survey->filled & SURVEY_INFO_TIME_TX) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_TX,
|
||||
survey->time_tx))
|
||||
goto nla_put_failure;
|
||||
if ((survey->filled & SURVEY_INFO_TIME_SCAN) &&
|
||||
nla_put_u64(msg, NL80211_SURVEY_INFO_TIME_SCAN,
|
||||
survey->time_scan))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, infoattr);
|
||||
|
|
@ -6539,19 +6693,22 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 portid, u32 seq,
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int nl80211_dump_survey(struct sk_buff *skb,
|
||||
struct netlink_callback *cb)
|
||||
static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct survey_info survey;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wireless_dev *wdev;
|
||||
int survey_idx = cb->args[2];
|
||||
int res;
|
||||
bool radio_stats;
|
||||
|
||||
res = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
/* prepare_wdev_dump parsed the attributes */
|
||||
radio_stats = nl80211_fam.attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS];
|
||||
|
||||
if (!wdev->netdev) {
|
||||
res = -EINVAL;
|
||||
goto out_err;
|
||||
|
|
@ -6569,13 +6726,9 @@ static int nl80211_dump_survey(struct sk_buff *skb,
|
|||
if (res)
|
||||
goto out_err;
|
||||
|
||||
/* Survey without a channel doesn't make sense */
|
||||
if (!survey.channel) {
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (survey.channel->flags & IEEE80211_CHAN_DISABLED) {
|
||||
/* don't send disabled channels, but do send non-channel data */
|
||||
if (survey.channel &&
|
||||
survey.channel->flags & IEEE80211_CHAN_DISABLED) {
|
||||
survey_idx++;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -6583,7 +6736,7 @@ static int nl80211_dump_survey(struct sk_buff *skb,
|
|||
if (nl80211_send_survey(skb,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, NLM_F_MULTI,
|
||||
wdev->netdev, &survey) < 0)
|
||||
wdev->netdev, radio_stats, &survey) < 0)
|
||||
goto out;
|
||||
survey_idx++;
|
||||
}
|
||||
|
|
@ -8599,6 +8752,48 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_send_wowlan_nd(struct sk_buff *msg,
|
||||
struct cfg80211_sched_scan_request *req)
|
||||
{
|
||||
struct nlattr *nd, *freqs, *matches, *match;
|
||||
int i;
|
||||
|
||||
if (!req)
|
||||
return 0;
|
||||
|
||||
nd = nla_nest_start(msg, NL80211_WOWLAN_TRIG_NET_DETECT);
|
||||
if (!nd)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_SCHED_SCAN_INTERVAL, req->interval))
|
||||
return -ENOBUFS;
|
||||
|
||||
freqs = nla_nest_start(msg, NL80211_ATTR_SCAN_FREQUENCIES);
|
||||
if (!freqs)
|
||||
return -ENOBUFS;
|
||||
|
||||
for (i = 0; i < req->n_channels; i++)
|
||||
nla_put_u32(msg, i, req->channels[i]->center_freq);
|
||||
|
||||
nla_nest_end(msg, freqs);
|
||||
|
||||
if (req->n_match_sets) {
|
||||
matches = nla_nest_start(msg, NL80211_ATTR_SCHED_SCAN_MATCH);
|
||||
for (i = 0; i < req->n_match_sets; i++) {
|
||||
match = nla_nest_start(msg, i);
|
||||
nla_put(msg, NL80211_SCHED_SCAN_MATCH_ATTR_SSID,
|
||||
req->match_sets[i].ssid.ssid_len,
|
||||
req->match_sets[i].ssid.ssid);
|
||||
nla_nest_end(msg, match);
|
||||
}
|
||||
nla_nest_end(msg, matches);
|
||||
}
|
||||
|
||||
nla_nest_end(msg, nd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
||||
|
|
@ -8656,6 +8851,11 @@ static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info)
|
|||
rdev->wiphy.wowlan_config->tcp))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nl80211_send_wowlan_nd(
|
||||
msg,
|
||||
rdev->wiphy.wowlan_config->nd_config))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nl_wowlan);
|
||||
}
|
||||
|
||||
|
|
@ -10225,7 +10425,8 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_GET_REG,
|
||||
.doit = nl80211_get_reg,
|
||||
.doit = nl80211_get_reg_do,
|
||||
.dumpit = nl80211_get_reg_dump,
|
||||
.policy = nl80211_policy,
|
||||
.internal_flags = NL80211_FLAG_NEED_RTNL,
|
||||
/* can be retrieved by unprivileged users */
|
||||
|
|
@ -10939,25 +11140,9 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
NL80211_MCGRP_SCAN, GFP_KERNEL);
|
||||
}
|
||||
|
||||
/*
|
||||
* This can happen on global regulatory changes or device specific settings
|
||||
* based on custom world regulatory domains.
|
||||
*/
|
||||
void nl80211_send_reg_change_event(struct regulatory_request *request)
|
||||
static bool nl80211_reg_change_event_fill(struct sk_buff *msg,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
|
||||
if (!hdr) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Userspace can always count this one always being set */
|
||||
if (nla_put_u8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator))
|
||||
goto nla_put_failure;
|
||||
|
|
@ -10983,8 +11168,46 @@ void nl80211_send_reg_change_event(struct regulatory_request *request)
|
|||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
if (request->wiphy_idx != WIPHY_IDX_INVALID &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
|
||||
if (request->wiphy_idx != WIPHY_IDX_INVALID) {
|
||||
struct wiphy *wiphy = wiphy_idx_to_wiphy(request->wiphy_idx);
|
||||
|
||||
if (wiphy &&
|
||||
nla_put_u32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (wiphy &&
|
||||
wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED &&
|
||||
nla_put_flag(msg, NL80211_ATTR_WIPHY_SELF_MANAGED_REG))
|
||||
goto nla_put_failure;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
nla_put_failure:
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* This can happen on global regulatory changes or device specific settings
|
||||
* based on custom regulatory domains.
|
||||
*/
|
||||
void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, cmd_id);
|
||||
if (!hdr) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nl80211_reg_change_event_fill(msg, request) == false)
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
|
@ -11523,7 +11746,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
|||
if (!msg)
|
||||
return;
|
||||
|
||||
if (nl80211_send_station(msg, 0, 0, 0,
|
||||
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
|
||||
rdev, dev, mac_addr, sinfo) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
|
|
@ -11534,12 +11757,16 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
|||
}
|
||||
EXPORT_SYMBOL(cfg80211_new_sta);
|
||||
|
||||
void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
|
||||
void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp)
|
||||
{
|
||||
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
struct station_info empty_sinfo = {};
|
||||
|
||||
if (!sinfo)
|
||||
sinfo = &empty_sinfo;
|
||||
|
||||
trace_cfg80211_del_sta(dev, mac_addr);
|
||||
|
||||
|
|
@ -11547,27 +11774,16 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
|
|||
if (!msg)
|
||||
return;
|
||||
|
||||
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION);
|
||||
if (!hdr) {
|
||||
if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
|
||||
rdev, dev, mac_addr, sinfo)) {
|
||||
nlmsg_free(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
|
||||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
|
||||
goto nla_put_failure;
|
||||
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
|
||||
NL80211_MCGRP_MLME, gfp);
|
||||
return;
|
||||
|
||||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_del_sta);
|
||||
EXPORT_SYMBOL(cfg80211_del_sta_sinfo);
|
||||
|
||||
void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
|
||||
enum nl80211_connect_failed_reason reason,
|
||||
|
|
@ -12471,6 +12687,13 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
|
|||
|
||||
list_for_each_entry_rcu(rdev, &cfg80211_rdev_list, list) {
|
||||
bool schedule_destroy_work = false;
|
||||
bool schedule_scan_stop = false;
|
||||
struct cfg80211_sched_scan_request *sched_scan_req =
|
||||
rcu_dereference(rdev->sched_scan_req);
|
||||
|
||||
if (sched_scan_req && notify->portid &&
|
||||
sched_scan_req->owner_nlportid == notify->portid)
|
||||
schedule_scan_stop = true;
|
||||
|
||||
list_for_each_entry_rcu(wdev, &rdev->wdev_list, list) {
|
||||
cfg80211_mlme_unregister_socket(wdev, notify->portid);
|
||||
|
|
@ -12501,6 +12724,12 @@ static int nl80211_netlink_notify(struct notifier_block * nb,
|
|||
spin_unlock(&rdev->destroy_list_lock);
|
||||
schedule_work(&rdev->destroy_work);
|
||||
}
|
||||
} else if (schedule_scan_stop) {
|
||||
sched_scan_req->owner_nlportid = 0;
|
||||
|
||||
if (rdev->ops->sched_scan_stop &&
|
||||
rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
|
||||
schedule_work(&rdev->sched_scan_stop_wk);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,21 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *netdev, u32 cmd);
|
||||
void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev);
|
||||
void nl80211_send_reg_change_event(struct regulatory_request *request);
|
||||
void nl80211_common_reg_change_event(enum nl80211_commands cmd_id,
|
||||
struct regulatory_request *request);
|
||||
|
||||
static inline void
|
||||
nl80211_send_reg_change_event(struct regulatory_request *request)
|
||||
{
|
||||
nl80211_common_reg_change_event(NL80211_CMD_REG_CHANGE, request);
|
||||
}
|
||||
|
||||
static inline void
|
||||
nl80211_send_wiphy_reg_change_event(struct regulatory_request *request)
|
||||
{
|
||||
nl80211_common_reg_change_event(NL80211_CMD_WIPHY_REG_CHANGE, request);
|
||||
}
|
||||
|
||||
void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev,
|
||||
const u8 *buf, size_t len, gfp_t gfp);
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ static struct regulatory_request core_request_world = {
|
|||
* protected by RTNL (and can be accessed with RCU protection)
|
||||
*/
|
||||
static struct regulatory_request __rcu *last_request =
|
||||
(void __rcu *)&core_request_world;
|
||||
(void __force __rcu *)&core_request_world;
|
||||
|
||||
/* To trigger userspace events */
|
||||
static struct platform_device *reg_pdev;
|
||||
|
|
@ -142,7 +142,7 @@ static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
|
|||
return rtnl_dereference(cfg80211_regdomain);
|
||||
}
|
||||
|
||||
static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
|
||||
const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
|
||||
{
|
||||
return rtnl_dereference(wiphy->regd);
|
||||
}
|
||||
|
|
@ -1307,6 +1307,9 @@ static bool ignore_reg_update(struct wiphy *wiphy,
|
|||
{
|
||||
struct regulatory_request *lr = get_last_request();
|
||||
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
return true;
|
||||
|
||||
if (!lr) {
|
||||
REG_DBG_PRINT("Ignoring regulatory request set by %s "
|
||||
"since last_request is not set\n",
|
||||
|
|
@ -1683,8 +1686,12 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|||
if (IS_ERR(reg_rule)) {
|
||||
REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n",
|
||||
chan->center_freq);
|
||||
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = chan->orig_flags;
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED) {
|
||||
chan->flags |= IEEE80211_CHAN_DISABLED;
|
||||
} else {
|
||||
chan->orig_flags |= IEEE80211_CHAN_DISABLED;
|
||||
chan->flags = chan->orig_flags;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1709,7 +1716,13 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|||
chan->dfs_state = NL80211_DFS_USABLE;
|
||||
|
||||
chan->beacon_found = false;
|
||||
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
|
||||
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
chan->flags = chan->orig_flags | bw_flags |
|
||||
map_regdom_flags(reg_rule->flags);
|
||||
else
|
||||
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
|
||||
|
||||
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
|
||||
chan->max_reg_power = chan->max_power =
|
||||
(int) MBM_TO_DBM(power_rule->max_eirp);
|
||||
|
|
@ -2095,6 +2108,26 @@ out_free:
|
|||
reg_free_request(reg_request);
|
||||
}
|
||||
|
||||
static bool reg_only_self_managed_wiphys(void)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
bool self_managed_found = false;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
wiphy = &rdev->wiphy;
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
self_managed_found = true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/* make sure at least one self-managed wiphy exists */
|
||||
return self_managed_found;
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
|
||||
* Regulatory hints come on a first come first serve basis and we
|
||||
|
|
@ -2126,6 +2159,11 @@ static void reg_process_pending_hints(void)
|
|||
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
if (reg_only_self_managed_wiphys()) {
|
||||
reg_free_request(reg_request);
|
||||
return;
|
||||
}
|
||||
|
||||
reg_process_hint(reg_request);
|
||||
}
|
||||
|
||||
|
|
@ -2153,11 +2191,52 @@ static void reg_process_pending_beacon_hints(void)
|
|||
spin_unlock_bh(®_pending_beacons_lock);
|
||||
}
|
||||
|
||||
static void reg_process_self_managed_hints(void)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
struct wiphy *wiphy;
|
||||
const struct ieee80211_regdomain *tmp;
|
||||
const struct ieee80211_regdomain *regd;
|
||||
enum ieee80211_band band;
|
||||
struct regulatory_request request = {};
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
wiphy = &rdev->wiphy;
|
||||
|
||||
spin_lock(®_requests_lock);
|
||||
regd = rdev->requested_regd;
|
||||
rdev->requested_regd = NULL;
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
if (regd == NULL)
|
||||
continue;
|
||||
|
||||
tmp = get_wiphy_regdom(wiphy);
|
||||
rcu_assign_pointer(wiphy->regd, regd);
|
||||
rcu_free_regdom(tmp);
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++)
|
||||
handle_band_custom(wiphy, wiphy->bands[band], regd);
|
||||
|
||||
reg_process_ht_flags(wiphy);
|
||||
|
||||
request.wiphy_idx = get_wiphy_idx(wiphy);
|
||||
request.alpha2[0] = regd->alpha2[0];
|
||||
request.alpha2[1] = regd->alpha2[1];
|
||||
request.initiator = NL80211_REGDOM_SET_BY_DRIVER;
|
||||
|
||||
nl80211_send_wiphy_reg_change_event(&request);
|
||||
}
|
||||
|
||||
reg_check_channels();
|
||||
}
|
||||
|
||||
static void reg_todo(struct work_struct *work)
|
||||
{
|
||||
rtnl_lock();
|
||||
reg_process_pending_hints();
|
||||
reg_process_pending_beacon_hints();
|
||||
reg_process_self_managed_hints();
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
|
|
@ -2438,6 +2517,8 @@ static void restore_regulatory_settings(bool reset_user)
|
|||
world_alpha2[1] = cfg80211_world_regdom->alpha2[1];
|
||||
|
||||
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
|
||||
if (rdev->wiphy.regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
continue;
|
||||
if (rdev->wiphy.regulatory_flags & REGULATORY_CUSTOM_REG)
|
||||
restore_custom_reg_settings(&rdev->wiphy);
|
||||
}
|
||||
|
|
@ -2841,10 +2922,79 @@ int set_regdom(const struct ieee80211_regdomain *rd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __regulatory_set_wiphy_regd(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd)
|
||||
{
|
||||
const struct ieee80211_regdomain *regd;
|
||||
const struct ieee80211_regdomain *prev_regd;
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
||||
if (WARN_ON(!wiphy || !rd))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN(!(wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED),
|
||||
"wiphy should have REGULATORY_WIPHY_SELF_MANAGED\n"))
|
||||
return -EPERM;
|
||||
|
||||
if (WARN(!is_valid_rd(rd), "Invalid regulatory domain detected\n")) {
|
||||
print_regdomain_info(rd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regd = reg_copy_regd(rd);
|
||||
if (IS_ERR(regd))
|
||||
return PTR_ERR(regd);
|
||||
|
||||
rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
spin_lock(®_requests_lock);
|
||||
prev_regd = rdev->requested_regd;
|
||||
rdev->requested_regd = regd;
|
||||
spin_unlock(®_requests_lock);
|
||||
|
||||
kfree(prev_regd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int regulatory_set_wiphy_regd(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd)
|
||||
{
|
||||
int ret = __regulatory_set_wiphy_regd(wiphy, rd);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
schedule_work(®_work);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_set_wiphy_regd);
|
||||
|
||||
int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy,
|
||||
struct ieee80211_regdomain *rd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
ret = __regulatory_set_wiphy_regd(wiphy, rd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* process the request immediately */
|
||||
reg_process_self_managed_hints();
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(regulatory_set_wiphy_regd_sync_rtnl);
|
||||
|
||||
void wiphy_regulatory_register(struct wiphy *wiphy)
|
||||
{
|
||||
struct regulatory_request *lr;
|
||||
|
||||
/* self-managed devices ignore external hints */
|
||||
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
|
||||
wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
|
||||
REGULATORY_COUNTRY_IE_IGNORE;
|
||||
|
||||
if (!reg_dev_ignore_cell_hint(wiphy))
|
||||
reg_num_devs_support_basehint++;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
|
|||
const struct ieee80211_reg_rule *rule);
|
||||
|
||||
bool reg_last_request_cell_base(void);
|
||||
const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy);
|
||||
|
||||
/**
|
||||
* regulatory_hint_found_beacon - hints a beacon was found on a channel
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
|
|||
|
||||
rtnl_lock();
|
||||
|
||||
request = rdev->sched_scan_req;
|
||||
request = rtnl_dereference(rdev->sched_scan_req);
|
||||
|
||||
/* we don't have sched_scan_req anymore if the scan is stopping */
|
||||
if (request) {
|
||||
|
|
@ -279,7 +279,8 @@ void cfg80211_sched_scan_results(struct wiphy *wiphy)
|
|||
{
|
||||
trace_cfg80211_sched_scan_results(wiphy);
|
||||
/* ignore if we're not scanning */
|
||||
if (wiphy_to_rdev(wiphy)->sched_scan_req)
|
||||
|
||||
if (rcu_access_pointer(wiphy_to_rdev(wiphy)->sched_scan_req))
|
||||
queue_work(cfg80211_wq,
|
||||
&wiphy_to_rdev(wiphy)->sched_scan_results_wk);
|
||||
}
|
||||
|
|
@ -308,6 +309,7 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
|
|||
int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
|
||||
bool driver_initiated)
|
||||
{
|
||||
struct cfg80211_sched_scan_request *sched_scan_req;
|
||||
struct net_device *dev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
|
@ -315,7 +317,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
if (!rdev->sched_scan_req)
|
||||
return -ENOENT;
|
||||
|
||||
dev = rdev->sched_scan_req->dev;
|
||||
sched_scan_req = rtnl_dereference(rdev->sched_scan_req);
|
||||
dev = sched_scan_req->dev;
|
||||
|
||||
if (!driver_initiated) {
|
||||
int err = rdev_sched_scan_stop(rdev, dev);
|
||||
|
|
@ -325,8 +328,8 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
|
|||
|
||||
nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED);
|
||||
|
||||
kfree(rdev->sched_scan_req);
|
||||
rdev->sched_scan_req = NULL;
|
||||
RCU_INIT_POINTER(rdev->sched_scan_req, NULL);
|
||||
kfree_rcu(sched_scan_req, rcu_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1604,11 +1604,12 @@ TRACE_EVENT(rdev_return_int_survey_info,
|
|||
WIPHY_ENTRY
|
||||
CHAN_ENTRY
|
||||
__field(int, ret)
|
||||
__field(u64, channel_time)
|
||||
__field(u64, channel_time_busy)
|
||||
__field(u64, channel_time_ext_busy)
|
||||
__field(u64, channel_time_rx)
|
||||
__field(u64, channel_time_tx)
|
||||
__field(u64, time)
|
||||
__field(u64, time_busy)
|
||||
__field(u64, time_ext_busy)
|
||||
__field(u64, time_rx)
|
||||
__field(u64, time_tx)
|
||||
__field(u64, time_scan)
|
||||
__field(u32, filled)
|
||||
__field(s8, noise)
|
||||
),
|
||||
|
|
@ -1616,22 +1617,24 @@ TRACE_EVENT(rdev_return_int_survey_info,
|
|||
WIPHY_ASSIGN;
|
||||
CHAN_ASSIGN(info->channel);
|
||||
__entry->ret = ret;
|
||||
__entry->channel_time = info->channel_time;
|
||||
__entry->channel_time_busy = info->channel_time_busy;
|
||||
__entry->channel_time_ext_busy = info->channel_time_ext_busy;
|
||||
__entry->channel_time_rx = info->channel_time_rx;
|
||||
__entry->channel_time_tx = info->channel_time_tx;
|
||||
__entry->time = info->time;
|
||||
__entry->time_busy = info->time_busy;
|
||||
__entry->time_ext_busy = info->time_ext_busy;
|
||||
__entry->time_rx = info->time_rx;
|
||||
__entry->time_tx = info->time_tx;
|
||||
__entry->time_scan = info->time_scan;
|
||||
__entry->filled = info->filled;
|
||||
__entry->noise = info->noise;
|
||||
),
|
||||
TP_printk(WIPHY_PR_FMT ", returned: %d, " CHAN_PR_FMT
|
||||
", channel time: %llu, channel time busy: %llu, "
|
||||
"channel time extension busy: %llu, channel time rx: %llu, "
|
||||
"channel time tx: %llu, filled: %u, noise: %d",
|
||||
"channel time tx: %llu, scan time: %llu, filled: %u, noise: %d",
|
||||
WIPHY_PR_ARG, __entry->ret, CHAN_PR_ARG,
|
||||
__entry->channel_time, __entry->channel_time_busy,
|
||||
__entry->channel_time_ext_busy, __entry->channel_time_rx,
|
||||
__entry->channel_time_tx, __entry->filled, __entry->noise)
|
||||
__entry->time, __entry->time_busy,
|
||||
__entry->time_ext_busy, __entry->time_rx,
|
||||
__entry->time_tx, __entry->time_scan,
|
||||
__entry->filled, __entry->noise)
|
||||
);
|
||||
|
||||
TRACE_EVENT(rdev_tdls_oper,
|
||||
|
|
|
|||
|
|
@ -1300,7 +1300,7 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
if (!(sinfo.filled & STATION_INFO_TX_BITRATE))
|
||||
if (!(sinfo.filled & BIT(NL80211_STA_INFO_TX_BITRATE)))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
rate->value = 100000 * cfg80211_calculate_bitrate(&sinfo.txrate);
|
||||
|
|
@ -1340,7 +1340,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
|
||||
switch (rdev->wiphy.signal_type) {
|
||||
case CFG80211_SIGNAL_TYPE_MBM:
|
||||
if (sinfo.filled & STATION_INFO_SIGNAL) {
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) {
|
||||
int sig = sinfo.signal;
|
||||
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
|
||||
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
|
||||
|
|
@ -1354,7 +1354,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
break;
|
||||
}
|
||||
case CFG80211_SIGNAL_TYPE_UNSPEC:
|
||||
if (sinfo.filled & STATION_INFO_SIGNAL) {
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) {
|
||||
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
|
||||
wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
|
||||
wstats.qual.level = sinfo.signal;
|
||||
|
|
@ -1367,9 +1367,9 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
|
|||
}
|
||||
|
||||
wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
|
||||
if (sinfo.filled & STATION_INFO_RX_DROP_MISC)
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_RX_DROP_MISC))
|
||||
wstats.discard.misc = sinfo.rx_dropped_misc;
|
||||
if (sinfo.filled & STATION_INFO_TX_FAILED)
|
||||
if (sinfo.filled & BIT(NL80211_STA_INFO_TX_FAILED))
|
||||
wstats.discard.retries = sinfo.tx_failed;
|
||||
|
||||
return &wstats;
|
||||
|
|
|
|||
Loading…
Reference in a new issue