For the next cycle, we have the following:
* the biggest change is Michał's work on integrating FQ/codel with the mac80211 internal software queues * cfg80211 connect result gets clarified for the "no connection at all" case * advertisement of per-interface type capabilities, in case they differ (which makes a lot of sense for some capabilities) * most of the nl80211 & hwsim unprivileged namespace operation changes * human-readable VHT capabilities in debugfs * some other cleanups, like spelling -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJXWWe/AAoJEGt7eEactAAdXVsQAKGkdXGmUU14tfiRCnZryMEH GyiVDHQivfcadicbK9599LXadvYc6ATZHfYoSnROwB82NfhKB71N8dUJ4qePxLNa lDe5uuuAgxtHG63hK1R02flPorkBAEcUcdHsFSuOw7JWag4/49sCqWH8X5K8E9aT vrhaPeppJPydwnmNzNOBvMsLEJFJdZWaEZupZQ0kiJ/jB/howFdzF75GxGQ2jh+F dPk22/PtV2igCtntqaty7h057AdZ+znQuiUdVB7eYIOle7veeGyMzFFf0xQ99LAZ +xcA7GA74u6m8O6SUVw+6nhrUJ5XTsKGUtmKCTVOcUGa5z7XDD7NIxk2SgloCJkC qPqVU8wyBCxKc+6JsyiVSLcB5MWvWxifvo0OyLsbCqhN50bTtJT96ymKOAx4NeSG s+TYlV2HgVRNN6PzGvl/ZUo8Mm1UFGWlCBPcyMy9Fwc0jxdhnOAZzOtqV1yVwlCz M43RKwxBX6MHAtlfwy6g3M5ievAviwY3Kt+yGeLRIVsJJfOUdQxYAa+m7GTeohD/ Tns4IHbtWJiLTKuaTvrs4ec3ycXrv7iibMINcarvkTgbbF9Qvarf/e2RoWO/freY OUixDdG7HmsY0XIUhSepeMJpn5xIhQ7dkmckhzDEgZqBM6uPJEMB2+O/CGNDsxEp VjfnwXJ+9PQrjheBvnD2 =FvhQ -----END PGP SIGNATURE----- Merge tag 'mac80211-next-for-davem-2016-06-09' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next Johannes Berg says: ==================== For the next cycle, we have the following: * the biggest change is Michał's work on integrating FQ/codel with the mac80211 internal software queues * cfg80211 connect result gets clarified for the "no connection at all" case * advertisement of per-interface type capabilities, in case they differ (which makes a lot of sense for some capabilities) * most of the nl80211 & hwsim unprivileged namespace operation changes * human-readable VHT capabilities in debugfs * some other cleanups, like spelling ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
d6cf3a85b4
|
@ -136,6 +136,7 @@
|
|||
!Finclude/net/cfg80211.h cfg80211_ibss_joined
|
||||
!Finclude/net/cfg80211.h cfg80211_connect_result
|
||||
!Finclude/net/cfg80211.h cfg80211_connect_bss
|
||||
!Finclude/net/cfg80211.h cfg80211_connect_timeout
|
||||
!Finclude/net/cfg80211.h cfg80211_roamed
|
||||
!Finclude/net/cfg80211.h cfg80211_disconnected
|
||||
!Finclude/net/cfg80211.h cfg80211_ready_on_channel
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/ktime.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include "mac80211_hwsim.h"
|
||||
|
||||
#define WARN_QUEUE 100
|
||||
|
@ -250,6 +252,28 @@ static inline void hwsim_clear_chanctx_magic(struct ieee80211_chanctx_conf *c)
|
|||
cp->magic = 0;
|
||||
}
|
||||
|
||||
static unsigned int hwsim_net_id;
|
||||
|
||||
static int hwsim_netgroup;
|
||||
|
||||
struct hwsim_net {
|
||||
int netgroup;
|
||||
};
|
||||
|
||||
static inline int hwsim_net_get_netgroup(struct net *net)
|
||||
{
|
||||
struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id);
|
||||
|
||||
return hwsim_net->netgroup;
|
||||
}
|
||||
|
||||
static inline void hwsim_net_set_netgroup(struct net *net)
|
||||
{
|
||||
struct hwsim_net *hwsim_net = net_generic(net, hwsim_net_id);
|
||||
|
||||
hwsim_net->netgroup = hwsim_netgroup++;
|
||||
}
|
||||
|
||||
static struct class *hwsim_class;
|
||||
|
||||
static struct net_device *hwsim_mon; /* global monitor netdev */
|
||||
|
@ -526,6 +550,9 @@ struct mac80211_hwsim_data {
|
|||
*/
|
||||
u64 group;
|
||||
|
||||
/* group shared by radios created in the same netns */
|
||||
int netgroup;
|
||||
|
||||
int power_level;
|
||||
|
||||
/* difference between this hw's clock and the real clock, in usecs */
|
||||
|
@ -568,6 +595,7 @@ static struct genl_family hwsim_genl_family = {
|
|||
.name = "MAC80211_HWSIM",
|
||||
.version = 1,
|
||||
.maxattr = HWSIM_ATTR_MAX,
|
||||
.netnsok = true,
|
||||
};
|
||||
|
||||
enum hwsim_multicast_groups {
|
||||
|
@ -1202,6 +1230,9 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
|||
if (!(data->group & data2->group))
|
||||
continue;
|
||||
|
||||
if (data->netgroup != data2->netgroup)
|
||||
continue;
|
||||
|
||||
if (!hwsim_chans_compat(chan, data2->tmp_chan) &&
|
||||
!hwsim_chans_compat(chan, data2->channel)) {
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
|
@ -2349,6 +2380,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
struct ieee80211_hw *hw;
|
||||
enum nl80211_band band;
|
||||
const struct ieee80211_ops *ops = &mac80211_hwsim_ops;
|
||||
struct net *net;
|
||||
int idx;
|
||||
|
||||
if (WARN_ON(param->channels > 1 && !param->use_chanctx))
|
||||
|
@ -2366,6 +2398,13 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
err = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (info)
|
||||
net = genl_info_net(info);
|
||||
else
|
||||
net = &init_net;
|
||||
wiphy_net_set(hw->wiphy, net);
|
||||
|
||||
data = hw->priv;
|
||||
data->hw = hw;
|
||||
|
||||
|
@ -2541,6 +2580,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
|
|||
data->group = 1;
|
||||
mutex_init(&data->mutex);
|
||||
|
||||
data->netgroup = hwsim_net_get_netgroup(net);
|
||||
|
||||
/* Enable frame retransmissions for lossy channels */
|
||||
hw->max_rates = 4;
|
||||
hw->max_rate_tries = 11;
|
||||
|
@ -3014,6 +3055,9 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!net_eq(wiphy_net(data->hw->wiphy), genl_info_net(info)))
|
||||
continue;
|
||||
|
||||
list_del(&data->list);
|
||||
spin_unlock_bh(&hwsim_radio_lock);
|
||||
mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
|
||||
|
@ -3040,6 +3084,9 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
|
|||
if (data->idx != idx)
|
||||
continue;
|
||||
|
||||
if (!net_eq(wiphy_net(data->hw->wiphy), genl_info_net(info)))
|
||||
continue;
|
||||
|
||||
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (!skb) {
|
||||
res = -ENOMEM;
|
||||
|
@ -3079,6 +3126,9 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb,
|
|||
if (data->idx < idx)
|
||||
continue;
|
||||
|
||||
if (!net_eq(wiphy_net(data->hw->wiphy), sock_net(skb->sk)))
|
||||
continue;
|
||||
|
||||
res = mac80211_hwsim_get_radio(skb, data,
|
||||
NETLINK_CB(cb->skb).portid,
|
||||
cb->nlh->nlmsg_seq, cb,
|
||||
|
@ -3118,13 +3168,13 @@ static const struct genl_ops hwsim_ops[] = {
|
|||
.cmd = HWSIM_CMD_NEW_RADIO,
|
||||
.policy = hwsim_genl_policy,
|
||||
.doit = hwsim_new_radio_nl,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
},
|
||||
{
|
||||
.cmd = HWSIM_CMD_DEL_RADIO,
|
||||
.policy = hwsim_genl_policy,
|
||||
.doit = hwsim_del_radio_nl,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
},
|
||||
{
|
||||
.cmd = HWSIM_CMD_GET_RADIO,
|
||||
|
@ -3206,6 +3256,40 @@ failure:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static __net_init int hwsim_init_net(struct net *net)
|
||||
{
|
||||
hwsim_net_set_netgroup(net);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit hwsim_exit_net(struct net *net)
|
||||
{
|
||||
struct mac80211_hwsim_data *data, *tmp;
|
||||
|
||||
spin_lock_bh(&hwsim_radio_lock);
|
||||
list_for_each_entry_safe(data, tmp, &hwsim_radios, list) {
|
||||
if (!net_eq(wiphy_net(data->hw->wiphy), net))
|
||||
continue;
|
||||
|
||||
/* Radios created in init_net are returned to init_net. */
|
||||
if (data->netgroup == hwsim_net_get_netgroup(&init_net))
|
||||
continue;
|
||||
|
||||
list_del(&data->list);
|
||||
INIT_WORK(&data->destroy_work, destroy_radio);
|
||||
schedule_work(&data->destroy_work);
|
||||
}
|
||||
spin_unlock_bh(&hwsim_radio_lock);
|
||||
}
|
||||
|
||||
static struct pernet_operations hwsim_net_ops = {
|
||||
.init = hwsim_init_net,
|
||||
.exit = hwsim_exit_net,
|
||||
.id = &hwsim_net_id,
|
||||
.size = sizeof(struct hwsim_net),
|
||||
};
|
||||
|
||||
static void hwsim_exit_netlink(void)
|
||||
{
|
||||
/* unregister the notifier */
|
||||
|
@ -3242,10 +3326,14 @@ static int __init init_mac80211_hwsim(void)
|
|||
spin_lock_init(&hwsim_radio_lock);
|
||||
INIT_LIST_HEAD(&hwsim_radios);
|
||||
|
||||
err = platform_driver_register(&mac80211_hwsim_driver);
|
||||
err = register_pernet_device(&hwsim_net_ops);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = platform_driver_register(&mac80211_hwsim_driver);
|
||||
if (err)
|
||||
goto out_unregister_pernet;
|
||||
|
||||
hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim");
|
||||
if (IS_ERR(hwsim_class)) {
|
||||
err = PTR_ERR(hwsim_class);
|
||||
|
@ -3363,6 +3451,8 @@ out_free_radios:
|
|||
mac80211_hwsim_free();
|
||||
out_unregister_driver:
|
||||
platform_driver_unregister(&mac80211_hwsim_driver);
|
||||
out_unregister_pernet:
|
||||
unregister_pernet_device(&hwsim_net_ops);
|
||||
return err;
|
||||
}
|
||||
module_init(init_mac80211_hwsim);
|
||||
|
@ -3376,5 +3466,6 @@ static void __exit exit_mac80211_hwsim(void)
|
|||
mac80211_hwsim_free();
|
||||
unregister_netdev(hwsim_mon);
|
||||
platform_driver_unregister(&mac80211_hwsim_driver);
|
||||
unregister_pernet_device(&hwsim_net_ops);
|
||||
}
|
||||
module_exit(exit_mac80211_hwsim);
|
||||
|
|
|
@ -2367,19 +2367,23 @@ struct cfg80211_qos_map {
|
|||
* (invoked with the wireless_dev mutex held)
|
||||
*
|
||||
* @connect: Connect to the ESS with the specified parameters. When connected,
|
||||
* call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
|
||||
* If the connection fails for some reason, call cfg80211_connect_result()
|
||||
* with the status from the AP. The driver is allowed to roam to other
|
||||
* BSSes within the ESS when the other BSS matches the connect parameters.
|
||||
* When such roaming is initiated by the driver, the driver is expected to
|
||||
* verify that the target matches the configured security parameters and
|
||||
* to use Reassociation Request frame instead of Association Request frame.
|
||||
* The connect function can also be used to request the driver to perform
|
||||
* a specific roam when connected to an ESS. In that case, the prev_bssid
|
||||
* call cfg80211_connect_result()/cfg80211_connect_bss() with status code
|
||||
* %WLAN_STATUS_SUCCESS. If the connection fails for some reason, call
|
||||
* cfg80211_connect_result()/cfg80211_connect_bss() with the status code
|
||||
* from the AP or cfg80211_connect_timeout() if no frame with status code
|
||||
* was received.
|
||||
* The driver is allowed to roam to other BSSes within the ESS when the
|
||||
* other BSS matches the connect parameters. When such roaming is initiated
|
||||
* by the driver, the driver is expected to verify that the target matches
|
||||
* the configured security parameters and to use Reassociation Request
|
||||
* frame instead of Association Request frame.
|
||||
* The connect function can also be used to request the driver to perform a
|
||||
* specific roam when connected to an ESS. In that case, the prev_bssid
|
||||
* parameter is set to the BSSID of the currently associated BSS as an
|
||||
* indication of requesting reassociation. In both the driver-initiated and
|
||||
* new connect() call initiated roaming cases, the result of roaming is
|
||||
* indicated with a call to cfg80211_roamed() or cfg80211_roamed_bss().
|
||||
* indication of requesting reassociation.
|
||||
* In both the driver-initiated and new connect() call initiated roaming
|
||||
* cases, the result of roaming is indicated with a call to
|
||||
* cfg80211_roamed() or cfg80211_roamed_bss().
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
* @disconnect: Disconnect from the BSS/ESS.
|
||||
* (invoked with the wireless_dev mutex held)
|
||||
|
@ -3079,6 +3083,24 @@ struct wiphy_vendor_command {
|
|||
unsigned long *storage);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wiphy_iftype_ext_capab - extended capabilities per interface type
|
||||
* @iftype: interface type
|
||||
* @extended_capabilities: extended capabilities supported by the driver,
|
||||
* additional capabilities might be supported by userspace; these are the
|
||||
* 802.11 extended capabilities ("Extended Capabilities element") and are
|
||||
* in the same format as in the information element. See IEEE Std
|
||||
* 802.11-2012 8.4.2.29 for the defined fields.
|
||||
* @extended_capabilities_mask: mask of the valid values
|
||||
* @extended_capabilities_len: length of the extended capabilities
|
||||
*/
|
||||
struct wiphy_iftype_ext_capab {
|
||||
enum nl80211_iftype iftype;
|
||||
const u8 *extended_capabilities;
|
||||
const u8 *extended_capabilities_mask;
|
||||
u8 extended_capabilities_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct wiphy - wireless hardware description
|
||||
* @reg_notifier: the driver's regulatory notification callback,
|
||||
|
@ -3199,9 +3221,14 @@ struct wiphy_vendor_command {
|
|||
* additional capabilities might be supported by userspace; these are
|
||||
* the 802.11 extended capabilities ("Extended Capabilities element")
|
||||
* and are in the same format as in the information element. See
|
||||
* 802.11-2012 8.4.2.29 for the defined fields.
|
||||
* 802.11-2012 8.4.2.29 for the defined fields. These are the default
|
||||
* extended capabilities to be used if the capabilities are not specified
|
||||
* for a specific interface type in iftype_ext_capab.
|
||||
* @extended_capabilities_mask: mask of the valid values
|
||||
* @extended_capabilities_len: length of the extended capabilities
|
||||
* @iftype_ext_capab: array of extended capabilities per interface type
|
||||
* @num_iftype_ext_capab: number of interface types for which extended
|
||||
* capabilities are specified separately.
|
||||
* @coalesce: packet coalescing support information
|
||||
*
|
||||
* @vendor_commands: array of vendor commands supported by the hardware
|
||||
|
@ -3301,6 +3328,9 @@ struct wiphy {
|
|||
const u8 *extended_capabilities, *extended_capabilities_mask;
|
||||
u8 extended_capabilities_len;
|
||||
|
||||
const struct wiphy_iftype_ext_capab *iftype_ext_capab;
|
||||
unsigned int num_iftype_ext_capab;
|
||||
|
||||
/* If multiple wiphys are registered and you're handed e.g.
|
||||
* a regular netdev with assigned ieee80211_ptr, you won't
|
||||
* know whether it points to a wiphy your driver has registered
|
||||
|
@ -4680,7 +4710,7 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
|
|||
void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
|
||||
struct cfg80211_bss *bss, const u8 *req_ie,
|
||||
size_t req_ie_len, const u8 *resp_ie,
|
||||
size_t resp_ie_len, u16 status, gfp_t gfp);
|
||||
size_t resp_ie_len, int status, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_connect_result - notify cfg80211 of connection result
|
||||
|
@ -4709,6 +4739,29 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
|||
resp_ie_len, status, gfp);
|
||||
}
|
||||
|
||||
/**
|
||||
* cfg80211_connect_timeout - notify cfg80211 of connection timeout
|
||||
*
|
||||
* @dev: network device
|
||||
* @bssid: the BSSID of the AP
|
||||
* @req_ie: association request IEs (maybe be %NULL)
|
||||
* @req_ie_len: association request IEs length
|
||||
* @gfp: allocation flags
|
||||
*
|
||||
* It should be called by the underlying driver whenever connect() has failed
|
||||
* in a sequence where no explicit authentication/association rejection was
|
||||
* received from the AP. This could happen, e.g., due to not being able to send
|
||||
* out the Authentication or Association Request frame or timing out while
|
||||
* waiting for the response.
|
||||
*/
|
||||
static inline void
|
||||
cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len, gfp_t gfp)
|
||||
{
|
||||
cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, NULL, 0, -1,
|
||||
gfp);
|
||||
}
|
||||
|
||||
/**
|
||||
* cfg80211_roamed - notify cfg80211 of roaming
|
||||
*
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/skbuff.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/codel.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
/**
|
||||
|
@ -895,7 +896,18 @@ struct ieee80211_tx_info {
|
|||
unsigned long jiffies;
|
||||
};
|
||||
/* NB: vif can be NULL for injected frames */
|
||||
struct ieee80211_vif *vif;
|
||||
union {
|
||||
/* NB: vif can be NULL for injected frames */
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
/* When packets are enqueued on txq it's easy
|
||||
* to re-construct the vif pointer. There's no
|
||||
* more space in tx_info so it can be used to
|
||||
* store the necessary enqueue time for packet
|
||||
* sojourn time computation.
|
||||
*/
|
||||
codel_time_t enqueue_time;
|
||||
};
|
||||
struct ieee80211_key_conf *hw_key;
|
||||
u32 flags;
|
||||
/* 4 bytes free */
|
||||
|
@ -2147,9 +2159,6 @@ enum ieee80211_hw_flags {
|
|||
* @n_cipher_schemes: a size of an array of cipher schemes definitions.
|
||||
* @cipher_schemes: a pointer to an array of cipher scheme definitions
|
||||
* supported by HW.
|
||||
*
|
||||
* @txq_ac_max_pending: maximum number of frames per AC pending in all txq
|
||||
* entries for a vif.
|
||||
*/
|
||||
struct ieee80211_hw {
|
||||
struct ieee80211_conf conf;
|
||||
|
@ -2180,7 +2189,6 @@ struct ieee80211_hw {
|
|||
u8 uapsd_max_sp_len;
|
||||
u8 n_cipher_schemes;
|
||||
const struct ieee80211_cipher_scheme *cipher_schemes;
|
||||
int txq_ac_max_pending;
|
||||
};
|
||||
|
||||
static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
|
||||
|
|
|
@ -493,7 +493,12 @@
|
|||
* This attribute is ignored if driver does not support roam scan.
|
||||
* It is also sent as an event, with the BSSID and response IEs when the
|
||||
* connection is established or failed to be established. This can be
|
||||
* determined by the STATUS_CODE attribute.
|
||||
* determined by the %NL80211_ATTR_STATUS_CODE attribute (0 = success,
|
||||
* non-zero = failure). If %NL80211_ATTR_TIMED_OUT is included in the
|
||||
* event, the connection attempt failed due to not being able to initiate
|
||||
* authentication/association or not receiving a response from the AP.
|
||||
* Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as
|
||||
* well to remain backwards compatible.
|
||||
* @NL80211_CMD_ROAM: request that the card roam (currently not implemented),
|
||||
* sent as an event when the card/driver roamed by itself.
|
||||
* @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify
|
||||
|
@ -1819,6 +1824,11 @@ enum nl80211_commands {
|
|||
*
|
||||
* @NL80211_ATTR_PAD: attribute used for padding for 64-bit alignment
|
||||
*
|
||||
* @NL80211_ATTR_IFTYPE_EXT_CAPA: Nested attribute of the following attributes:
|
||||
* %NL80211_ATTR_IFTYPE, %NL80211_ATTR_EXT_CAPA,
|
||||
* %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per
|
||||
* interface type.
|
||||
*
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
|
@ -2201,6 +2211,8 @@ enum nl80211_attrs {
|
|||
|
||||
NL80211_ATTR_PAD,
|
||||
|
||||
NL80211_ATTR_IFTYPE_EXT_CAPA,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
|
|
|
@ -670,8 +670,7 @@
|
|||
/*
|
||||
* Generic format for most parameters that fit in an int
|
||||
*/
|
||||
struct iw_param
|
||||
{
|
||||
struct iw_param {
|
||||
__s32 value; /* The value of the parameter itself */
|
||||
__u8 fixed; /* Hardware should not use auto select */
|
||||
__u8 disabled; /* Disable the feature */
|
||||
|
@ -682,8 +681,7 @@ struct iw_param
|
|||
* For all data larger than 16 octets, we need to use a
|
||||
* pointer to memory allocated in user space.
|
||||
*/
|
||||
struct iw_point
|
||||
{
|
||||
struct iw_point {
|
||||
void __user *pointer; /* Pointer to the data (in user space) */
|
||||
__u16 length; /* number of fields or size in bytes */
|
||||
__u16 flags; /* Optional params */
|
||||
|
@ -698,8 +696,7 @@ struct iw_point
|
|||
* of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')...
|
||||
* The power of 10 is in 'e', the result of the division is in 'm'.
|
||||
*/
|
||||
struct iw_freq
|
||||
{
|
||||
struct iw_freq {
|
||||
__s32 m; /* Mantissa */
|
||||
__s16 e; /* Exponent */
|
||||
__u8 i; /* List index (when in range struct) */
|
||||
|
@ -709,8 +706,7 @@ struct iw_freq
|
|||
/*
|
||||
* Quality of the link
|
||||
*/
|
||||
struct iw_quality
|
||||
{
|
||||
struct iw_quality {
|
||||
__u8 qual; /* link quality (%retries, SNR,
|
||||
%missed beacons or better...) */
|
||||
__u8 level; /* signal level (dBm) */
|
||||
|
@ -725,8 +721,7 @@ struct iw_quality
|
|||
* is already pretty exhaustive, and you should use that first.
|
||||
* This is only additional stats...
|
||||
*/
|
||||
struct iw_discarded
|
||||
{
|
||||
struct iw_discarded {
|
||||
__u32 nwid; /* Rx : Wrong nwid/essid */
|
||||
__u32 code; /* Rx : Unable to code/decode (WEP) */
|
||||
__u32 fragment; /* Rx : Can't perform MAC reassembly */
|
||||
|
@ -738,16 +733,14 @@ struct iw_discarded
|
|||
* Packet/Time period missed in the wireless adapter due to
|
||||
* "wireless" specific problems...
|
||||
*/
|
||||
struct iw_missed
|
||||
{
|
||||
struct iw_missed {
|
||||
__u32 beacon; /* Missed beacons/superframe */
|
||||
};
|
||||
|
||||
/*
|
||||
* Quality range (for spy threshold)
|
||||
*/
|
||||
struct iw_thrspy
|
||||
{
|
||||
struct iw_thrspy {
|
||||
struct sockaddr addr; /* Source address (hw/mac) */
|
||||
struct iw_quality qual; /* Quality of the link */
|
||||
struct iw_quality low; /* Low threshold */
|
||||
|
@ -765,8 +758,7 @@ struct iw_thrspy
|
|||
* Especially, scan results are required to include an entry for the
|
||||
* current BSS if the driver is in Managed mode and associated with an AP.
|
||||
*/
|
||||
struct iw_scan_req
|
||||
{
|
||||
struct iw_scan_req {
|
||||
__u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */
|
||||
__u8 essid_len;
|
||||
__u8 num_channels; /* num entries in channel_list;
|
||||
|
@ -827,8 +819,7 @@ struct iw_scan_req
|
|||
* RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for
|
||||
* debugging/testing.
|
||||
*/
|
||||
struct iw_encode_ext
|
||||
{
|
||||
struct iw_encode_ext {
|
||||
__u32 ext_flags; /* IW_ENCODE_EXT_* */
|
||||
__u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
|
||||
__u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
|
||||
|
@ -841,8 +832,7 @@ struct iw_encode_ext
|
|||
};
|
||||
|
||||
/* SIOCSIWMLME data */
|
||||
struct iw_mlme
|
||||
{
|
||||
struct iw_mlme {
|
||||
__u16 cmd; /* IW_MLME_* */
|
||||
__u16 reason_code;
|
||||
struct sockaddr addr;
|
||||
|
@ -855,16 +845,14 @@ struct iw_mlme
|
|||
|
||||
#define IW_PMKID_LEN 16
|
||||
|
||||
struct iw_pmksa
|
||||
{
|
||||
struct iw_pmksa {
|
||||
__u32 cmd; /* IW_PMKSA_* */
|
||||
struct sockaddr bssid;
|
||||
__u8 pmkid[IW_PMKID_LEN];
|
||||
};
|
||||
|
||||
/* IWEVMICHAELMICFAILURE data */
|
||||
struct iw_michaelmicfailure
|
||||
{
|
||||
struct iw_michaelmicfailure {
|
||||
__u32 flags;
|
||||
struct sockaddr src_addr;
|
||||
__u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */
|
||||
|
@ -872,8 +860,7 @@ struct iw_michaelmicfailure
|
|||
|
||||
/* IWEVPMKIDCAND data */
|
||||
#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */
|
||||
struct iw_pmkid_cand
|
||||
{
|
||||
struct iw_pmkid_cand {
|
||||
__u32 flags; /* IW_PMKID_CAND_* */
|
||||
__u32 index; /* the smaller the index, the higher the
|
||||
* priority */
|
||||
|
@ -884,8 +871,7 @@ struct iw_pmkid_cand
|
|||
/*
|
||||
* Wireless statistics (used for /proc/net/wireless)
|
||||
*/
|
||||
struct iw_statistics
|
||||
{
|
||||
struct iw_statistics {
|
||||
__u16 status; /* Status
|
||||
* - device dependent for now */
|
||||
|
||||
|
@ -897,7 +883,7 @@ struct iw_statistics
|
|||
|
||||
/* ------------------------ IOCTL REQUEST ------------------------ */
|
||||
/*
|
||||
* This structure defines the payload of an ioctl, and is used
|
||||
* This structure defines the payload of an ioctl, and is used
|
||||
* below.
|
||||
*
|
||||
* Note that this structure should fit on the memory footprint
|
||||
|
@ -906,8 +892,7 @@ struct iw_statistics
|
|||
* You should check this when increasing the structures defined
|
||||
* above in this file...
|
||||
*/
|
||||
union iwreq_data
|
||||
{
|
||||
union iwreq_data {
|
||||
/* Config - generic */
|
||||
char name[IFNAMSIZ];
|
||||
/* Name : used to verify the presence of wireless extensions.
|
||||
|
@ -944,15 +929,14 @@ union iwreq_data
|
|||
* convenience...
|
||||
* Do I need to remind you about structure size (32 octets) ?
|
||||
*/
|
||||
struct iwreq
|
||||
{
|
||||
struct iwreq {
|
||||
union
|
||||
{
|
||||
char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
|
||||
} ifr_ifrn;
|
||||
|
||||
/* Data part (defined just above) */
|
||||
union iwreq_data u;
|
||||
union iwreq_data u;
|
||||
};
|
||||
|
||||
/* -------------------------- IOCTL DATA -------------------------- */
|
||||
|
@ -965,8 +949,7 @@ struct iwreq
|
|||
* Range of parameters
|
||||
*/
|
||||
|
||||
struct iw_range
|
||||
{
|
||||
struct iw_range {
|
||||
/* Informative stuff (to choose between different interface) */
|
||||
__u32 throughput; /* To give an idea... */
|
||||
/* In theory this value should be the maximum benchmarked
|
||||
|
@ -1069,9 +1052,8 @@ struct iw_range
|
|||
/*
|
||||
* Private ioctl interface information
|
||||
*/
|
||||
|
||||
struct iw_priv_args
|
||||
{
|
||||
|
||||
struct iw_priv_args {
|
||||
__u32 cmd; /* Number of the ioctl to issue */
|
||||
__u16 set_args; /* Type and number of args */
|
||||
__u16 get_args; /* Type and number of args */
|
||||
|
@ -1088,8 +1070,7 @@ struct iw_priv_args
|
|||
/*
|
||||
* A Wireless Event. Contains basically the same data as the ioctl...
|
||||
*/
|
||||
struct iw_event
|
||||
{
|
||||
struct iw_event {
|
||||
__u16 len; /* Real length of this stuff */
|
||||
__u16 cmd; /* Wireless IOCTL */
|
||||
union iwreq_data u; /* IOCTL fixed payload */
|
||||
|
|
|
@ -194,17 +194,21 @@ static void
|
|||
ieee80211_agg_stop_txq(struct sta_info *sta, int tid)
|
||||
{
|
||||
struct ieee80211_txq *txq = sta->sta.txq[tid];
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct fq *fq;
|
||||
struct txq_info *txqi;
|
||||
|
||||
if (!txq)
|
||||
return;
|
||||
|
||||
txqi = to_txq_info(txq);
|
||||
sdata = vif_to_sdata(txq->vif);
|
||||
fq = &sdata->local->fq;
|
||||
|
||||
/* Lock here to protect against further seqno updates on dequeue */
|
||||
spin_lock_bh(&txqi->queue.lock);
|
||||
spin_lock_bh(&fq->lock);
|
||||
set_bit(IEEE80211_TXQ_STOP, &txqi->flags);
|
||||
spin_unlock_bh(&txqi->queue.lock);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
#include "rate.h"
|
||||
|
@ -70,6 +71,177 @@ DEBUGFS_READONLY_FILE(wep_iv, "%#08x",
|
|||
DEBUGFS_READONLY_FILE(rate_ctrl_alg, "%s",
|
||||
local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver");
|
||||
|
||||
struct aqm_info {
|
||||
struct ieee80211_local *local;
|
||||
size_t size;
|
||||
size_t len;
|
||||
unsigned char buf[0];
|
||||
};
|
||||
|
||||
#define AQM_HDR_LEN 200
|
||||
#define AQM_HW_ENTRY_LEN 40
|
||||
#define AQM_TXQ_ENTRY_LEN 110
|
||||
|
||||
static int aqm_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct ieee80211_local *local = inode->i_private;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct sta_info *sta;
|
||||
struct txq_info *txqi;
|
||||
struct fq *fq = &local->fq;
|
||||
struct aqm_info *info = NULL;
|
||||
int len = 0;
|
||||
int i;
|
||||
|
||||
if (!local->ops->wake_tx_queue)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
len += AQM_HDR_LEN;
|
||||
len += 6 * AQM_HW_ENTRY_LEN;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
||||
len += AQM_TXQ_ENTRY_LEN;
|
||||
list_for_each_entry_rcu(sta, &local->sta_list, list)
|
||||
len += AQM_TXQ_ENTRY_LEN * ARRAY_SIZE(sta->sta.txq);
|
||||
rcu_read_unlock();
|
||||
|
||||
info = vmalloc(len);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_bh(&local->fq.lock);
|
||||
rcu_read_lock();
|
||||
|
||||
file->private_data = info;
|
||||
info->local = local;
|
||||
info->size = len;
|
||||
len = 0;
|
||||
|
||||
len += scnprintf(info->buf + len, info->size - len,
|
||||
"* hw\n"
|
||||
"access name value\n"
|
||||
"R fq_flows_cnt %u\n"
|
||||
"R fq_backlog %u\n"
|
||||
"R fq_overlimit %u\n"
|
||||
"R fq_collisions %u\n"
|
||||
"RW fq_limit %u\n"
|
||||
"RW fq_quantum %u\n",
|
||||
fq->flows_cnt,
|
||||
fq->backlog,
|
||||
fq->overlimit,
|
||||
fq->collisions,
|
||||
fq->limit,
|
||||
fq->quantum);
|
||||
|
||||
len += scnprintf(info->buf + len,
|
||||
info->size - len,
|
||||
"* vif\n"
|
||||
"ifname addr ac backlog-bytes backlog-packets flows overlimit collisions tx-bytes tx-packets\n");
|
||||
|
||||
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||
txqi = to_txq_info(sdata->vif.txq);
|
||||
len += scnprintf(info->buf + len, info->size - len,
|
||||
"%s %pM %u %u %u %u %u %u %u %u\n",
|
||||
sdata->name,
|
||||
sdata->vif.addr,
|
||||
txqi->txq.ac,
|
||||
txqi->tin.backlog_bytes,
|
||||
txqi->tin.backlog_packets,
|
||||
txqi->tin.flows,
|
||||
txqi->tin.overlimit,
|
||||
txqi->tin.collisions,
|
||||
txqi->tin.tx_bytes,
|
||||
txqi->tin.tx_packets);
|
||||
}
|
||||
|
||||
len += scnprintf(info->buf + len,
|
||||
info->size - len,
|
||||
"* sta\n"
|
||||
"ifname addr tid ac backlog-bytes backlog-packets flows overlimit collisions tx-bytes tx-packets\n");
|
||||
|
||||
list_for_each_entry_rcu(sta, &local->sta_list, list) {
|
||||
sdata = sta->sdata;
|
||||
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
txqi = to_txq_info(sta->sta.txq[i]);
|
||||
len += scnprintf(info->buf + len, info->size - len,
|
||||
"%s %pM %d %d %u %u %u %u %u %u %u\n",
|
||||
sdata->name,
|
||||
sta->sta.addr,
|
||||
txqi->txq.tid,
|
||||
txqi->txq.ac,
|
||||
txqi->tin.backlog_bytes,
|
||||
txqi->tin.backlog_packets,
|
||||
txqi->tin.flows,
|
||||
txqi->tin.overlimit,
|
||||
txqi->tin.collisions,
|
||||
txqi->tin.tx_bytes,
|
||||
txqi->tin.tx_packets);
|
||||
}
|
||||
}
|
||||
|
||||
info->len = len;
|
||||
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&local->fq.lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int aqm_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
vfree(file->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t aqm_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct aqm_info *info = file->private_data;
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos,
|
||||
info->buf, info->len);
|
||||
}
|
||||
|
||||
static ssize_t aqm_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct aqm_info *info = file->private_data;
|
||||
struct ieee80211_local *local = info->local;
|
||||
char buf[100];
|
||||
size_t len;
|
||||
|
||||
if (count > sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(buf, user_buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
len = strlen(buf);
|
||||
if (len > 0 && buf[len-1] == '\n')
|
||||
buf[len-1] = 0;
|
||||
|
||||
if (sscanf(buf, "fq_limit %u", &local->fq.limit) == 1)
|
||||
return count;
|
||||
else if (sscanf(buf, "fq_quantum %u", &local->fq.quantum) == 1)
|
||||
return count;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct file_operations aqm_ops = {
|
||||
.write = aqm_write,
|
||||
.read = aqm_read,
|
||||
.open = aqm_open,
|
||||
.release = aqm_release,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static ssize_t reset_write(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -256,6 +428,7 @@ void debugfs_hw_add(struct ieee80211_local *local)
|
|||
DEBUGFS_ADD(hwflags);
|
||||
DEBUGFS_ADD(user_power);
|
||||
DEBUGFS_ADD(power);
|
||||
DEBUGFS_ADD_MODE(aqm, 0600);
|
||||
|
||||
statsd = debugfs_create_dir("statistics", phyd);
|
||||
|
||||
|
|
|
@ -328,14 +328,88 @@ STA_OPS(ht_capa);
|
|||
static ssize_t sta_vht_capa_read(struct file *file, char __user *userbuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char buf[128], *p = buf;
|
||||
char buf[512], *p = buf;
|
||||
struct sta_info *sta = file->private_data;
|
||||
struct ieee80211_sta_vht_cap *vhtc = &sta->sta.vht_cap;
|
||||
|
||||
p += scnprintf(p, sizeof(buf) + buf - p, "VHT %ssupported\n",
|
||||
vhtc->vht_supported ? "" : "not ");
|
||||
if (vhtc->vht_supported) {
|
||||
p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.8x\n", vhtc->cap);
|
||||
p += scnprintf(p, sizeof(buf) + buf - p, "cap: %#.8x\n",
|
||||
vhtc->cap);
|
||||
#define PFLAG(a, b) \
|
||||
do { \
|
||||
if (vhtc->cap & IEEE80211_VHT_CAP_ ## a) \
|
||||
p += scnprintf(p, sizeof(buf) + buf - p, \
|
||||
"\t\t%s\n", b); \
|
||||
} while (0)
|
||||
|
||||
switch (vhtc->cap & 0x3) {
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tMAX-MPDU-3895\n");
|
||||
break;
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tMAX-MPDU-7991\n");
|
||||
break;
|
||||
case IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tMAX-MPDU-11454\n");
|
||||
break;
|
||||
default:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tMAX-MPDU-UNKNOWN\n");
|
||||
};
|
||||
switch (vhtc->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
|
||||
case 0:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\t80Mhz\n");
|
||||
break;
|
||||
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\t160Mhz\n");
|
||||
break;
|
||||
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\t80+80Mhz\n");
|
||||
break;
|
||||
default:
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tUNKNOWN-MHZ: 0x%x\n",
|
||||
(vhtc->cap >> 2) & 0x3);
|
||||
};
|
||||
PFLAG(RXLDPC, "RXLDPC");
|
||||
PFLAG(SHORT_GI_80, "SHORT-GI-80");
|
||||
PFLAG(SHORT_GI_160, "SHORT-GI-160");
|
||||
PFLAG(TXSTBC, "TXSTBC");
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tRXSTBC_%d\n", (vhtc->cap >> 8) & 0x7);
|
||||
PFLAG(SU_BEAMFORMER_CAPABLE, "SU-BEAMFORMER-CAPABLE");
|
||||
PFLAG(SU_BEAMFORMEE_CAPABLE, "SU-BEAMFORMEE-CAPABLE");
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tBEAMFORMEE-STS: 0x%x\n",
|
||||
(vhtc->cap & IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK) >>
|
||||
IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tSOUNDING-DIMENSIONS: 0x%x\n",
|
||||
(vhtc->cap & IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK)
|
||||
>> IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);
|
||||
PFLAG(MU_BEAMFORMER_CAPABLE, "MU-BEAMFORMER-CAPABLE");
|
||||
PFLAG(MU_BEAMFORMEE_CAPABLE, "MU-BEAMFORMEE-CAPABLE");
|
||||
PFLAG(VHT_TXOP_PS, "TXOP-PS");
|
||||
PFLAG(HTC_VHT, "HTC-VHT");
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tMPDU-LENGTH-EXPONENT: 0x%x\n",
|
||||
(vhtc->cap & IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
|
||||
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
|
||||
PFLAG(VHT_LINK_ADAPTATION_VHT_UNSOL_MFB,
|
||||
"LINK-ADAPTATION-VHT-UNSOL-MFB");
|
||||
p += scnprintf(p, sizeof(buf) + buf - p,
|
||||
"\t\tLINK-ADAPTATION-VHT-MRQ-MFB: 0x%x\n",
|
||||
(vhtc->cap & IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB) >> 26);
|
||||
PFLAG(RX_ANTENNA_PATTERN, "RX-ANTENNA-PATTERN");
|
||||
PFLAG(TX_ANTENNA_PATTERN, "TX-ANTENNA-PATTERN");
|
||||
|
||||
p += scnprintf(p, sizeof(buf)+buf-p, "RX MCS: %.4x\n",
|
||||
le16_to_cpu(vhtc->vht_mcs.rx_mcs_map));
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <net/ieee80211_radiotap.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <net/fq.h>
|
||||
#include "key.h"
|
||||
#include "sta_info.h"
|
||||
#include "debug.h"
|
||||
|
@ -805,10 +806,19 @@ enum txq_info_flags {
|
|||
IEEE80211_TXQ_NO_AMSDU,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct txq_info - per tid queue
|
||||
*
|
||||
* @tin: contains packets split into multiple flows
|
||||
* @def_flow: used as a fallback flow when a packet destined to @tin hashes to
|
||||
* a fq_flow which is already owned by a different tin
|
||||
* @def_cvars: codel vars for @def_flow
|
||||
*/
|
||||
struct txq_info {
|
||||
struct sk_buff_head queue;
|
||||
struct fq_tin tin;
|
||||
struct fq_flow def_flow;
|
||||
struct codel_vars def_cvars;
|
||||
unsigned long flags;
|
||||
unsigned long byte_cnt;
|
||||
|
||||
/* keep last! */
|
||||
struct ieee80211_txq txq;
|
||||
|
@ -856,7 +866,7 @@ struct ieee80211_sub_if_data {
|
|||
bool control_port_no_encrypt;
|
||||
int encrypt_headroom;
|
||||
|
||||
atomic_t txqs_len[IEEE80211_NUM_ACS];
|
||||
atomic_t num_tx_queued;
|
||||
struct ieee80211_tx_queue_params tx_conf[IEEE80211_NUM_ACS];
|
||||
struct mac80211_qos_map __rcu *qos_map;
|
||||
|
||||
|
@ -1099,6 +1109,11 @@ struct ieee80211_local {
|
|||
* it first anyway so they become a no-op */
|
||||
struct ieee80211_hw hw;
|
||||
|
||||
struct fq fq;
|
||||
struct codel_vars *cvars;
|
||||
struct codel_params cparams;
|
||||
struct codel_stats cstats;
|
||||
|
||||
const struct ieee80211_ops *ops;
|
||||
|
||||
/*
|
||||
|
@ -1931,9 +1946,13 @@ static inline bool ieee80211_can_run_worker(struct ieee80211_local *local)
|
|||
return true;
|
||||
}
|
||||
|
||||
void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
struct txq_info *txq, int tid);
|
||||
int ieee80211_txq_setup_flows(struct ieee80211_local *local);
|
||||
void ieee80211_txq_teardown_flows(struct ieee80211_local *local);
|
||||
void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
struct txq_info *txq, int tid);
|
||||
void ieee80211_txq_purge(struct ieee80211_local *local,
|
||||
struct txq_info *txqi);
|
||||
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
|
||||
u16 transaction, u16 auth_alg, u16 status,
|
||||
const u8 *extra, size_t extra_len, const u8 *bssid,
|
||||
|
|
|
@ -779,6 +779,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
|||
bool going_down)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct fq *fq = &local->fq;
|
||||
unsigned long flags;
|
||||
struct sk_buff *skb, *tmp;
|
||||
u32 hw_reconf_flags = 0;
|
||||
|
@ -977,12 +978,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
|||
if (sdata->vif.txq) {
|
||||
struct txq_info *txqi = to_txq_info(sdata->vif.txq);
|
||||
|
||||
spin_lock_bh(&txqi->queue.lock);
|
||||
ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
|
||||
txqi->byte_cnt = 0;
|
||||
spin_unlock_bh(&txqi->queue.lock);
|
||||
|
||||
atomic_set(&sdata->txqs_len[txqi->txq.ac], 0);
|
||||
spin_lock_bh(&fq->lock);
|
||||
ieee80211_txq_purge(local, txqi);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
}
|
||||
|
||||
if (local->open_count == 0)
|
||||
|
@ -1198,6 +1196,12 @@ static void ieee80211_if_setup(struct net_device *dev)
|
|||
dev->destructor = ieee80211_if_free;
|
||||
}
|
||||
|
||||
static void ieee80211_if_setup_no_queue(struct net_device *dev)
|
||||
{
|
||||
ieee80211_if_setup(dev);
|
||||
dev->priv_flags |= IFF_NO_QUEUE;
|
||||
}
|
||||
|
||||
static void ieee80211_iface_work(struct work_struct *work)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata =
|
||||
|
@ -1707,6 +1711,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|||
struct net_device *ndev = NULL;
|
||||
struct ieee80211_sub_if_data *sdata = NULL;
|
||||
struct txq_info *txqi;
|
||||
void (*if_setup)(struct net_device *dev);
|
||||
int ret, i;
|
||||
int txqs = 1;
|
||||
|
||||
|
@ -1734,12 +1739,17 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|||
txq_size += sizeof(struct txq_info) +
|
||||
local->hw.txq_data_size;
|
||||
|
||||
if (local->ops->wake_tx_queue)
|
||||
if_setup = ieee80211_if_setup_no_queue;
|
||||
else
|
||||
if_setup = ieee80211_if_setup;
|
||||
|
||||
if (local->hw.queues >= IEEE80211_NUM_ACS)
|
||||
txqs = IEEE80211_NUM_ACS;
|
||||
|
||||
ndev = alloc_netdev_mqs(size + txq_size,
|
||||
name, name_assign_type,
|
||||
ieee80211_if_setup, txqs, 1);
|
||||
if_setup, txqs, 1);
|
||||
if (!ndev)
|
||||
return -ENOMEM;
|
||||
dev_net_set(ndev, wiphy_net(local->hw.wiphy));
|
||||
|
@ -1780,7 +1790,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|||
|
||||
if (txq_size) {
|
||||
txqi = netdev_priv(ndev) + size;
|
||||
ieee80211_init_tx_queue(sdata, NULL, txqi, 0);
|
||||
ieee80211_txq_init(sdata, NULL, txqi, 0);
|
||||
}
|
||||
|
||||
sdata->dev = ndev;
|
||||
|
|
|
@ -1055,9 +1055,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
|
||||
local->dynamic_ps_forced_timeout = -1;
|
||||
|
||||
if (!local->hw.txq_ac_max_pending)
|
||||
local->hw.txq_ac_max_pending = 64;
|
||||
|
||||
result = ieee80211_wep_init(local);
|
||||
if (result < 0)
|
||||
wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
|
||||
|
@ -1089,6 +1086,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
|
||||
rtnl_unlock();
|
||||
|
||||
result = ieee80211_txq_setup_flows(local);
|
||||
if (result)
|
||||
goto fail_flows;
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
|
||||
result = register_inetaddr_notifier(&local->ifa_notifier);
|
||||
|
@ -1114,6 +1115,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
|||
#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
|
||||
fail_ifa:
|
||||
#endif
|
||||
ieee80211_txq_teardown_flows(local);
|
||||
fail_flows:
|
||||
rtnl_lock();
|
||||
rate_control_deinitialize(local);
|
||||
ieee80211_remove_interfaces(local);
|
||||
|
@ -1172,6 +1175,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
|
|||
skb_queue_purge(&local->skb_queue);
|
||||
skb_queue_purge(&local->skb_queue_unreliable);
|
||||
skb_queue_purge(&local->skb_queue_tdls_chsw);
|
||||
ieee80211_txq_teardown_flows(local);
|
||||
|
||||
destroy_workqueue(local->workqueue);
|
||||
wiphy_unregister(local->hw.wiphy);
|
||||
|
|
|
@ -1268,7 +1268,7 @@ static void sta_ps_start(struct sta_info *sta)
|
|||
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
|
||||
struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
|
||||
|
||||
if (!skb_queue_len(&txqi->queue))
|
||||
if (!txqi->tin.backlog_packets)
|
||||
set_bit(tid, &sta->txq_buffered_tids);
|
||||
else
|
||||
clear_bit(tid, &sta->txq_buffered_tids);
|
||||
|
|
|
@ -90,6 +90,7 @@ static void __cleanup_single_sta(struct sta_info *sta)
|
|||
struct tid_ampdu_tx *tid_tx;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct fq *fq = &local->fq;
|
||||
struct ps_data *ps;
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA) ||
|
||||
|
@ -113,11 +114,10 @@ static void __cleanup_single_sta(struct sta_info *sta)
|
|||
if (sta->sta.txq[0]) {
|
||||
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
|
||||
int n = skb_queue_len(&txqi->queue);
|
||||
|
||||
ieee80211_purge_tx_queue(&local->hw, &txqi->queue);
|
||||
atomic_sub(n, &sdata->txqs_len[txqi->txq.ac]);
|
||||
txqi->byte_cnt = 0;
|
||||
spin_lock_bh(&fq->lock);
|
||||
ieee80211_txq_purge(local, txqi);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,7 +368,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
struct txq_info *txq = txq_data + i * size;
|
||||
|
||||
ieee80211_init_tx_queue(sdata, sta, txq, i);
|
||||
ieee80211_txq_init(sdata, sta, txq, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1211,7 +1211,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
|
|||
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
|
||||
struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
|
||||
|
||||
if (!skb_queue_len(&txqi->queue))
|
||||
if (!txqi->tin.backlog_packets)
|
||||
continue;
|
||||
|
||||
drv_wake_tx_queue(local, txqi);
|
||||
|
@ -1648,7 +1648,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
|
|||
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
|
||||
struct txq_info *txqi = to_txq_info(sta->sta.txq[tid]);
|
||||
|
||||
if (!(tids & BIT(tid)) || skb_queue_len(&txqi->queue))
|
||||
if (!(tids & BIT(tid)) || txqi->tin.backlog_packets)
|
||||
continue;
|
||||
|
||||
sta_info_recalc_tim(sta);
|
||||
|
|
|
@ -24,7 +24,10 @@
|
|||
#include <net/ieee80211_radiotap.h>
|
||||
#include <net/cfg80211.h>
|
||||
#include <net/mac80211.h>
|
||||
#include <net/codel.h>
|
||||
#include <net/codel_impl.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <net/fq_impl.h>
|
||||
|
||||
#include "ieee80211_i.h"
|
||||
#include "driver-ops.h"
|
||||
|
@ -1236,27 +1239,21 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
|
|||
return TX_CONTINUE;
|
||||
}
|
||||
|
||||
static void ieee80211_drv_tx(struct ieee80211_local *local,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *pubsta,
|
||||
struct sk_buff *skb)
|
||||
static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *pubsta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_control control = {
|
||||
.sta = pubsta,
|
||||
};
|
||||
struct ieee80211_txq *txq = NULL;
|
||||
struct txq_info *txqi;
|
||||
u8 ac;
|
||||
|
||||
if ((info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) ||
|
||||
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
|
||||
goto tx_normal;
|
||||
return NULL;
|
||||
|
||||
if (!ieee80211_is_data(hdr->frame_control))
|
||||
goto tx_normal;
|
||||
return NULL;
|
||||
|
||||
if (pubsta) {
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
||||
|
@ -1267,51 +1264,230 @@ static void ieee80211_drv_tx(struct ieee80211_local *local,
|
|||
}
|
||||
|
||||
if (!txq)
|
||||
goto tx_normal;
|
||||
return NULL;
|
||||
|
||||
ac = txq->ac;
|
||||
txqi = to_txq_info(txq);
|
||||
atomic_inc(&sdata->txqs_len[ac]);
|
||||
if (atomic_read(&sdata->txqs_len[ac]) >= local->hw.txq_ac_max_pending)
|
||||
netif_stop_subqueue(sdata->dev, ac);
|
||||
return to_txq_info(txq);
|
||||
}
|
||||
|
||||
spin_lock_bh(&txqi->queue.lock);
|
||||
txqi->byte_cnt += skb->len;
|
||||
__skb_queue_tail(&txqi->queue, skb);
|
||||
spin_unlock_bh(&txqi->queue.lock);
|
||||
static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
|
||||
{
|
||||
IEEE80211_SKB_CB(skb)->control.enqueue_time = codel_get_time();
|
||||
}
|
||||
|
||||
drv_wake_tx_queue(local, txqi);
|
||||
static void ieee80211_set_skb_vif(struct sk_buff *skb, struct txq_info *txqi)
|
||||
{
|
||||
IEEE80211_SKB_CB(skb)->control.vif = txqi->txq.vif;
|
||||
}
|
||||
|
||||
return;
|
||||
static u32 codel_skb_len_func(const struct sk_buff *skb)
|
||||
{
|
||||
return skb->len;
|
||||
}
|
||||
|
||||
tx_normal:
|
||||
drv_tx(local, &control, skb);
|
||||
static codel_time_t codel_skb_time_func(const struct sk_buff *skb)
|
||||
{
|
||||
const struct ieee80211_tx_info *info;
|
||||
|
||||
info = (const struct ieee80211_tx_info *)skb->cb;
|
||||
return info->control.enqueue_time;
|
||||
}
|
||||
|
||||
static struct sk_buff *codel_dequeue_func(struct codel_vars *cvars,
|
||||
void *ctx)
|
||||
{
|
||||
struct ieee80211_local *local;
|
||||
struct txq_info *txqi;
|
||||
struct fq *fq;
|
||||
struct fq_flow *flow;
|
||||
|
||||
txqi = ctx;
|
||||
local = vif_to_sdata(txqi->txq.vif)->local;
|
||||
fq = &local->fq;
|
||||
|
||||
if (cvars == &txqi->def_cvars)
|
||||
flow = &txqi->def_flow;
|
||||
else
|
||||
flow = &fq->flows[cvars - local->cvars];
|
||||
|
||||
return fq_flow_dequeue(fq, flow);
|
||||
}
|
||||
|
||||
static void codel_drop_func(struct sk_buff *skb,
|
||||
void *ctx)
|
||||
{
|
||||
struct ieee80211_local *local;
|
||||
struct ieee80211_hw *hw;
|
||||
struct txq_info *txqi;
|
||||
|
||||
txqi = ctx;
|
||||
local = vif_to_sdata(txqi->txq.vif)->local;
|
||||
hw = &local->hw;
|
||||
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
}
|
||||
|
||||
static struct sk_buff *fq_tin_dequeue_func(struct fq *fq,
|
||||
struct fq_tin *tin,
|
||||
struct fq_flow *flow)
|
||||
{
|
||||
struct ieee80211_local *local;
|
||||
struct txq_info *txqi;
|
||||
struct codel_vars *cvars;
|
||||
struct codel_params *cparams;
|
||||
struct codel_stats *cstats;
|
||||
|
||||
local = container_of(fq, struct ieee80211_local, fq);
|
||||
txqi = container_of(tin, struct txq_info, tin);
|
||||
cparams = &local->cparams;
|
||||
cstats = &local->cstats;
|
||||
|
||||
if (flow == &txqi->def_flow)
|
||||
cvars = &txqi->def_cvars;
|
||||
else
|
||||
cvars = &local->cvars[flow - fq->flows];
|
||||
|
||||
return codel_dequeue(txqi,
|
||||
&flow->backlog,
|
||||
cparams,
|
||||
cvars,
|
||||
cstats,
|
||||
codel_skb_len_func,
|
||||
codel_skb_time_func,
|
||||
codel_drop_func,
|
||||
codel_dequeue_func);
|
||||
}
|
||||
|
||||
static void fq_skb_free_func(struct fq *fq,
|
||||
struct fq_tin *tin,
|
||||
struct fq_flow *flow,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local;
|
||||
|
||||
local = container_of(fq, struct ieee80211_local, fq);
|
||||
ieee80211_free_txskb(&local->hw, skb);
|
||||
}
|
||||
|
||||
static struct fq_flow *fq_flow_get_default_func(struct fq *fq,
|
||||
struct fq_tin *tin,
|
||||
int idx,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct txq_info *txqi;
|
||||
|
||||
txqi = container_of(tin, struct txq_info, tin);
|
||||
return &txqi->def_flow;
|
||||
}
|
||||
|
||||
static void ieee80211_txq_enqueue(struct ieee80211_local *local,
|
||||
struct txq_info *txqi,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct fq *fq = &local->fq;
|
||||
struct fq_tin *tin = &txqi->tin;
|
||||
|
||||
ieee80211_set_skb_enqueue_time(skb);
|
||||
fq_tin_enqueue(fq, tin, skb,
|
||||
fq_skb_free_func,
|
||||
fq_flow_get_default_func);
|
||||
}
|
||||
|
||||
void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
struct txq_info *txqi, int tid)
|
||||
{
|
||||
fq_tin_init(&txqi->tin);
|
||||
fq_flow_init(&txqi->def_flow);
|
||||
codel_vars_init(&txqi->def_cvars);
|
||||
|
||||
txqi->txq.vif = &sdata->vif;
|
||||
|
||||
if (sta) {
|
||||
txqi->txq.sta = &sta->sta;
|
||||
sta->sta.txq[tid] = &txqi->txq;
|
||||
txqi->txq.tid = tid;
|
||||
txqi->txq.ac = ieee802_1d_to_ac[tid & 7];
|
||||
} else {
|
||||
sdata->vif.txq = &txqi->txq;
|
||||
txqi->txq.tid = 0;
|
||||
txqi->txq.ac = IEEE80211_AC_BE;
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_txq_purge(struct ieee80211_local *local,
|
||||
struct txq_info *txqi)
|
||||
{
|
||||
struct fq *fq = &local->fq;
|
||||
struct fq_tin *tin = &txqi->tin;
|
||||
|
||||
fq_tin_reset(fq, tin, fq_skb_free_func);
|
||||
}
|
||||
|
||||
int ieee80211_txq_setup_flows(struct ieee80211_local *local)
|
||||
{
|
||||
struct fq *fq = &local->fq;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (!local->ops->wake_tx_queue)
|
||||
return 0;
|
||||
|
||||
ret = fq_init(fq, 4096);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
codel_params_init(&local->cparams);
|
||||
codel_stats_init(&local->cstats);
|
||||
local->cparams.interval = MS2TIME(100);
|
||||
local->cparams.target = MS2TIME(20);
|
||||
local->cparams.ecn = true;
|
||||
|
||||
local->cvars = kcalloc(fq->flows_cnt, sizeof(local->cvars[0]),
|
||||
GFP_KERNEL);
|
||||
if (!local->cvars) {
|
||||
fq_reset(fq, fq_skb_free_func);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = 0; i < fq->flows_cnt; i++)
|
||||
codel_vars_init(&local->cvars[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ieee80211_txq_teardown_flows(struct ieee80211_local *local)
|
||||
{
|
||||
struct fq *fq = &local->fq;
|
||||
|
||||
if (!local->ops->wake_tx_queue)
|
||||
return;
|
||||
|
||||
kfree(local->cvars);
|
||||
local->cvars = NULL;
|
||||
|
||||
fq_reset(fq, fq_skb_free_func);
|
||||
}
|
||||
|
||||
struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
|
||||
struct ieee80211_txq *txq)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
|
||||
struct txq_info *txqi = container_of(txq, struct txq_info, txq);
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct sk_buff *skb = NULL;
|
||||
u8 ac = txq->ac;
|
||||
struct fq *fq = &local->fq;
|
||||
struct fq_tin *tin = &txqi->tin;
|
||||
|
||||
spin_lock_bh(&txqi->queue.lock);
|
||||
spin_lock_bh(&fq->lock);
|
||||
|
||||
if (test_bit(IEEE80211_TXQ_STOP, &txqi->flags))
|
||||
goto out;
|
||||
|
||||
skb = __skb_dequeue(&txqi->queue);
|
||||
skb = fq_tin_dequeue(fq, tin, fq_tin_dequeue_func);
|
||||
if (!skb)
|
||||
goto out;
|
||||
|
||||
txqi->byte_cnt -= skb->len;
|
||||
|
||||
atomic_dec(&sdata->txqs_len[ac]);
|
||||
if (__netif_subqueue_stopped(sdata->dev, ac))
|
||||
ieee80211_propagate_queue_wake(local, sdata->vif.hw_queue[ac]);
|
||||
ieee80211_set_skb_vif(skb, txqi);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
if (txq->sta && ieee80211_is_data_qos(hdr->frame_control)) {
|
||||
|
@ -1327,7 +1503,7 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&txqi->queue.lock);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
|
||||
if (skb && skb_has_frag_list(skb) &&
|
||||
!ieee80211_hw_check(&local->hw, TX_FRAG_LIST))
|
||||
|
@ -1343,7 +1519,10 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
|||
struct sk_buff_head *skbs,
|
||||
bool txpending)
|
||||
{
|
||||
struct ieee80211_tx_control control = {};
|
||||
struct fq *fq = &local->fq;
|
||||
struct sk_buff *skb, *tmp;
|
||||
struct txq_info *txqi;
|
||||
unsigned long flags;
|
||||
|
||||
skb_queue_walk_safe(skbs, skb, tmp) {
|
||||
|
@ -1358,6 +1537,21 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
|||
}
|
||||
#endif
|
||||
|
||||
txqi = ieee80211_get_txq(local, vif, sta, skb);
|
||||
if (txqi) {
|
||||
info->control.vif = vif;
|
||||
|
||||
__skb_unlink(skb, skbs);
|
||||
|
||||
spin_lock_bh(&fq->lock);
|
||||
ieee80211_txq_enqueue(local, txqi, skb);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
|
||||
drv_wake_tx_queue(local, txqi);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
||||
if (local->queue_stop_reasons[q] ||
|
||||
(!txpending && !skb_queue_empty(&local->pending[q]))) {
|
||||
|
@ -1400,9 +1594,10 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
|||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||
|
||||
info->control.vif = vif;
|
||||
control.sta = sta;
|
||||
|
||||
__skb_unlink(skb, skbs);
|
||||
ieee80211_drv_tx(local, vif, sta, skb);
|
||||
drv_tx(local, &control, skb);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2882,6 +3077,9 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
|
|||
struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct fq *fq = &local->fq;
|
||||
struct fq_tin *tin;
|
||||
struct fq_flow *flow;
|
||||
u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
|
||||
struct ieee80211_txq *txq = sta->sta.txq[tid];
|
||||
struct txq_info *txqi;
|
||||
|
@ -2893,6 +3091,7 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
|
|||
__be16 len;
|
||||
void *data;
|
||||
bool ret = false;
|
||||
unsigned int orig_len;
|
||||
int n = 1, nfrags;
|
||||
|
||||
if (!ieee80211_hw_check(&local->hw, TX_AMSDU))
|
||||
|
@ -2909,12 +3108,20 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
|
|||
max_amsdu_len = min_t(int, max_amsdu_len,
|
||||
sta->sta.max_rc_amsdu_len);
|
||||
|
||||
spin_lock_bh(&txqi->queue.lock);
|
||||
spin_lock_bh(&fq->lock);
|
||||
|
||||
head = skb_peek_tail(&txqi->queue);
|
||||
/* TODO: Ideally aggregation should be done on dequeue to remain
|
||||
* responsive to environment changes.
|
||||
*/
|
||||
|
||||
tin = &txqi->tin;
|
||||
flow = fq_flow_classify(fq, tin, skb, fq_flow_get_default_func);
|
||||
head = skb_peek_tail(&flow->queue);
|
||||
if (!head)
|
||||
goto out;
|
||||
|
||||
orig_len = head->len;
|
||||
|
||||
if (skb->len + head->len > max_amsdu_len)
|
||||
goto out;
|
||||
|
||||
|
@ -2953,8 +3160,13 @@ static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
|
|||
head->data_len += skb->len;
|
||||
*frag_tail = skb;
|
||||
|
||||
flow->backlog += head->len - orig_len;
|
||||
tin->backlog_bytes += head->len - orig_len;
|
||||
|
||||
fq_recalc_backlog(fq, tin, flow);
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&txqi->queue.lock);
|
||||
spin_unlock_bh(&fq->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -244,6 +244,9 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
|
|||
struct ieee80211_sub_if_data *sdata;
|
||||
int n_acs = IEEE80211_NUM_ACS;
|
||||
|
||||
if (local->ops->wake_tx_queue)
|
||||
return;
|
||||
|
||||
if (local->hw.queues < IEEE80211_NUM_ACS)
|
||||
n_acs = 1;
|
||||
|
||||
|
@ -260,11 +263,6 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
|
|||
for (ac = 0; ac < n_acs; ac++) {
|
||||
int ac_queue = sdata->vif.hw_queue[ac];
|
||||
|
||||
if (local->ops->wake_tx_queue &&
|
||||
(atomic_read(&sdata->txqs_len[ac]) >
|
||||
local->hw.txq_ac_max_pending))
|
||||
continue;
|
||||
|
||||
if (ac_queue == queue ||
|
||||
(sdata->vif.cab_queue == queue &&
|
||||
local->queue_stop_reasons[ac_queue] == 0 &&
|
||||
|
@ -352,6 +350,9 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
|
|||
if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
|
||||
return;
|
||||
|
||||
if (local->ops->wake_tx_queue)
|
||||
return;
|
||||
|
||||
if (local->hw.queues < IEEE80211_NUM_ACS)
|
||||
n_acs = 1;
|
||||
|
||||
|
@ -3388,25 +3389,6 @@ u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo)
|
|||
return buf;
|
||||
}
|
||||
|
||||
void ieee80211_init_tx_queue(struct ieee80211_sub_if_data *sdata,
|
||||
struct sta_info *sta,
|
||||
struct txq_info *txqi, int tid)
|
||||
{
|
||||
skb_queue_head_init(&txqi->queue);
|
||||
txqi->txq.vif = &sdata->vif;
|
||||
|
||||
if (sta) {
|
||||
txqi->txq.sta = &sta->sta;
|
||||
sta->sta.txq[tid] = &txqi->txq;
|
||||
txqi->txq.tid = tid;
|
||||
txqi->txq.ac = ieee802_1d_to_ac[tid & 7];
|
||||
} else {
|
||||
sdata->vif.txq = &txqi->txq;
|
||||
txqi->txq.tid = 0;
|
||||
txqi->txq.ac = IEEE80211_AC_BE;
|
||||
}
|
||||
}
|
||||
|
||||
void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
|
||||
unsigned long *frame_cnt,
|
||||
unsigned long *byte_cnt)
|
||||
|
@ -3414,9 +3396,9 @@ void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
|
|||
struct txq_info *txqi = to_txq_info(txq);
|
||||
|
||||
if (frame_cnt)
|
||||
*frame_cnt = txqi->queue.qlen;
|
||||
*frame_cnt = txqi->tin.backlog_packets;
|
||||
|
||||
if (byte_cnt)
|
||||
*byte_cnt = txqi->byte_cnt;
|
||||
*byte_cnt = txqi->tin.backlog_bytes;
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_txq_get_depth);
|
||||
|
|
|
@ -748,6 +748,36 @@ int wiphy_register(struct wiphy *wiphy)
|
|||
nl80211_send_reg_change_event(&request);
|
||||
}
|
||||
|
||||
/* Check that nobody globally advertises any capabilities they do not
|
||||
* advertise on all possible interface types.
|
||||
*/
|
||||
if (wiphy->extended_capabilities_len &&
|
||||
wiphy->num_iftype_ext_capab &&
|
||||
wiphy->iftype_ext_capab) {
|
||||
u8 supported_on_all, j;
|
||||
const struct wiphy_iftype_ext_capab *capab;
|
||||
|
||||
capab = wiphy->iftype_ext_capab;
|
||||
for (j = 0; j < wiphy->extended_capabilities_len; j++) {
|
||||
if (capab[0].extended_capabilities_len > j)
|
||||
supported_on_all =
|
||||
capab[0].extended_capabilities[j];
|
||||
else
|
||||
supported_on_all = 0x00;
|
||||
for (i = 1; i < wiphy->num_iftype_ext_capab; i++) {
|
||||
if (j >= capab[i].extended_capabilities_len) {
|
||||
supported_on_all = 0x00;
|
||||
break;
|
||||
}
|
||||
supported_on_all &=
|
||||
capab[i].extended_capabilities[j];
|
||||
}
|
||||
if (WARN_ON(wiphy->extended_capabilities[j] &
|
||||
~supported_on_all))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rdev->wiphy.registered = true;
|
||||
rtnl_unlock();
|
||||
|
||||
|
|
|
@ -214,7 +214,7 @@ struct cfg80211_event {
|
|||
size_t req_ie_len;
|
||||
size_t resp_ie_len;
|
||||
struct cfg80211_bss *bss;
|
||||
u16 status;
|
||||
int status; /* -1 = failed; 0..65535 = status code */
|
||||
} cr;
|
||||
struct {
|
||||
const u8 *req_ie;
|
||||
|
@ -374,7 +374,7 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
|||
void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, bool wextev,
|
||||
int status, bool wextev,
|
||||
struct cfg80211_bss *bss);
|
||||
void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
|
||||
size_t ie_len, u16 reason, bool from_ap);
|
||||
|
|
|
@ -167,6 +167,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
|
|||
|
||||
if (attrs[NL80211_ATTR_IFINDEX]) {
|
||||
int ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]);
|
||||
|
||||
netdev = __dev_get_by_index(netns, ifindex);
|
||||
if (netdev) {
|
||||
if (netdev->ieee80211_ptr)
|
||||
|
@ -731,6 +732,7 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
|
|||
|
||||
if (tb[NL80211_KEY_DEFAULT_TYPES]) {
|
||||
struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
|
||||
|
||||
err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
|
||||
tb[NL80211_KEY_DEFAULT_TYPES],
|
||||
nl80211_key_default_policy);
|
||||
|
@ -1264,7 +1266,7 @@ nl80211_send_mgmt_stypes(struct sk_buff *msg,
|
|||
struct nl80211_dump_wiphy_state {
|
||||
s64 filter_wiphy;
|
||||
long start;
|
||||
long split_start, band_start, chan_start;
|
||||
long split_start, band_start, chan_start, capa_start;
|
||||
bool split;
|
||||
};
|
||||
|
||||
|
@ -1382,6 +1384,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
rdev->ops->get_antenna) {
|
||||
u32 tx_ant = 0, rx_ant = 0;
|
||||
int res;
|
||||
|
||||
res = rdev_get_antenna(rdev, &tx_ant, &rx_ant);
|
||||
if (!res) {
|
||||
if (nla_put_u32(msg,
|
||||
|
@ -1761,6 +1764,47 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
|
|||
nla_nest_end(msg, nested);
|
||||
}
|
||||
|
||||
state->split_start++;
|
||||
break;
|
||||
case 13:
|
||||
if (rdev->wiphy.num_iftype_ext_capab &&
|
||||
rdev->wiphy.iftype_ext_capab) {
|
||||
struct nlattr *nested_ext_capab, *nested;
|
||||
|
||||
nested = nla_nest_start(msg,
|
||||
NL80211_ATTR_IFTYPE_EXT_CAPA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
|
||||
for (i = state->capa_start;
|
||||
i < rdev->wiphy.num_iftype_ext_capab; i++) {
|
||||
const struct wiphy_iftype_ext_capab *capab;
|
||||
|
||||
capab = &rdev->wiphy.iftype_ext_capab[i];
|
||||
|
||||
nested_ext_capab = nla_nest_start(msg, i);
|
||||
if (!nested_ext_capab ||
|
||||
nla_put_u32(msg, NL80211_ATTR_IFTYPE,
|
||||
capab->iftype) ||
|
||||
nla_put(msg, NL80211_ATTR_EXT_CAPA,
|
||||
capab->extended_capabilities_len,
|
||||
capab->extended_capabilities) ||
|
||||
nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
|
||||
capab->extended_capabilities_len,
|
||||
capab->extended_capabilities_mask))
|
||||
goto nla_put_failure;
|
||||
|
||||
nla_nest_end(msg, nested_ext_capab);
|
||||
if (state->split)
|
||||
break;
|
||||
}
|
||||
nla_nest_end(msg, nested);
|
||||
if (i < rdev->wiphy.num_iftype_ext_capab) {
|
||||
state->capa_start = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* done */
|
||||
state->split_start = 0;
|
||||
break;
|
||||
|
@ -2116,7 +2160,6 @@ static int nl80211_set_wds_peer(struct sk_buff *skb, struct genl_info *info)
|
|||
return rdev_set_wds_peer(rdev, dev, bssid);
|
||||
}
|
||||
|
||||
|
||||
static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
|
@ -2251,6 +2294,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
|
|||
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
|
||||
info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]) {
|
||||
u32 tx_ant, rx_ant;
|
||||
|
||||
if ((!rdev->wiphy.available_antennas_tx &&
|
||||
!rdev->wiphy.available_antennas_rx) ||
|
||||
!rdev->ops->set_antenna)
|
||||
|
@ -2919,6 +2963,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
|
|||
pairwise = !!mac_addr;
|
||||
if (info->attrs[NL80211_ATTR_KEY_TYPE]) {
|
||||
u32 kt = nla_get_u32(info->attrs[NL80211_ATTR_KEY_TYPE]);
|
||||
|
||||
if (kt >= NUM_NL80211_KEYTYPES)
|
||||
return -EINVAL;
|
||||
if (kt != NL80211_KEYTYPE_GROUP &&
|
||||
|
@ -3962,7 +4007,6 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|||
sta_idx++;
|
||||
}
|
||||
|
||||
|
||||
out:
|
||||
cb->args[2] = sta_idx;
|
||||
err = skb->len;
|
||||
|
@ -4763,7 +4807,6 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|||
path_idx++;
|
||||
}
|
||||
|
||||
|
||||
out:
|
||||
cb->args[2] = path_idx;
|
||||
err = skb->len;
|
||||
|
@ -5053,7 +5096,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
enum nl80211_user_reg_hint_type user_reg_hint_type;
|
||||
u32 owner_nlportid;
|
||||
|
||||
|
||||
/*
|
||||
* You should only get this when cfg80211 hasn't yet initialized
|
||||
* completely when built-in to the kernel right between the time
|
||||
|
@ -5262,7 +5304,6 @@ do { \
|
|||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
if (!info->attrs[NL80211_ATTR_MESH_CONFIG])
|
||||
return -EINVAL;
|
||||
if (nla_parse_nested(tb, NL80211_MESHCONF_ATTR_MAX,
|
||||
|
@ -5409,7 +5450,6 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
|
|||
IEEE80211_PATH_METRIC_VENDOR :
|
||||
IEEE80211_PATH_METRIC_AIRTIME;
|
||||
|
||||
|
||||
if (tb[NL80211_MESH_SETUP_IE]) {
|
||||
struct nlattr *ieattr =
|
||||
tb[NL80211_MESH_SETUP_IE];
|
||||
|
@ -5796,10 +5836,8 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
r = set_regdom(rd, REGD_SOURCE_CRDA);
|
||||
/* set_regdom took ownership */
|
||||
rd = NULL;
|
||||
|
||||
/* set_regdom takes ownership of rd */
|
||||
return set_regdom(rd, REGD_SOURCE_CRDA);
|
||||
bad_reg:
|
||||
kfree(rd);
|
||||
return r;
|
||||
|
@ -6033,6 +6071,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
|||
/* all channels */
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
int j;
|
||||
|
||||
if (!wiphy->bands[band])
|
||||
continue;
|
||||
for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
|
||||
|
@ -6442,6 +6481,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
/* all channels */
|
||||
for (band = 0; band < NUM_NL80211_BANDS; band++) {
|
||||
int j;
|
||||
|
||||
if (!wiphy->bands[band])
|
||||
continue;
|
||||
for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
|
||||
|
@ -6511,7 +6551,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
|
|||
nla_data(ssid), nla_len(ssid));
|
||||
request->match_sets[i].ssid.ssid_len =
|
||||
nla_len(ssid);
|
||||
/* special attribute - old implemenation w/a */
|
||||
/* special attribute - old implementation w/a */
|
||||
request->match_sets[i].rssi_thold =
|
||||
default_match_rssi;
|
||||
rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI];
|
||||
|
@ -7204,6 +7244,7 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info)
|
|||
if (key.idx >= 0) {
|
||||
int i;
|
||||
bool ok = false;
|
||||
|
||||
for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) {
|
||||
if (key.p.cipher == rdev->wiphy.cipher_suites[i]) {
|
||||
ok = true;
|
||||
|
@ -7282,6 +7323,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,
|
|||
|
||||
if (info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) {
|
||||
u16 proto;
|
||||
|
||||
proto = nla_get_u16(
|
||||
info->attrs[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]);
|
||||
settings->control_port_ethertype = cpu_to_be16(proto);
|
||||
|
@ -8435,6 +8477,7 @@ static u32 rateset_to_mask(struct ieee80211_supported_band *sband,
|
|||
for (i = 0; i < rates_len; i++) {
|
||||
int rate = (rates[i] & 0x7f) * 5;
|
||||
int ridx;
|
||||
|
||||
for (ridx = 0; ridx < sband->n_bitrates; ridx++) {
|
||||
struct ieee80211_rate *srate =
|
||||
&sband->bitrates[ridx];
|
||||
|
@ -8743,7 +8786,6 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info)
|
|||
if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
|
||||
params.wait > rdev->wiphy.max_remain_on_channel_duration)
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
|
||||
|
@ -10590,7 +10632,6 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(cfg80211_vendor_cmd_reply);
|
||||
|
||||
|
||||
static int nl80211_set_qos_map(struct sk_buff *skb,
|
||||
struct genl_info *info)
|
||||
{
|
||||
|
@ -10945,7 +10986,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_WIPHY,
|
||||
.doit = nl80211_set_wiphy,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
|
@ -10961,7 +11002,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_INTERFACE,
|
||||
.doit = nl80211_set_interface,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -10969,7 +11010,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_NEW_INTERFACE,
|
||||
.doit = nl80211_new_interface,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -10977,7 +11018,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DEL_INTERFACE,
|
||||
.doit = nl80211_del_interface,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -10985,7 +11026,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_GET_KEY,
|
||||
.doit = nl80211_get_key,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -10993,7 +11034,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_KEY,
|
||||
.doit = nl80211_set_key,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL |
|
||||
NL80211_FLAG_CLEAR_SKB,
|
||||
|
@ -11002,7 +11043,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_NEW_KEY,
|
||||
.doit = nl80211_new_key,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL |
|
||||
NL80211_FLAG_CLEAR_SKB,
|
||||
|
@ -11011,14 +11052,14 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DEL_KEY,
|
||||
.doit = nl80211_del_key,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
{
|
||||
.cmd = NL80211_CMD_SET_BEACON,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.doit = nl80211_set_beacon,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
|
@ -11026,7 +11067,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
{
|
||||
.cmd = NL80211_CMD_START_AP,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.doit = nl80211_start_ap,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
|
@ -11034,7 +11075,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
{
|
||||
.cmd = NL80211_CMD_STOP_AP,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.doit = nl80211_stop_ap,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
|
@ -11051,7 +11092,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_STATION,
|
||||
.doit = nl80211_set_station,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11059,7 +11100,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_NEW_STATION,
|
||||
.doit = nl80211_new_station,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11067,7 +11108,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DEL_STATION,
|
||||
.doit = nl80211_del_station,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11076,7 +11117,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.doit = nl80211_get_mpath,
|
||||
.dumpit = nl80211_dump_mpath,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11085,7 +11126,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.doit = nl80211_get_mpp,
|
||||
.dumpit = nl80211_dump_mpp,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11093,7 +11134,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_MPATH,
|
||||
.doit = nl80211_set_mpath,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11101,7 +11142,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_NEW_MPATH,
|
||||
.doit = nl80211_new_mpath,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11109,7 +11150,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DEL_MPATH,
|
||||
.doit = nl80211_del_mpath,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11117,7 +11158,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_BSS,
|
||||
.doit = nl80211_set_bss,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11156,7 +11197,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_MESH_CONFIG,
|
||||
.doit = nl80211_update_mesh_config,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11164,7 +11205,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_TRIGGER_SCAN,
|
||||
.doit = nl80211_trigger_scan,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11172,7 +11213,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_ABORT_SCAN,
|
||||
.doit = nl80211_abort_scan,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11185,7 +11226,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_START_SCHED_SCAN,
|
||||
.doit = nl80211_start_sched_scan,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11193,7 +11234,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_STOP_SCHED_SCAN,
|
||||
.doit = nl80211_stop_sched_scan,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11201,7 +11242,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_AUTHENTICATE,
|
||||
.doit = nl80211_authenticate,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL |
|
||||
NL80211_FLAG_CLEAR_SKB,
|
||||
|
@ -11210,7 +11251,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_ASSOCIATE,
|
||||
.doit = nl80211_associate,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11218,7 +11259,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DEAUTHENTICATE,
|
||||
.doit = nl80211_deauthenticate,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11226,7 +11267,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DISASSOCIATE,
|
||||
.doit = nl80211_disassociate,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11234,7 +11275,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_JOIN_IBSS,
|
||||
.doit = nl80211_join_ibss,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11242,7 +11283,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_LEAVE_IBSS,
|
||||
.doit = nl80211_leave_ibss,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11252,7 +11293,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.doit = nl80211_testmode_do,
|
||||
.dumpit = nl80211_testmode_dump,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11261,7 +11302,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_CONNECT,
|
||||
.doit = nl80211_connect,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11269,7 +11310,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DISCONNECT,
|
||||
.doit = nl80211_disconnect,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11277,7 +11318,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_WIPHY_NETNS,
|
||||
.doit = nl80211_wiphy_netns,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11290,7 +11331,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_PMKSA,
|
||||
.doit = nl80211_setdel_pmksa,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11298,7 +11339,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DEL_PMKSA,
|
||||
.doit = nl80211_setdel_pmksa,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11306,7 +11347,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_FLUSH_PMKSA,
|
||||
.doit = nl80211_flush_pmksa,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11314,7 +11355,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_REMAIN_ON_CHANNEL,
|
||||
.doit = nl80211_remain_on_channel,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11322,7 +11363,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL,
|
||||
.doit = nl80211_cancel_remain_on_channel,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11330,7 +11371,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_TX_BITRATE_MASK,
|
||||
.doit = nl80211_set_tx_bitrate_mask,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11338,7 +11379,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_REGISTER_FRAME,
|
||||
.doit = nl80211_register_mgmt,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11346,7 +11387,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_FRAME,
|
||||
.doit = nl80211_tx_mgmt,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11354,7 +11395,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_FRAME_WAIT_CANCEL,
|
||||
.doit = nl80211_tx_mgmt_cancel_wait,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11362,7 +11403,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_POWER_SAVE,
|
||||
.doit = nl80211_set_power_save,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11378,7 +11419,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_CQM,
|
||||
.doit = nl80211_set_cqm,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11386,7 +11427,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_CHANNEL,
|
||||
.doit = nl80211_set_channel,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11394,7 +11435,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_WDS_PEER,
|
||||
.doit = nl80211_set_wds_peer,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11402,7 +11443,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_JOIN_MESH,
|
||||
.doit = nl80211_join_mesh,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11410,7 +11451,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_LEAVE_MESH,
|
||||
.doit = nl80211_leave_mesh,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11418,7 +11459,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_JOIN_OCB,
|
||||
.doit = nl80211_join_ocb,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11426,7 +11467,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_LEAVE_OCB,
|
||||
.doit = nl80211_leave_ocb,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11443,7 +11484,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_WOWLAN,
|
||||
.doit = nl80211_set_wowlan,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11452,7 +11493,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_REKEY_OFFLOAD,
|
||||
.doit = nl80211_set_rekey_data,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL |
|
||||
NL80211_FLAG_CLEAR_SKB,
|
||||
|
@ -11461,7 +11502,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_TDLS_MGMT,
|
||||
.doit = nl80211_tdls_mgmt,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11469,7 +11510,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_TDLS_OPER,
|
||||
.doit = nl80211_tdls_oper,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11477,7 +11518,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_UNEXPECTED_FRAME,
|
||||
.doit = nl80211_register_unexpected_frame,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11485,7 +11526,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_PROBE_CLIENT,
|
||||
.doit = nl80211_probe_client,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11493,7 +11534,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_REGISTER_BEACONS,
|
||||
.doit = nl80211_register_beacons,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11501,7 +11542,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_NOACK_MAP,
|
||||
.doit = nl80211_set_noack_map,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11509,7 +11550,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_START_P2P_DEVICE,
|
||||
.doit = nl80211_start_p2p_device,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11517,7 +11558,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_STOP_P2P_DEVICE,
|
||||
.doit = nl80211_stop_p2p_device,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11525,7 +11566,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_MCAST_RATE,
|
||||
.doit = nl80211_set_mcast_rate,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11533,7 +11574,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_MAC_ACL,
|
||||
.doit = nl80211_set_mac_acl,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11541,7 +11582,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_RADAR_DETECT,
|
||||
.doit = nl80211_start_radar_detection,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11554,7 +11595,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_UPDATE_FT_IES,
|
||||
.doit = nl80211_update_ft_ies,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11562,7 +11603,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_CRIT_PROTOCOL_START,
|
||||
.doit = nl80211_crit_protocol_start,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11570,7 +11611,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_CRIT_PROTOCOL_STOP,
|
||||
.doit = nl80211_crit_protocol_stop,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11585,7 +11626,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_COALESCE,
|
||||
.doit = nl80211_set_coalesce,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11593,7 +11634,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_CHANNEL_SWITCH,
|
||||
.doit = nl80211_channel_switch,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11602,7 +11643,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.doit = nl80211_vendor_cmd,
|
||||
.dumpit = nl80211_vendor_cmd_dump,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_WIPHY |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11610,7 +11651,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_SET_QOS_MAP,
|
||||
.doit = nl80211_set_qos_map,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11618,7 +11659,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_ADD_TX_TS,
|
||||
.doit = nl80211_add_tx_ts,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11626,7 +11667,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_DEL_TX_TS,
|
||||
.doit = nl80211_del_tx_ts,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11634,7 +11675,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
|
||||
.doit = nl80211_tdls_channel_switch,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -11642,7 +11683,7 @@ static const struct genl_ops nl80211_ops[] = {
|
|||
.cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
|
||||
.doit = nl80211_tdls_cancel_channel_switch,
|
||||
.policy = nl80211_policy,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.flags = GENL_UNS_ADMIN_PERM,
|
||||
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
|
||||
NL80211_FLAG_NEED_RTNL,
|
||||
},
|
||||
|
@ -12092,7 +12133,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *netdev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, gfp_t gfp)
|
||||
int status, gfp_t gfp)
|
||||
{
|
||||
struct sk_buff *msg;
|
||||
void *hdr;
|
||||
|
@ -12110,7 +12151,10 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
|
|||
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
|
||||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
|
||||
(bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) ||
|
||||
nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, status) ||
|
||||
nla_put_u16(msg, NL80211_ATTR_STATUS_CODE,
|
||||
status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE :
|
||||
status) ||
|
||||
(status < 0 && nla_put_flag(msg, NL80211_ATTR_TIMED_OUT)) ||
|
||||
(req_ie &&
|
||||
nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) ||
|
||||
(resp_ie &&
|
||||
|
@ -12126,7 +12170,6 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
|
|||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
|
||||
}
|
||||
|
||||
void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
|
||||
|
@ -12165,7 +12208,6 @@ void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
|
|||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
|
||||
}
|
||||
|
||||
void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
|
||||
|
@ -12203,7 +12245,6 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
|
|||
nla_put_failure:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
|
||||
}
|
||||
|
||||
void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
|
||||
|
@ -13545,7 +13586,6 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp)
|
|||
if (hdr)
|
||||
genlmsg_cancel(msg, hdr);
|
||||
nlmsg_free(msg);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(cfg80211_crit_proto_stopped);
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *netdev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, gfp_t gfp);
|
||||
int status, gfp_t gfp);
|
||||
void nl80211_send_roamed(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *netdev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
|
|
|
@ -244,9 +244,7 @@ void cfg80211_conn_work(struct work_struct *work)
|
|||
if (cfg80211_conn_do_work(wdev)) {
|
||||
__cfg80211_connect_result(
|
||||
wdev->netdev, bssid,
|
||||
NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
false, NULL);
|
||||
NULL, 0, NULL, 0, -1, false, NULL);
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
}
|
||||
|
@ -648,7 +646,7 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
|
|||
void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
const u8 *req_ie, size_t req_ie_len,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, bool wextev,
|
||||
int status, bool wextev,
|
||||
struct cfg80211_bss *bss)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
|
@ -757,7 +755,7 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
|||
void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,
|
||||
struct cfg80211_bss *bss, const u8 *req_ie,
|
||||
size_t req_ie_len, const u8 *resp_ie,
|
||||
size_t resp_ie_len, u16 status, gfp_t gfp)
|
||||
size_t resp_ie_len, int status, gfp_t gfp)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
|
||||
|
|
Загрузка…
Ссылка в новой задаче