]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/mac80211/mlme.c
mac80211: add might_sleep to hw_config
[linux-2.6-omap-h63xx.git] / net / mac80211 / mlme.c
index 829995e740a78fdccb673586312e2bdbb4124962..39bc9c69893bfc15e8f6b811f32c487218db98c1 100644 (file)
@@ -236,7 +236,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
-       u8 *pos, *ies, *ht_add_ie;
+       u8 *pos, *ies, *ht_ie;
        int i, len, count, rates_len, supp_rates_len;
        u16 capab;
        struct ieee80211_bss *bss;
@@ -393,24 +393,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
 
        /* wmm support is a must to HT */
        if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) &&
-           sband->ht_info.ht_supported &&
-           (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) {
-               struct ieee80211_ht_addt_info *ht_add_info =
-                       (struct ieee80211_ht_addt_info *)ht_add_ie;
-               u16 cap = sband->ht_info.cap;
+           sband->ht_cap.ht_supported &&
+           (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) &&
+           ht_ie[1] >= sizeof(struct ieee80211_ht_info)) {
+               struct ieee80211_ht_info *ht_info =
+                       (struct ieee80211_ht_info *)(ht_ie + 2);
+               u16 cap = sband->ht_cap.cap;
                __le16 tmp;
                u32 flags = local->hw.conf.channel->flags;
 
-               switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) {
-               case IEEE80211_HT_IE_CHA_SEC_ABOVE:
+               switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
                        if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) {
-                               cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
+                               cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
                                cap &= ~IEEE80211_HT_CAP_SGI_40;
                        }
                        break;
-               case IEEE80211_HT_IE_CHA_SEC_BELOW:
+               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
                        if (flags & IEEE80211_CHAN_NO_FAT_BELOW) {
-                               cap &= ~IEEE80211_HT_CAP_SUP_WIDTH;
+                               cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
                                cap &= ~IEEE80211_HT_CAP_SGI_40;
                        }
                        break;
@@ -424,9 +425,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
                memcpy(pos, &tmp, sizeof(u16));
                pos += sizeof(u16);
                /* TODO: needs a define here for << 2 */
-               *pos++ = sband->ht_info.ampdu_factor |
-                        (sband->ht_info.ampdu_density << 2);
-               memcpy(pos, sband->ht_info.supp_mcs_set, 16);
+               *pos++ = sband->ht_cap.ampdu_factor |
+                        (sband->ht_cap.ampdu_density << 2);
+               memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
        }
 
        kfree(ifsta->assocreq_ies);
@@ -571,7 +572,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
 static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
                                           u16 capab, bool erp_valid, u8 erp)
 {
-       struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
        struct ieee80211_if_sta *ifsta = &sdata->u.sta;
 #endif
@@ -699,14 +700,15 @@ static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata,
 
 
 static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
-                                    struct ieee80211_if_sta *ifsta)
+                                    struct ieee80211_if_sta *ifsta,
+                                    u32 bss_info_changed)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_conf *conf = &local_to_hw(local)->conf;
-       u32 changed = BSS_CHANGED_ASSOC;
 
        struct ieee80211_bss *bss;
 
+       bss_info_changed |= BSS_CHANGED_ASSOC;
        ifsta->flags |= IEEE80211_STA_ASSOCIATED;
 
        if (sdata->vif.type != NL80211_IFTYPE_STATION)
@@ -717,23 +719,16 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
                                   ifsta->ssid, ifsta->ssid_len);
        if (bss) {
                /* set timing information */
-               sdata->bss_conf.beacon_int = bss->beacon_int;
-               sdata->bss_conf.timestamp = bss->timestamp;
-               sdata->bss_conf.dtim_period = bss->dtim_period;
+               sdata->vif.bss_conf.beacon_int = bss->beacon_int;
+               sdata->vif.bss_conf.timestamp = bss->timestamp;
+               sdata->vif.bss_conf.dtim_period = bss->dtim_period;
 
-               changed |= ieee80211_handle_bss_capability(sdata,
+               bss_info_changed |= ieee80211_handle_bss_capability(sdata,
                        bss->capability, bss->has_erp_value, bss->erp_value);
 
                ieee80211_rx_bss_put(local, 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;
-       }
-
        ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
        memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
        ieee80211_sta_send_associnfo(sdata, ifsta);
@@ -741,14 +736,14 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
        ifsta->last_probe = jiffies;
        ieee80211_led_assoc(local, 1);
 
-       sdata->bss_conf.assoc = 1;
+       sdata->vif.bss_conf.assoc = 1;
        /*
         * For now just always ask the driver to update the basic rateset
         * when we have associated, we aren't checking whether it actually
         * changed or not.
         */
-       changed |= BSS_CHANGED_BASIC_RATES;
-       ieee80211_bss_info_change_notify(sdata, changed);
+       bss_info_changed |= BSS_CHANGED_BASIC_RATES;
+       ieee80211_bss_info_change_notify(sdata, bss_info_changed);
 
        netif_tx_start_all_queues(sdata->dev);
        netif_carrier_on(sdata->dev);
@@ -812,7 +807,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta;
-       u32 changed = BSS_CHANGED_ASSOC;
+       u32 changed = 0;
 
        rcu_read_lock();
 
@@ -846,15 +841,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
        changed |= ieee80211_reset_erp_info(sdata);
 
-       if (sdata->bss_conf.assoc_ht)
-               changed |= BSS_CHANGED_HT;
-
-       sdata->bss_conf.assoc_ht = 0;
-       sdata->bss_conf.ht_conf = NULL;
-       sdata->bss_conf.ht_bss_conf = NULL;
-
        ieee80211_led_assoc(local, 0);
-       sdata->bss_conf.assoc = 0;
+       changed |= BSS_CHANGED_ASSOC;
+       sdata->vif.bss_conf.assoc = false;
 
        ieee80211_sta_send_apinfo(sdata, ifsta);
 
@@ -866,6 +855,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        rcu_read_unlock();
 
        sta_info_destroy(sta);
+
+       local->hw.conf.ht.enabled = false;
+       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT);
+
+       ieee80211_bss_info_change_notify(sdata, changed);
 }
 
 static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata)
@@ -1181,10 +1175,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        u64 rates, basic_rates;
        u16 capab_info, status_code, aid;
        struct ieee802_11_elems elems;
-       struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf;
+       struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
        u8 *pos;
+       u32 changed = 0;
        int i, j;
        bool have_higher_than_11mbit = false;
+       u16 ap_ht_cap_flags;
 
        /* AssocResp and ReassocResp have identical structure, so process both
         * of them in this function. */
@@ -1323,7 +1319,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        }
 
        sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
-       sdata->bss_conf.basic_rates = basic_rates;
+       sdata->vif.bss_conf.basic_rates = basic_rates;
 
        /* cf. IEEE 802.11 9.2.12 */
        if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
@@ -1332,15 +1328,11 @@ 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 &&
-           (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
-               struct ieee80211_ht_bss_info bss_info;
-               ieee80211_ht_cap_ie_to_ht_info(
-                               elems.ht_cap_elem, &sta->sta.ht_info);
-               ieee80211_ht_addt_info_ie_to_ht_bss_info(
-                               elems.ht_info_elem, &bss_info);
-               ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info);
-       }
+       if (elems.ht_cap_elem)
+               ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+                               elems.ht_cap_elem, &sta->sta.ht_cap);
+
+       ap_ht_cap_flags = sta->sta.ht_cap.cap;
 
        rate_control_rate_init(sta);
 
@@ -1352,11 +1344,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        } else
                rcu_read_unlock();
 
+       if (elems.ht_info_elem && elems.wmm_param &&
+           (ifsta->flags & IEEE80211_STA_WMM_ENABLED))
+               changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
+                                              ap_ht_cap_flags);
+
        /* set AID and assoc capability,
         * ieee80211_set_associated() will tell the driver */
        bss_conf->aid = aid;
        bss_conf->assoc_capability = capab_info;
-       ieee80211_set_associated(sdata, ifsta);
+       ieee80211_set_associated(sdata, ifsta, changed);
 
        ieee80211_associated(sdata, ifsta);
 }
@@ -1656,7 +1653,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        size_t baselen;
        struct ieee802_11_elems elems;
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_conf *conf = &local->hw.conf;
        u32 changed = 0;
        bool erp_valid;
        u8 erp_value = 0;
@@ -1692,14 +1688,31 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                        le16_to_cpu(mgmt->u.beacon.capab_info),
                        erp_valid, erp_value);
 
-       if (elems.ht_cap_elem && elems.ht_info_elem &&
-           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(
-                               elems.ht_info_elem, &bss_info);
-               changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf,
-                                              &bss_info);
+       if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) {
+               struct sta_info *sta;
+               struct ieee80211_supported_band *sband;
+               u16 ap_ht_cap_flags;
+
+               rcu_read_lock();
+
+               sta = sta_info_get(local, ifsta->bssid);
+               if (!sta) {
+                       rcu_read_unlock();
+                       return;
+               }
+
+               sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+
+               ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
+                               elems.ht_cap_elem, &sta->sta.ht_cap);
+
+               ap_ht_cap_flags = sta->sta.ht_cap.cap;
+
+               rcu_read_unlock();
+
+               changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
+                                              ap_ht_cap_flags);
        }
 
        ieee80211_bss_info_change_notify(sdata, changed);