diff options
author | Ron Rindjunsky <ron.rindjunsky@intel.com> | 2007-11-26 09:14:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:55:33 -0500 |
commit | d3c990fb26b78f60614885d9ecaf7b7686b7b098 (patch) | |
tree | 4948049e6b1bd1ee0392173380e8444e69baa8c5 | |
parent | fd4c7f2fce1737105208c564e1458c885918982d (diff) |
mac80211: adding 802.11n configuration flows
This patch configures the 802.11n mode of operation
internally in ieee80211_conf structure and in the low-level
driver as well (through op conf_ht).
It does not include AP configuration flows.
Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/mac80211.h | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211.c | 51 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 32 |
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 | */ |
1045 | struct ieee80211_ops { | 1047 | struct 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 | */ | ||
573 | int 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 | |||
566 | void ieee80211_erp_info_change_notify(struct net_device *dev, u8 changes) | 617 | void 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); | |||
708 | void ieee80211_if_setup(struct net_device *dev); | 708 | void ieee80211_if_setup(struct net_device *dev); |
709 | struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local, | 709 | struct ieee80211_rate *ieee80211_get_rate(struct ieee80211_local *local, |
710 | int phymode, int hwrate); | 710 | int phymode, int hwrate); |
711 | int 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 */ |
713 | extern const struct iw_handler_def ieee80211_iw_handler_def; | 716 | extern 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); |