aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2011-11-18 14:31:59 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-21 16:22:06 -0500
commit7e7c8926b2f4e3453b8aeb39cd814d2af3fec24f (patch)
treee22df42bf84d6ea3cb67ae0e332d7d7d10cca4b4 /net
parentdd76986b0e398978ca32dd60c1b7dc50ab4e9ae1 (diff)
wireless: Support ht-capabilities over-rides.
This allows users to disable features such as HT, HT40, and to modify the MCS, AMPDU, and AMSDU settings for drivers that support it. The MCS, AMPDU, and AMSDU features that may be disabled are are reported in the phy-info netlink message as a mask. Attemping to disable features that are not supported will take no affect, but will not return errors. This is to aid backwards compatibility in user-space apps that may not be clever enough to deal with parsing the the capabilities mask. This patch only enables the infrastructure. An additional patch will enable the feature in mac80211. Signed-off-by: Ben Greear <greearb@candelatech.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/core.h10
-rw-r--r--net/wireless/mlme.c37
-rw-r--r--net/wireless/nl80211.c44
-rw-r--r--net/wireless/sme.c7
4 files changed, 91 insertions, 7 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 1c7d4df5418c..fb08c28fc90a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -341,13 +341,17 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
341 const u8 *bssid, const u8 *prev_bssid, 341 const u8 *bssid, const u8 *prev_bssid,
342 const u8 *ssid, int ssid_len, 342 const u8 *ssid, int ssid_len,
343 const u8 *ie, int ie_len, bool use_mfp, 343 const u8 *ie, int ie_len, bool use_mfp,
344 struct cfg80211_crypto_settings *crypt); 344 struct cfg80211_crypto_settings *crypt,
345 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
346 struct ieee80211_ht_cap *ht_capa_mask);
345int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 347int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
346 struct net_device *dev, struct ieee80211_channel *chan, 348 struct net_device *dev, struct ieee80211_channel *chan,
347 const u8 *bssid, const u8 *prev_bssid, 349 const u8 *bssid, const u8 *prev_bssid,
348 const u8 *ssid, int ssid_len, 350 const u8 *ssid, int ssid_len,
349 const u8 *ie, int ie_len, bool use_mfp, 351 const u8 *ie, int ie_len, bool use_mfp,
350 struct cfg80211_crypto_settings *crypt); 352 struct cfg80211_crypto_settings *crypt,
353 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
354 struct ieee80211_ht_cap *ht_capa_mask);
351int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, 355int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
352 struct net_device *dev, const u8 *bssid, 356 struct net_device *dev, const u8 *bssid,
353 const u8 *ie, int ie_len, u16 reason, 357 const u8 *ie, int ie_len, u16 reason,
@@ -379,6 +383,8 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
379 bool channel_type_valid, unsigned int wait, 383 bool channel_type_valid, unsigned int wait,
380 const u8 *buf, size_t len, bool no_cck, 384 const u8 *buf, size_t len, bool no_cck,
381 bool dont_wait_for_ack, u64 *cookie); 385 bool dont_wait_for_ack, u64 *cookie);
386void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
387 const struct ieee80211_ht_cap *ht_capa_mask);
382 388
383/* SME */ 389/* SME */
384int __cfg80211_connect(struct cfg80211_registered_device *rdev, 390int __cfg80211_connect(struct cfg80211_registered_device *rdev,
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 6c1bafd508c8..438dfc105b4a 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -501,13 +501,32 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
501 return err; 501 return err;
502} 502}
503 503
504/* Do a logical ht_capa &= ht_capa_mask. */
505void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
506 const struct ieee80211_ht_cap *ht_capa_mask)
507{
508 int i;
509 u8 *p1, *p2;
510 if (!ht_capa_mask) {
511 memset(ht_capa, 0, sizeof(*ht_capa));
512 return;
513 }
514
515 p1 = (u8*)(ht_capa);
516 p2 = (u8*)(ht_capa_mask);
517 for (i = 0; i<sizeof(*ht_capa); i++)
518 p1[i] &= p2[i];
519}
520
504int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, 521int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
505 struct net_device *dev, 522 struct net_device *dev,
506 struct ieee80211_channel *chan, 523 struct ieee80211_channel *chan,
507 const u8 *bssid, const u8 *prev_bssid, 524 const u8 *bssid, const u8 *prev_bssid,
508 const u8 *ssid, int ssid_len, 525 const u8 *ssid, int ssid_len,
509 const u8 *ie, int ie_len, bool use_mfp, 526 const u8 *ie, int ie_len, bool use_mfp,
510 struct cfg80211_crypto_settings *crypt) 527 struct cfg80211_crypto_settings *crypt,
528 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
529 struct ieee80211_ht_cap *ht_capa_mask)
511{ 530{
512 struct wireless_dev *wdev = dev->ieee80211_ptr; 531 struct wireless_dev *wdev = dev->ieee80211_ptr;
513 struct cfg80211_assoc_request req; 532 struct cfg80211_assoc_request req;
@@ -537,6 +556,15 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
537 memcpy(&req.crypto, crypt, sizeof(req.crypto)); 556 memcpy(&req.crypto, crypt, sizeof(req.crypto));
538 req.use_mfp = use_mfp; 557 req.use_mfp = use_mfp;
539 req.prev_bssid = prev_bssid; 558 req.prev_bssid = prev_bssid;
559 req.flags = assoc_flags;
560 if (ht_capa)
561 memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa));
562 if (ht_capa_mask)
563 memcpy(&req.ht_capa_mask, ht_capa_mask,
564 sizeof(req.ht_capa_mask));
565 cfg80211_oper_and_ht_capa(&req.ht_capa_mask,
566 rdev->wiphy.ht_capa_mod_mask);
567
540 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, 568 req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
541 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 569 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
542 if (!req.bss) { 570 if (!req.bss) {
@@ -574,14 +602,17 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
574 const u8 *bssid, const u8 *prev_bssid, 602 const u8 *bssid, const u8 *prev_bssid,
575 const u8 *ssid, int ssid_len, 603 const u8 *ssid, int ssid_len,
576 const u8 *ie, int ie_len, bool use_mfp, 604 const u8 *ie, int ie_len, bool use_mfp,
577 struct cfg80211_crypto_settings *crypt) 605 struct cfg80211_crypto_settings *crypt,
606 u32 assoc_flags, struct ieee80211_ht_cap *ht_capa,
607 struct ieee80211_ht_cap *ht_capa_mask)
578{ 608{
579 struct wireless_dev *wdev = dev->ieee80211_ptr; 609 struct wireless_dev *wdev = dev->ieee80211_ptr;
580 int err; 610 int err;
581 611
582 wdev_lock(wdev); 612 wdev_lock(wdev);
583 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, 613 err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
584 ssid, ssid_len, ie, ie_len, use_mfp, crypt); 614 ssid, ssid_len, ie, ie_len, use_mfp, crypt,
615 assoc_flags, ht_capa, ht_capa_mask);
585 wdev_unlock(wdev); 616 wdev_unlock(wdev);
586 617
587 return err; 618 return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 889f06483862..a1cabde7cb5f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -200,6 +200,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
200 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY, 200 [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY,
201 .len = IEEE80211_MAX_DATA_LEN }, 201 .len = IEEE80211_MAX_DATA_LEN },
202 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 }, 202 [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
203 [NL80211_ATTR_DISABLE_HT] = { .type = NLA_FLAG },
204 [NL80211_ATTR_HT_CAPABILITY_MASK] = {
205 .len = NL80211_HT_CAPABILITY_LEN
206 },
203}; 207};
204 208
205/* policy for the key attributes */ 209/* policy for the key attributes */
@@ -1032,6 +1036,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
1032 1036
1033 NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features); 1037 NLA_PUT_U32(msg, NL80211_ATTR_FEATURE_FLAGS, dev->wiphy.features);
1034 1038
1039 if (dev->wiphy.ht_capa_mod_mask)
1040 NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY_MASK,
1041 sizeof(*dev->wiphy.ht_capa_mod_mask),
1042 dev->wiphy.ht_capa_mod_mask);
1043
1035 return genlmsg_end(msg, hdr); 1044 return genlmsg_end(msg, hdr);
1036 1045
1037 nla_put_failure: 1046 nla_put_failure:
@@ -4413,6 +4422,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
4413 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; 4422 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
4414 int err, ssid_len, ie_len = 0; 4423 int err, ssid_len, ie_len = 0;
4415 bool use_mfp = false; 4424 bool use_mfp = false;
4425 u32 flags = 0;
4426 struct ieee80211_ht_cap *ht_capa = NULL;
4427 struct ieee80211_ht_cap *ht_capa_mask = NULL;
4416 4428
4417 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) 4429 if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
4418 return -EINVAL; 4430 return -EINVAL;
@@ -4456,11 +4468,25 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
4456 if (info->attrs[NL80211_ATTR_PREV_BSSID]) 4468 if (info->attrs[NL80211_ATTR_PREV_BSSID])
4457 prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]); 4469 prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
4458 4470
4471 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
4472 flags |= ASSOC_REQ_DISABLE_HT;
4473
4474 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
4475 ht_capa_mask =
4476 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]);
4477
4478 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
4479 if (!ht_capa_mask)
4480 return -EINVAL;
4481 ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);
4482 }
4483
4459 err = nl80211_crypto_settings(rdev, info, &crypto, 1); 4484 err = nl80211_crypto_settings(rdev, info, &crypto, 1);
4460 if (!err) 4485 if (!err)
4461 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid, 4486 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid, prev_bssid,
4462 ssid, ssid_len, ie, ie_len, use_mfp, 4487 ssid, ssid_len, ie, ie_len, use_mfp,
4463 &crypto); 4488 &crypto, flags, ht_capa,
4489 ht_capa_mask);
4464 4490
4465 return err; 4491 return err;
4466} 4492}
@@ -4950,6 +4976,22 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
4950 return PTR_ERR(connkeys); 4976 return PTR_ERR(connkeys);
4951 } 4977 }
4952 4978
4979 if (nla_get_flag(info->attrs[NL80211_ATTR_DISABLE_HT]))
4980 connect.flags |= ASSOC_REQ_DISABLE_HT;
4981
4982 if (info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
4983 memcpy(&connect.ht_capa_mask,
4984 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]),
4985 sizeof(connect.ht_capa_mask));
4986
4987 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
4988 if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
4989 return -EINVAL;
4990 memcpy(&connect.ht_capa,
4991 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
4992 sizeof(connect.ht_capa));
4993 }
4994
4953 err = cfg80211_connect(rdev, dev, &connect, connkeys); 4995 err = cfg80211_connect(rdev, dev, &connect, connkeys);
4954 if (err) 4996 if (err)
4955 kfree(connkeys); 4997 kfree(connkeys);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 6e86d5acf145..ed9d0e6f4a06 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -189,7 +189,9 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
189 prev_bssid, 189 prev_bssid,
190 params->ssid, params->ssid_len, 190 params->ssid, params->ssid_len,
191 params->ie, params->ie_len, 191 params->ie, params->ie_len,
192 false, &params->crypto); 192 false, &params->crypto,
193 params->flags, &params->ht_capa,
194 &params->ht_capa_mask);
193 if (err) 195 if (err)
194 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, 196 __cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid,
195 NULL, 0, 197 NULL, 0,
@@ -773,6 +775,9 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
773 wdev->connect_keys = NULL; 775 wdev->connect_keys = NULL;
774 } 776 }
775 777
778 cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
779 rdev->wiphy.ht_capa_mod_mask);
780
776 if (connkeys && connkeys->def >= 0) { 781 if (connkeys && connkeys->def >= 0) {
777 int idx; 782 int idx;
778 u32 cipher; 783 u32 cipher;