aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h8
-rw-r--r--include/uapi/linux/nl80211.h10
-rw-r--r--net/wireless/nl80211.c36
3 files changed, 54 insertions, 0 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a229046d86d4..fa2612952c19 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -626,12 +626,14 @@ enum plink_actions {
626/** 626/**
627 * enum station_parameters_apply_mask - station parameter values to apply 627 * enum station_parameters_apply_mask - station parameter values to apply
628 * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) 628 * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
629 * @STATION_PARAM_APPLY_CAPABILITY: apply new capability
629 * 630 *
630 * Not all station parameters have in-band "no change" signalling, 631 * Not all station parameters have in-band "no change" signalling,
631 * for those that don't these flags will are used. 632 * for those that don't these flags will are used.
632 */ 633 */
633enum station_parameters_apply_mask { 634enum station_parameters_apply_mask {
634 STATION_PARAM_APPLY_UAPSD = BIT(0), 635 STATION_PARAM_APPLY_UAPSD = BIT(0),
636 STATION_PARAM_APPLY_CAPABILITY = BIT(1),
635}; 637};
636 638
637/** 639/**
@@ -662,6 +664,9 @@ enum station_parameters_apply_mask {
662 * see &enum station_parameters_apply_mask 664 * see &enum station_parameters_apply_mask
663 * @local_pm: local link-specific mesh power save mode (no change when set 665 * @local_pm: local link-specific mesh power save mode (no change when set
664 * to unknown) 666 * to unknown)
667 * @capability: station capability
668 * @ext_capab: extended capabilities of the station
669 * @ext_capab_len: number of extended capabilities
665 */ 670 */
666struct station_parameters { 671struct station_parameters {
667 u8 *supported_rates; 672 u8 *supported_rates;
@@ -678,6 +683,9 @@ struct station_parameters {
678 u8 uapsd_queues; 683 u8 uapsd_queues;
679 u8 max_sp; 684 u8 max_sp;
680 enum nl80211_mesh_power_mode local_pm; 685 enum nl80211_mesh_power_mode local_pm;
686 u16 capability;
687 u8 *ext_capab;
688 u8 ext_capab_len;
681}; 689};
682 690
683/** 691/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1fd6e5611896..f7c35ca01efc 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1361,6 +1361,13 @@ enum nl80211_commands {
1361 * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver 1361 * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver
1362 * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields. 1362 * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields.
1363 * 1363 *
1364 * @NL80211_ATTR_STA_CAPABILITY: Station capabilities (u16) are advertised to
1365 * the driver, e.g., to enable TDLS power save (PU-APSD).
1366 *
1367 * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are
1368 * advertised to the driver, e.g., to enable TDLS off channel operations
1369 * and PU-APSD.
1370 *
1364 * @NL80211_ATTR_MAX: highest attribute number currently defined 1371 * @NL80211_ATTR_MAX: highest attribute number currently defined
1365 * @__NL80211_ATTR_AFTER_LAST: internal use 1372 * @__NL80211_ATTR_AFTER_LAST: internal use
1366 */ 1373 */
@@ -1644,6 +1651,9 @@ enum nl80211_attrs {
1644 NL80211_ATTR_EXT_CAPA, 1651 NL80211_ATTR_EXT_CAPA,
1645 NL80211_ATTR_EXT_CAPA_MASK, 1652 NL80211_ATTR_EXT_CAPA_MASK,
1646 1653
1654 NL80211_ATTR_STA_CAPABILITY,
1655 NL80211_ATTR_STA_EXT_CAPABILITY,
1656
1647 /* add attributes here, update the policy in nl80211.c */ 1657 /* add attributes here, update the policy in nl80211.c */
1648 1658
1649 __NL80211_ATTR_AFTER_LAST, 1659 __NL80211_ATTR_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1237431c3efa..be9f2b5a403f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -368,6 +368,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
368 [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, 368 [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
369 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, 369 [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 },
370 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, 370 [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED },
371 [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
372 [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
371}; 373};
372 374
373/* policy for the key attributes */ 375/* policy for the key attributes */
@@ -3435,6 +3437,19 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3435 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); 3437 nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
3436 } 3438 }
3437 3439
3440 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
3441 params.capability =
3442 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
3443 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
3444 }
3445
3446 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
3447 params.ext_capab =
3448 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
3449 params.ext_capab_len =
3450 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
3451 }
3452
3438 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL] || 3453 if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL] ||
3439 info->attrs[NL80211_ATTR_HT_CAPABILITY]) 3454 info->attrs[NL80211_ATTR_HT_CAPABILITY])
3440 return -EINVAL; 3455 return -EINVAL;
@@ -3505,6 +3520,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3505 /* reject other things that can't change */ 3520 /* reject other things that can't change */
3506 if (params.supported_rates) 3521 if (params.supported_rates)
3507 return -EINVAL; 3522 return -EINVAL;
3523 if (info->attrs[NL80211_ATTR_STA_CAPABILITY])
3524 return -EINVAL;
3525 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
3526 return -EINVAL;
3508 3527
3509 /* must be last in here for error handling */ 3528 /* must be last in here for error handling */
3510 params.vlan = get_vlan(info, rdev); 3529 params.vlan = get_vlan(info, rdev);
@@ -3537,6 +3556,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
3537 return -EINVAL; 3556 return -EINVAL;
3538 if (params.supported_rates) 3557 if (params.supported_rates)
3539 return -EINVAL; 3558 return -EINVAL;
3559 if (info->attrs[NL80211_ATTR_STA_CAPABILITY])
3560 return -EINVAL;
3561 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY])
3562 return -EINVAL;
3540 /* 3563 /*
3541 * No special handling for TDLS here -- the userspace 3564 * No special handling for TDLS here -- the userspace
3542 * mesh code doesn't have this bug. 3565 * mesh code doesn't have this bug.
@@ -3601,6 +3624,19 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
3601 if (!params.aid || params.aid > IEEE80211_MAX_AID) 3624 if (!params.aid || params.aid > IEEE80211_MAX_AID)
3602 return -EINVAL; 3625 return -EINVAL;
3603 3626
3627 if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
3628 params.capability =
3629 nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
3630 params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY;
3631 }
3632
3633 if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) {
3634 params.ext_capab =
3635 nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
3636 params.ext_capab_len =
3637 nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]);
3638 }
3639
3604 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) 3640 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
3605 params.ht_capa = 3641 params.ht_capa =
3606 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); 3642 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);