aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h3
-rw-r--r--net/mac80211/ieee80211.c51
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/ieee80211_sta.c32
4 files changed, 89 insertions, 0 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 79e96455438a..0d67b331ee72 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1041,6 +1041,8 @@ enum ieee80211_erp_change_flags {
1041 * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. 1041 * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
1042 * This is needed only for IBSS mode and the result of this function is 1042 * This is needed only for IBSS mode and the result of this function is
1043 * used to determine whether to reply to Probe Requests. 1043 * used to determine whether to reply to Probe Requests.
1044 *
1045 * @conf_ht: Configures low level driver with 802.11n HT data. Must be atomic.
1044 */ 1046 */
1045struct ieee80211_ops { 1047struct ieee80211_ops {
1046 int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb, 1048 int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
@@ -1086,6 +1088,7 @@ struct ieee80211_ops {
1086 struct sk_buff *skb, 1088 struct sk_buff *skb,
1087 struct ieee80211_tx_control *control); 1089 struct ieee80211_tx_control *control);
1088 int (*tx_last_beacon)(struct ieee80211_hw *hw); 1090 int (*tx_last_beacon)(struct ieee80211_hw *hw);
1091 int (*conf_ht)(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
1089}; 1092};
1090 1093
1091/** 1094/**
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c
index 4f8b6653e364..d6a97a68a62e 100644
--- a/net/mac80211/ieee80211.c
+++ b/net/mac80211/ieee80211.c
@@ -34,6 +34,8 @@
34#include "debugfs.h" 34#include "debugfs.h"
35#include "debugfs_netdev.h" 35#include "debugfs_netdev.h"
36 36
37#define SUPP_MCS_SET_LEN 16
38
37/* 39/*
38 * For seeing transmitted packets on monitor interfaces 40 * For seeing transmitted packets on monitor interfaces
39 * we have a radiotap header too. 41 * we have a radiotap header too.
@@ -563,6 +565,55 @@ int ieee80211_hw_config(struct ieee80211_local *local)
563 return ret; 565 return ret;
564} 566}
565 567
568/**
569 * ieee80211_hw_config_ht should be used only after legacy configuration
570 * has been determined, as ht configuration depends upon the hardware's
571 * HT abilities for a _specific_ band.
572 */
573int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
574 struct ieee80211_ht_info *req_ht_cap,
575 struct ieee80211_ht_bss_info *req_bss_cap)
576{
577 struct ieee80211_conf *conf = &local->hw.conf;
578 struct ieee80211_hw_mode *mode = conf->mode;
579 int i;
580
581 /* HT is not supported */
582 if (!mode->ht_info.ht_supported) {
583 conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
584 return -EOPNOTSUPP;
585 }
586
587 /* disable HT */
588 if (!enable_ht) {
589 conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE;
590 } else {
591 conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE;
592 conf->ht_conf.cap = req_ht_cap->cap & mode->ht_info.cap;
593 conf->ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS);
594 conf->ht_conf.cap |=
595 mode->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS;
596 conf->ht_bss_conf.primary_channel =
597 req_bss_cap->primary_channel;
598 conf->ht_bss_conf.bss_cap = req_bss_cap->bss_cap;
599 conf->ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode;
600 for (i = 0; i < SUPP_MCS_SET_LEN; i++)
601 conf->ht_conf.supp_mcs_set[i] =
602 mode->ht_info.supp_mcs_set[i] &
603 req_ht_cap->supp_mcs_set[i];
604
605 /* In STA mode, this gives us indication
606 * to the AP's mode of operation */
607 conf->ht_conf.ht_supported = 1;
608 conf->ht_conf.ampdu_factor = req_ht_cap->ampdu_factor;
609 conf->ht_conf.ampdu_density = req_ht_cap->ampdu_density;
610 }
611
612 local->ops->conf_ht(local_to_hw(local), &local->hw.conf);
613
614 return 0;
615}
616
566void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes) 617void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes)
567{ 618{
568 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 619 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 66b6cf3a62ac..2dcb9425fe8f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -708,6 +708,9 @@ int ieee80211_if_update_wds(struct net_device *dev, u8 *remote_addr);
708void ieee80211_if_setup(struct net_device *dev); 708void ieee80211_if_setup(struct net_device *dev);
709struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local, 709struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local,
710 int phymode, int hwrate); 710 int phymode, int hwrate);
711int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht,
712 struct ieee80211_ht_info *req_ht_cap,
713 struct ieee80211_ht_bss_info *req_bss_cap);
711 714
712/* ieee80211_ioctl.c */ 715/* ieee80211_ioctl.c */
713extern const struct iw_handler_def ieee80211_iw_handler_def; 716extern const struct iw_handler_def ieee80211_iw_handler_def;
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 1d553d78b227..87830c04a1ca 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -1437,6 +1437,19 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1437 } 1437 }
1438 sta->supp_rates = rates; 1438 sta->supp_rates = rates;
1439 1439
1440 if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
1441 local->ops->conf_ht) {
1442 struct ieee80211_ht_bss_info bss_info;
1443
1444 ieee80211_ht_cap_ie_to_ht_info(
1445 (struct ieee80211_ht_cap *)
1446 elems.ht_cap_elem, &sta->ht_info);
1447 ieee80211_ht_addt_info_ie_to_ht_bss_info(
1448 (struct ieee80211_ht_addt_info *)
1449 elems.ht_info_elem, &bss_info);
1450 ieee80211_hw_config_ht(local, 1, &sta->ht_info, &bss_info);
1451 }
1452
1440 rate_control_rate_init(sta, local); 1453 rate_control_rate_init(sta, local);
1441 1454
1442 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { 1455 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
@@ -1859,6 +1872,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1859 struct ieee80211_if_sta *ifsta; 1872 struct ieee80211_if_sta *ifsta;
1860 size_t baselen; 1873 size_t baselen;
1861 struct ieee802_11_elems elems; 1874 struct ieee802_11_elems elems;
1875 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1876 struct ieee80211_conf *conf = &local->hw.conf;
1862 1877
1863 ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1); 1878 ieee80211_rx_bss_info(dev, mgmt, len, rx_status, 1);
1864 1879
@@ -1881,6 +1896,23 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1881 if (elems.erp_info && elems.erp_info_len >= 1) 1896 if (elems.erp_info && elems.erp_info_len >= 1)
1882 ieee80211_handle_erp_ie(dev, elems.erp_info[0]); 1897 ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
1883 1898
1899 if (elems.ht_cap_elem && elems.ht_info_elem &&
1900 elems.wmm_param && local->ops->conf_ht &&
1901 conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
1902 struct ieee80211_ht_bss_info bss_info;
1903
1904 ieee80211_ht_addt_info_ie_to_ht_bss_info(
1905 (struct ieee80211_ht_addt_info *)
1906 elems.ht_info_elem, &bss_info);
1907 /* check if AP changed bss inforamation */
1908 if ((conf->ht_bss_conf.primary_channel !=
1909 bss_info.primary_channel) ||
1910 (conf->ht_bss_conf.bss_cap != bss_info.bss_cap) ||
1911 (conf->ht_bss_conf.bss_op_mode != bss_info.bss_op_mode))
1912 ieee80211_hw_config_ht(local, 1, &conf->ht_conf,
1913 &bss_info);
1914 }
1915
1884 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { 1916 if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
1885 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, 1917 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
1886 elems.wmm_param_len); 1918 elems.wmm_param_len);