aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-09-26 15:19:05 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-26 15:39:24 -0400
commit57219dc7bfc5cae48c8309974054733499a0dc63 (patch)
treed078e6726dee978e3cc14c6a1467dce1fe2f3225 /net/wireless/nl80211.c
parent6ea754eb761d9e7a8ac6fa462b05f9e4cf04fb6c (diff)
parent7a0a260a0f6ff0226c33cf28a5cc26711ab0ae5f (diff)
Merge tag 'master-2014-09-16' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== pull request: wireless-next 2014-09-22 Please pull this batch of updates intended for the 3.18 stream... For the mac80211 bits, Johannes says: "This time, I have some rate minstrel improvements, support for a very small feature from CCX that Steinar reverse-engineered, dynamic ACK timeout support, a number of changes for TDLS, early support for radio resource measurement and many fixes. Also, I'm changing a number of places to clear key memory when it's freed and Intel claims copyright for code they developed." For the bluetooth bits, Johan says: "Here are some more patches intended for 3.18. Most of them are cleanups or fixes for SMP. The only exception is a fix for BR/EDR L2CAP fixed channels which should now work better together with the L2CAP information request procedure." For the iwlwifi bits, Emmanuel says: "I fix here dvm which was broken by my last pull request. Arik continues to work on TDLS and Luca solved a few issues in CT-Kill. Eyal keeps digging into rate scaling code, more to come soon. Besides this, nothing really special here." Beyond that, there are the usual big batches of updates to ath9k, b43, mwifiex, and wil6210 as well as a handful of other bits here and there. Also, rtlwifi gets some btcoexist attention from Larry. Please let me know if there are problems! ==================== Had to adjust the wil6210 code to comply with Joe Perches's recent change in net-next to make the netdev_*() routines return void instead of 'int'. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c233
1 files changed, 211 insertions, 22 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 233c54e45092..cb9f5a44ffad 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2,6 +2,7 @@
2 * This is the new netlink-based wireless configuration interface. 2 * This is the new netlink-based wireless configuration interface.
3 * 3 *
4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
5 * Copyright 2013-2014 Intel Mobile Communications GmbH
5 */ 6 */
6 7
7#include <linux/if.h> 8#include <linux/if.h>
@@ -225,6 +226,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
225 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 }, 226 [NL80211_ATTR_WIPHY_FRAG_THRESHOLD] = { .type = NLA_U32 },
226 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 }, 227 [NL80211_ATTR_WIPHY_RTS_THRESHOLD] = { .type = NLA_U32 },
227 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 }, 228 [NL80211_ATTR_WIPHY_COVERAGE_CLASS] = { .type = NLA_U8 },
229 [NL80211_ATTR_WIPHY_DYN_ACK] = { .type = NLA_FLAG },
228 230
229 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, 231 [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 },
230 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, 232 [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
@@ -388,6 +390,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
388 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, 390 [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
389 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG }, 391 [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
390 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY }, 392 [NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
393 [NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
394 [NL80211_ATTR_TSID] = { .type = NLA_U8 },
395 [NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
396 [NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
397 [NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
391}; 398};
392 399
393/* policy for the key attributes */ 400/* policy for the key attributes */
@@ -1507,6 +1514,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
1507 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH) 1514 if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
1508 CMD(channel_switch, CHANNEL_SWITCH); 1515 CMD(channel_switch, CHANNEL_SWITCH);
1509 CMD(set_qos_map, SET_QOS_MAP); 1516 CMD(set_qos_map, SET_QOS_MAP);
1517 if (rdev->wiphy.flags &
1518 WIPHY_FLAG_SUPPORTS_WMM_ADMISSION)
1519 CMD(add_tx_ts, ADD_TX_TS);
1510 } 1520 }
1511 /* add into the if now */ 1521 /* add into the if now */
1512#undef CMD 1522#undef CMD
@@ -2237,11 +2247,21 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
2237 } 2247 }
2238 2248
2239 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { 2249 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
2250 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
2251 return -EINVAL;
2252
2240 coverage_class = nla_get_u8( 2253 coverage_class = nla_get_u8(
2241 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); 2254 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
2242 changed |= WIPHY_PARAM_COVERAGE_CLASS; 2255 changed |= WIPHY_PARAM_COVERAGE_CLASS;
2243 } 2256 }
2244 2257
2258 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
2259 if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
2260 return -EOPNOTSUPP;
2261
2262 changed |= WIPHY_PARAM_DYN_ACK;
2263 }
2264
2245 if (changed) { 2265 if (changed) {
2246 u8 old_retry_short, old_retry_long; 2266 u8 old_retry_short, old_retry_long;
2247 u32 old_frag_threshold, old_rts_threshold; 2267 u32 old_frag_threshold, old_rts_threshold;
@@ -3326,6 +3346,29 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3326 return PTR_ERR(params.acl); 3346 return PTR_ERR(params.acl);
3327 } 3347 }
3328 3348
3349 if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
3350 params.smps_mode =
3351 nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
3352 switch (params.smps_mode) {
3353 case NL80211_SMPS_OFF:
3354 break;
3355 case NL80211_SMPS_STATIC:
3356 if (!(rdev->wiphy.features &
3357 NL80211_FEATURE_STATIC_SMPS))
3358 return -EINVAL;
3359 break;
3360 case NL80211_SMPS_DYNAMIC:
3361 if (!(rdev->wiphy.features &
3362 NL80211_FEATURE_DYNAMIC_SMPS))
3363 return -EINVAL;
3364 break;
3365 default:
3366 return -EINVAL;
3367 }
3368 } else {
3369 params.smps_mode = NL80211_SMPS_OFF;
3370 }
3371
3329 wdev_lock(wdev); 3372 wdev_lock(wdev);
3330 err = rdev_start_ap(rdev, dev, &params); 3373 err = rdev_start_ap(rdev, dev, &params);
3331 if (!err) { 3374 if (!err) {
@@ -6583,6 +6626,14 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
6583 sizeof(req.vht_capa)); 6626 sizeof(req.vht_capa));
6584 } 6627 }
6585 6628
6629 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
6630 if (!(rdev->wiphy.features &
6631 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
6632 !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
6633 return -EINVAL;
6634 req.flags |= ASSOC_REQ_USE_RRM;
6635 }
6636
6586 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1); 6637 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
6587 if (!err) { 6638 if (!err) {
6588 wdev_lock(dev->ieee80211_ptr); 6639 wdev_lock(dev->ieee80211_ptr);
@@ -6845,7 +6896,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
6845 6896
6846 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 6897 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
6847 if (err) 6898 if (err)
6848 kfree(connkeys); 6899 kzfree(connkeys);
6849 return err; 6900 return err;
6850} 6901}
6851 6902
@@ -7217,7 +7268,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
7217 7268
7218 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) { 7269 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
7219 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) { 7270 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
7220 kfree(connkeys); 7271 kzfree(connkeys);
7221 return -EINVAL; 7272 return -EINVAL;
7222 } 7273 }
7223 memcpy(&connect.ht_capa, 7274 memcpy(&connect.ht_capa,
@@ -7235,7 +7286,7 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
7235 7286
7236 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) { 7287 if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) {
7237 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) { 7288 if (!info->attrs[NL80211_ATTR_VHT_CAPABILITY_MASK]) {
7238 kfree(connkeys); 7289 kzfree(connkeys);
7239 return -EINVAL; 7290 return -EINVAL;
7240 } 7291 }
7241 memcpy(&connect.vht_capa, 7292 memcpy(&connect.vht_capa,
@@ -7243,11 +7294,19 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
7243 sizeof(connect.vht_capa)); 7294 sizeof(connect.vht_capa));
7244 } 7295 }
7245 7296
7297 if (nla_get_flag(info->attrs[NL80211_ATTR_USE_RRM])) {
7298 if (!(rdev->wiphy.features &
7299 NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES) ||
7300 !(rdev->wiphy.features & NL80211_FEATURE_QUIET))
7301 return -EINVAL;
7302 connect.flags |= ASSOC_REQ_USE_RRM;
7303 }
7304
7246 wdev_lock(dev->ieee80211_ptr); 7305 wdev_lock(dev->ieee80211_ptr);
7247 err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL); 7306 err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);
7248 wdev_unlock(dev->ieee80211_ptr); 7307 wdev_unlock(dev->ieee80211_ptr);
7249 if (err) 7308 if (err)
7250 kfree(connkeys); 7309 kzfree(connkeys);
7251 return err; 7310 return err;
7252} 7311}
7253 7312
@@ -8933,13 +8992,9 @@ static int nl80211_set_rekey_data(struct sk_buff *skb, struct genl_info *info)
8933 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN) 8992 if (nla_len(tb[NL80211_REKEY_DATA_KCK]) != NL80211_KCK_LEN)
8934 return -ERANGE; 8993 return -ERANGE;
8935 8994
8936 memcpy(rekey_data.kek, nla_data(tb[NL80211_REKEY_DATA_KEK]), 8995 rekey_data.kek = nla_data(tb[NL80211_REKEY_DATA_KEK]);
8937 NL80211_KEK_LEN); 8996 rekey_data.kck = nla_data(tb[NL80211_REKEY_DATA_KCK]);
8938 memcpy(rekey_data.kck, nla_data(tb[NL80211_REKEY_DATA_KCK]), 8997 rekey_data.replay_ctr = nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]);
8939 NL80211_KCK_LEN);
8940 memcpy(rekey_data.replay_ctr,
8941 nla_data(tb[NL80211_REKEY_DATA_REPLAY_CTR]),
8942 NL80211_REPLAY_CTR_LEN);
8943 8998
8944 wdev_lock(wdev); 8999 wdev_lock(wdev);
8945 if (!wdev->current_bss) { 9000 if (!wdev->current_bss) {
@@ -9371,6 +9426,93 @@ static int nl80211_set_qos_map(struct sk_buff *skb,
9371 return ret; 9426 return ret;
9372} 9427}
9373 9428
9429static int nl80211_add_tx_ts(struct sk_buff *skb, struct genl_info *info)
9430{
9431 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9432 struct net_device *dev = info->user_ptr[1];
9433 struct wireless_dev *wdev = dev->ieee80211_ptr;
9434 const u8 *peer;
9435 u8 tsid, up;
9436 u16 admitted_time = 0;
9437 int err;
9438
9439 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
9440 return -EOPNOTSUPP;
9441
9442 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
9443 !info->attrs[NL80211_ATTR_USER_PRIO])
9444 return -EINVAL;
9445
9446 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
9447 if (tsid >= IEEE80211_NUM_TIDS)
9448 return -EINVAL;
9449
9450 up = nla_get_u8(info->attrs[NL80211_ATTR_USER_PRIO]);
9451 if (up >= IEEE80211_NUM_UPS)
9452 return -EINVAL;
9453
9454 /* WMM uses TIDs 0-7 even for TSPEC */
9455 if (tsid < IEEE80211_FIRST_TSPEC_TSID) {
9456 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
9457 return -EINVAL;
9458 } else {
9459 /* TODO: handle 802.11 TSPEC/admission control
9460 * need more attributes for that (e.g. BA session requirement)
9461 */
9462 return -EINVAL;
9463 }
9464
9465 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
9466
9467 if (info->attrs[NL80211_ATTR_ADMITTED_TIME]) {
9468 admitted_time =
9469 nla_get_u16(info->attrs[NL80211_ATTR_ADMITTED_TIME]);
9470 if (!admitted_time)
9471 return -EINVAL;
9472 }
9473
9474 wdev_lock(wdev);
9475 switch (wdev->iftype) {
9476 case NL80211_IFTYPE_STATION:
9477 case NL80211_IFTYPE_P2P_CLIENT:
9478 if (wdev->current_bss)
9479 break;
9480 err = -ENOTCONN;
9481 goto out;
9482 default:
9483 err = -EOPNOTSUPP;
9484 goto out;
9485 }
9486
9487 err = rdev_add_tx_ts(rdev, dev, tsid, peer, up, admitted_time);
9488
9489 out:
9490 wdev_unlock(wdev);
9491 return err;
9492}
9493
9494static int nl80211_del_tx_ts(struct sk_buff *skb, struct genl_info *info)
9495{
9496 struct cfg80211_registered_device *rdev = info->user_ptr[0];
9497 struct net_device *dev = info->user_ptr[1];
9498 struct wireless_dev *wdev = dev->ieee80211_ptr;
9499 const u8 *peer;
9500 u8 tsid;
9501 int err;
9502
9503 if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC])
9504 return -EINVAL;
9505
9506 tsid = nla_get_u8(info->attrs[NL80211_ATTR_TSID]);
9507 peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
9508
9509 wdev_lock(wdev);
9510 err = rdev_del_tx_ts(rdev, dev, tsid, peer);
9511 wdev_unlock(wdev);
9512
9513 return err;
9514}
9515
9374#define NL80211_FLAG_NEED_WIPHY 0x01 9516#define NL80211_FLAG_NEED_WIPHY 0x01
9375#define NL80211_FLAG_NEED_NETDEV 0x02 9517#define NL80211_FLAG_NEED_NETDEV 0x02
9376#define NL80211_FLAG_NEED_RTNL 0x04 9518#define NL80211_FLAG_NEED_RTNL 0x04
@@ -9381,6 +9523,7 @@ static int nl80211_set_qos_map(struct sk_buff *skb,
9381/* If a netdev is associated, it must be UP, P2P must be started */ 9523/* If a netdev is associated, it must be UP, P2P must be started */
9382#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\ 9524#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
9383 NL80211_FLAG_CHECK_NETDEV_UP) 9525 NL80211_FLAG_CHECK_NETDEV_UP)
9526#define NL80211_FLAG_CLEAR_SKB 0x20
9384 9527
9385static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 9528static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
9386 struct genl_info *info) 9529 struct genl_info *info)
@@ -9464,8 +9607,20 @@ static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
9464 dev_put(info->user_ptr[1]); 9607 dev_put(info->user_ptr[1]);
9465 } 9608 }
9466 } 9609 }
9610
9467 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) 9611 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL)
9468 rtnl_unlock(); 9612 rtnl_unlock();
9613
9614 /* If needed, clear the netlink message payload from the SKB
9615 * as it might contain key data that shouldn't stick around on
9616 * the heap after the SKB is freed. The netlink message header
9617 * is still needed for further processing, so leave it intact.
9618 */
9619 if (ops->internal_flags & NL80211_FLAG_CLEAR_SKB) {
9620 struct nlmsghdr *nlh = nlmsg_hdr(skb);
9621
9622 memset(nlmsg_data(nlh), 0, nlmsg_len(nlh));
9623 }
9469} 9624}
9470 9625
9471static const struct genl_ops nl80211_ops[] = { 9626static const struct genl_ops nl80211_ops[] = {
@@ -9533,7 +9688,8 @@ static const struct genl_ops nl80211_ops[] = {
9533 .policy = nl80211_policy, 9688 .policy = nl80211_policy,
9534 .flags = GENL_ADMIN_PERM, 9689 .flags = GENL_ADMIN_PERM,
9535 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 9690 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9536 NL80211_FLAG_NEED_RTNL, 9691 NL80211_FLAG_NEED_RTNL |
9692 NL80211_FLAG_CLEAR_SKB,
9537 }, 9693 },
9538 { 9694 {
9539 .cmd = NL80211_CMD_NEW_KEY, 9695 .cmd = NL80211_CMD_NEW_KEY,
@@ -9541,7 +9697,8 @@ static const struct genl_ops nl80211_ops[] = {
9541 .policy = nl80211_policy, 9697 .policy = nl80211_policy,
9542 .flags = GENL_ADMIN_PERM, 9698 .flags = GENL_ADMIN_PERM,
9543 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 9699 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9544 NL80211_FLAG_NEED_RTNL, 9700 NL80211_FLAG_NEED_RTNL |
9701 NL80211_FLAG_CLEAR_SKB,
9545 }, 9702 },
9546 { 9703 {
9547 .cmd = NL80211_CMD_DEL_KEY, 9704 .cmd = NL80211_CMD_DEL_KEY,
@@ -9719,7 +9876,8 @@ static const struct genl_ops nl80211_ops[] = {
9719 .policy = nl80211_policy, 9876 .policy = nl80211_policy,
9720 .flags = GENL_ADMIN_PERM, 9877 .flags = GENL_ADMIN_PERM,
9721 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 9878 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9722 NL80211_FLAG_NEED_RTNL, 9879 NL80211_FLAG_NEED_RTNL |
9880 NL80211_FLAG_CLEAR_SKB,
9723 }, 9881 },
9724 { 9882 {
9725 .cmd = NL80211_CMD_ASSOCIATE, 9883 .cmd = NL80211_CMD_ASSOCIATE,
@@ -9953,7 +10111,8 @@ static const struct genl_ops nl80211_ops[] = {
9953 .policy = nl80211_policy, 10111 .policy = nl80211_policy,
9954 .flags = GENL_ADMIN_PERM, 10112 .flags = GENL_ADMIN_PERM,
9955 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 10113 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
9956 NL80211_FLAG_NEED_RTNL, 10114 NL80211_FLAG_NEED_RTNL |
10115 NL80211_FLAG_CLEAR_SKB,
9957 }, 10116 },
9958 { 10117 {
9959 .cmd = NL80211_CMD_TDLS_MGMT, 10118 .cmd = NL80211_CMD_TDLS_MGMT,
@@ -10111,6 +10270,22 @@ static const struct genl_ops nl80211_ops[] = {
10111 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 10270 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10112 NL80211_FLAG_NEED_RTNL, 10271 NL80211_FLAG_NEED_RTNL,
10113 }, 10272 },
10273 {
10274 .cmd = NL80211_CMD_ADD_TX_TS,
10275 .doit = nl80211_add_tx_ts,
10276 .policy = nl80211_policy,
10277 .flags = GENL_ADMIN_PERM,
10278 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10279 NL80211_FLAG_NEED_RTNL,
10280 },
10281 {
10282 .cmd = NL80211_CMD_DEL_TX_TS,
10283 .doit = nl80211_del_tx_ts,
10284 .policy = nl80211_policy,
10285 .flags = GENL_ADMIN_PERM,
10286 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
10287 NL80211_FLAG_NEED_RTNL,
10288 },
10114}; 10289};
10115 10290
10116/* notification functions */ 10291/* notification functions */
@@ -10379,7 +10554,8 @@ nla_put_failure:
10379static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev, 10554static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
10380 struct net_device *netdev, 10555 struct net_device *netdev,
10381 const u8 *buf, size_t len, 10556 const u8 *buf, size_t len,
10382 enum nl80211_commands cmd, gfp_t gfp) 10557 enum nl80211_commands cmd, gfp_t gfp,
10558 int uapsd_queues)
10383{ 10559{
10384 struct sk_buff *msg; 10560 struct sk_buff *msg;
10385 void *hdr; 10561 void *hdr;
@@ -10399,6 +10575,19 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
10399 nla_put(msg, NL80211_ATTR_FRAME, len, buf)) 10575 nla_put(msg, NL80211_ATTR_FRAME, len, buf))
10400 goto nla_put_failure; 10576 goto nla_put_failure;
10401 10577
10578 if (uapsd_queues >= 0) {
10579 struct nlattr *nla_wmm =
10580 nla_nest_start(msg, NL80211_ATTR_STA_WME);
10581 if (!nla_wmm)
10582 goto nla_put_failure;
10583
10584 if (nla_put_u8(msg, NL80211_STA_WME_UAPSD_QUEUES,
10585 uapsd_queues))
10586 goto nla_put_failure;
10587
10588 nla_nest_end(msg, nla_wmm);
10589 }
10590
10402 genlmsg_end(msg, hdr); 10591 genlmsg_end(msg, hdr);
10403 10592
10404 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, 10593 genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -10415,15 +10604,15 @@ void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev,
10415 size_t len, gfp_t gfp) 10604 size_t len, gfp_t gfp)
10416{ 10605{
10417 nl80211_send_mlme_event(rdev, netdev, buf, len, 10606 nl80211_send_mlme_event(rdev, netdev, buf, len,
10418 NL80211_CMD_AUTHENTICATE, gfp); 10607 NL80211_CMD_AUTHENTICATE, gfp, -1);
10419} 10608}
10420 10609
10421void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev, 10610void nl80211_send_rx_assoc(struct cfg80211_registered_device *rdev,
10422 struct net_device *netdev, const u8 *buf, 10611 struct net_device *netdev, const u8 *buf,
10423 size_t len, gfp_t gfp) 10612 size_t len, gfp_t gfp, int uapsd_queues)
10424{ 10613{
10425 nl80211_send_mlme_event(rdev, netdev, buf, len, 10614 nl80211_send_mlme_event(rdev, netdev, buf, len,
10426 NL80211_CMD_ASSOCIATE, gfp); 10615 NL80211_CMD_ASSOCIATE, gfp, uapsd_queues);
10427} 10616}
10428 10617
10429void nl80211_send_deauth(struct cfg80211_registered_device *rdev, 10618void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
@@ -10431,7 +10620,7 @@ void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
10431 size_t len, gfp_t gfp) 10620 size_t len, gfp_t gfp)
10432{ 10621{
10433 nl80211_send_mlme_event(rdev, netdev, buf, len, 10622 nl80211_send_mlme_event(rdev, netdev, buf, len,
10434 NL80211_CMD_DEAUTHENTICATE, gfp); 10623 NL80211_CMD_DEAUTHENTICATE, gfp, -1);
10435} 10624}
10436 10625
10437void nl80211_send_disassoc(struct cfg80211_registered_device *rdev, 10626void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
@@ -10439,7 +10628,7 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
10439 size_t len, gfp_t gfp) 10628 size_t len, gfp_t gfp)
10440{ 10629{
10441 nl80211_send_mlme_event(rdev, netdev, buf, len, 10630 nl80211_send_mlme_event(rdev, netdev, buf, len,
10442 NL80211_CMD_DISASSOCIATE, gfp); 10631 NL80211_CMD_DISASSOCIATE, gfp, -1);
10443} 10632}
10444 10633
10445void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf, 10634void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
@@ -10460,7 +10649,7 @@ void cfg80211_rx_unprot_mlme_mgmt(struct net_device *dev, const u8 *buf,
10460 cmd = NL80211_CMD_UNPROT_DISASSOCIATE; 10649 cmd = NL80211_CMD_UNPROT_DISASSOCIATE;
10461 10650
10462 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len); 10651 trace_cfg80211_rx_unprot_mlme_mgmt(dev, buf, len);
10463 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC); 10652 nl80211_send_mlme_event(rdev, dev, buf, len, cmd, GFP_ATOMIC, -1);
10464} 10653}
10465EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt); 10654EXPORT_SYMBOL(cfg80211_rx_unprot_mlme_mgmt);
10466 10655