diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211.c | 73 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 33 |
3 files changed, 66 insertions, 46 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index aaa5480..5d30dd4 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -1046,54 +1046,69 @@ int ieee80211_hw_config(struct ieee80211_local *local) } /** - * ieee80211_hw_config_ht should be used only after legacy configuration - * has been determined, as ht configuration depends upon the hardware's - * HT abilities for a _specific_ band. + * ieee80211_handle_ht should be used only after legacy configuration + * has been determined namely band, as ht configuration depends upon + * the hardware's HT abilities for a _specific_ band. */ -int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, +u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, struct ieee80211_ht_info *req_ht_cap, struct ieee80211_ht_bss_info *req_bss_cap) { struct ieee80211_conf *conf = &local->hw.conf; struct ieee80211_supported_band *sband; + struct ieee80211_ht_info ht_conf; + struct ieee80211_ht_bss_info ht_bss_conf; int i; + u32 changed = 0; sband = local->hw.wiphy->bands[conf->channel->band]; /* HT is not supported */ if (!sband->ht_info.ht_supported) { conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; - return -EOPNOTSUPP; + return 0; } - /* disable HT */ - if (!enable_ht) { - conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; - } else { + memset(&ht_conf, 0, sizeof(struct ieee80211_ht_info)); + memset(&ht_bss_conf, 0, sizeof(struct ieee80211_ht_bss_info)); + + if (enable_ht) { + if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) + changed |= BSS_CHANGED_HT; + conf->flags |= IEEE80211_CONF_SUPPORT_HT_MODE; - conf->ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; - conf->ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); - conf->ht_conf.cap |= - sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; - conf->ht_bss_conf.primary_channel = - req_bss_cap->primary_channel; - conf->ht_bss_conf.bss_cap = req_bss_cap->bss_cap; - conf->ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; + ht_conf.ht_supported = 1; + + ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; + ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); + ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; + for (i = 0; i < SUPP_MCS_SET_LEN; i++) - conf->ht_conf.supp_mcs_set[i] = - sband->ht_info.supp_mcs_set[i] & - req_ht_cap->supp_mcs_set[i]; - - /* In STA mode, this gives us indication - * to the AP's mode of operation */ - conf->ht_conf.ht_supported = 1; - conf->ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; - conf->ht_conf.ampdu_density = req_ht_cap->ampdu_density; + ht_conf.supp_mcs_set[i] = + sband->ht_info.supp_mcs_set[i] & + req_ht_cap->supp_mcs_set[i]; + + ht_bss_conf.primary_channel = req_bss_cap->primary_channel; + ht_bss_conf.bss_cap = req_bss_cap->bss_cap; + ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; + + ht_conf.ampdu_factor = req_ht_cap->ampdu_factor; + ht_conf.ampdu_density = req_ht_cap->ampdu_density; + + /* if bss configuration changed store the new one */ + if (memcmp(&conf->ht_conf, &ht_conf, sizeof(ht_conf)) || + memcmp(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf))) { + changed |= BSS_CHANGED_HT; + memcpy(&conf->ht_conf, &ht_conf, sizeof(ht_conf)); + memcpy(&conf->ht_bss_conf, &ht_bss_conf, sizeof(ht_bss_conf)); + } + } else { + if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) + changed |= BSS_CHANGED_HT; + conf->flags &= ~IEEE80211_CONF_SUPPORT_HT_MODE; } - local->ops->conf_ht(local_to_hw(local), &local->hw.conf); - - return 0; + return changed; } void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 0997a0f..377c448 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -865,9 +865,9 @@ int ieee80211_if_config(struct net_device *dev); int ieee80211_if_config_beacon(struct net_device *dev); void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); void ieee80211_if_setup(struct net_device *dev); -int ieee80211_hw_config_ht(struct ieee80211_local *local, int enable_ht, - struct ieee80211_ht_info *req_ht_cap, - struct ieee80211_ht_bss_info *req_bss_cap); +u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, + struct ieee80211_ht_info *req_ht_cap, + struct ieee80211_ht_bss_info *req_bss_cap); /* ieee80211_ioctl.c */ 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 1ee07f0..0e93623 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -493,6 +493,7 @@ static void ieee80211_set_associated(struct net_device *dev, { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_local *local = sdata->local; + struct ieee80211_conf *conf = &local_to_hw(local)->conf; union iwreq_data wrqu; u32 changed = BSS_CHANGED_ASSOC; @@ -505,7 +506,7 @@ static void ieee80211_set_associated(struct net_device *dev, return; bss = ieee80211_rx_bss_get(dev, ifsta->bssid, - local->hw.conf.channel->center_freq, + conf->channel->center_freq, ifsta->ssid, ifsta->ssid_len); if (bss) { if (bss->has_erp_value) @@ -514,6 +515,13 @@ static void ieee80211_set_associated(struct net_device *dev, ieee80211_rx_bss_put(dev, bss); } + if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { + changed |= BSS_CHANGED_HT; + sdata->bss_conf.assoc_ht = 1; + sdata->bss_conf.ht_conf = &conf->ht_conf; + sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; + } + netif_carrier_on(dev); ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); @@ -524,6 +532,11 @@ static void ieee80211_set_associated(struct net_device *dev, ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; netif_carrier_off(dev); ieee80211_reset_erp_info(dev); + + sdata->bss_conf.assoc_ht = 0; + sdata->bss_conf.ht_conf = NULL; + sdata->bss_conf.ht_bss_conf = NULL; + memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); } wrqu.ap_addr.sa_family = ARPHRD_ETHER; @@ -1999,17 +2012,15 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, else sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; - if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && - local->ops->conf_ht) { + if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) { struct ieee80211_ht_bss_info bss_info; - ieee80211_ht_cap_ie_to_ht_info( (struct ieee80211_ht_cap *) elems.ht_cap_elem, &sta->ht_info); ieee80211_ht_addt_info_ie_to_ht_bss_info( (struct ieee80211_ht_addt_info *) elems.ht_info_elem, &bss_info); - ieee80211_hw_config_ht(local, 1, &sta->ht_info, &bss_info); + ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info); } rate_control_rate_init(sta, local); @@ -2760,20 +2771,14 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); if (elems.ht_cap_elem && elems.ht_info_elem && - elems.wmm_param && local->ops->conf_ht && - conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { + elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { struct ieee80211_ht_bss_info bss_info; ieee80211_ht_addt_info_ie_to_ht_bss_info( (struct ieee80211_ht_addt_info *) elems.ht_info_elem, &bss_info); - /* check if AP changed bss inforamation */ - if ((conf->ht_bss_conf.primary_channel != - bss_info.primary_channel) || - (conf->ht_bss_conf.bss_cap != bss_info.bss_cap) || - (conf->ht_bss_conf.bss_op_mode != bss_info.bss_op_mode)) - ieee80211_hw_config_ht(local, 1, &conf->ht_conf, - &bss_info); + changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, + &bss_info); } if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { |