- bss = ieee80211_rx_bss_get(local, ifsta->bssid,
- local->hw.conf.channel->center_freq,
- ifsta->ssid, ifsta->ssid_len);
- if (bss) {
- sta->last_signal = bss->signal;
- sta->last_qual = bss->qual;
- sta->last_noise = bss->noise;
- ieee80211_rx_bss_put(local, bss);
- }
-
- err = sta_info_insert(sta);
- if (err) {
- printk(KERN_DEBUG "%s: failed to insert STA entry for"
- " the AP (error %d)\n", sdata->dev->name, err);
- rcu_read_unlock();
- return;
- }
- /* update new sta with its last rx activity */
- sta->last_rx = jiffies;
- }
-
- /*
- * FIXME: Do we really need to update the sta_info's information here?
- * We already know about the AP (we found it in our list) so it
- * should already be filled with the right info, no?
- * As is stands, all this is racy because typically we assume
- * the information that is filled in here (except flags) doesn't
- * change while a STA structure is alive. As such, it should move
- * to between the sta_info_alloc() and sta_info_insert() above.
- */
-
- set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
- WLAN_STA_AUTHORIZED);
-
- rates = 0;
- basic_rates = 0;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-
- for (i = 0; i < elems.supp_rates_len; i++) {
- int rate = (elems.supp_rates[i] & 0x7f) * 5;
-
- if (rate > 110)
- have_higher_than_11mbit = true;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate)
- rates |= BIT(j);
- if (elems.supp_rates[i] & 0x80)
- basic_rates |= BIT(j);
- }
- }
-
- for (i = 0; i < elems.ext_supp_rates_len; i++) {
- int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
-
- if (rate > 110)
- have_higher_than_11mbit = true;
-
- for (j = 0; j < sband->n_bitrates; j++) {
- if (sband->bitrates[j].bitrate == rate)
- rates |= BIT(j);
- if (elems.ext_supp_rates[i] & 0x80)
- basic_rates |= BIT(j);
- }
- }
-
- sta->supp_rates[local->hw.conf.channel->band] = rates;
- sdata->basic_rates = basic_rates;
-
- /* cf. IEEE 802.11 9.2.12 */
- if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
- have_higher_than_11mbit)
- sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
- 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(
- (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_handle_ht(local, 1, &sta->ht_info, &bss_info);
- }
-
- rate_control_rate_init(sta, local);
-
- if (elems.wmm_param) {
- set_sta_flags(sta, WLAN_STA_WME);
- rcu_read_unlock();
- ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param,
- elems.wmm_param_len);
- } else
- rcu_read_unlock();
-
- /* 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_associated(sdata, ifsta);
-}
-
-
-/* Caller must hold local->sta_bss_lock */
-static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
- struct ieee80211_sta_bss *bss)
-{
- u8 hash_idx;
-
- if (bss_mesh_cfg(bss))
- hash_idx = mesh_id_hash(bss_mesh_id(bss),
- bss_mesh_id_len(bss));
- else
- hash_idx = STA_HASH(bss->bssid);
-
- bss->hnext = local->sta_bss_hash[hash_idx];
- local->sta_bss_hash[hash_idx] = bss;
-}
-
-
-/* Caller must hold local->sta_bss_lock */
-static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
- struct ieee80211_sta_bss *bss)
-{
- struct ieee80211_sta_bss *b, *prev = NULL;
- b = local->sta_bss_hash[STA_HASH(bss->bssid)];
- while (b) {
- if (b == bss) {
- if (!prev)
- local->sta_bss_hash[STA_HASH(bss->bssid)] =
- bss->hnext;
- else
- prev->hnext = bss->hnext;
- break;
- }
- prev = b;
- b = b->hnext;
- }
-}
-
-
-static struct ieee80211_sta_bss *
-ieee80211_rx_bss_add(struct ieee80211_sub_if_data *sdata, u8 *bssid, int freq,
- u8 *ssid, u8 ssid_len)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_sta_bss *bss;
-
- bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
- if (!bss)
- return NULL;
- atomic_inc(&bss->users);
- atomic_inc(&bss->users);
- memcpy(bss->bssid, bssid, ETH_ALEN);
- bss->freq = freq;
- if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
- memcpy(bss->ssid, ssid, ssid_len);
- bss->ssid_len = ssid_len;
- }
-
- spin_lock_bh(&local->sta_bss_lock);
- /* TODO: order by RSSI? */
- list_add_tail(&bss->list, &local->sta_bss_list);
- __ieee80211_rx_bss_hash_add(local, bss);
- spin_unlock_bh(&local->sta_bss_lock);
- return bss;
-}
-
-static struct ieee80211_sta_bss *
-ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
- u8 *ssid, u8 ssid_len)
-{
- struct ieee80211_sta_bss *bss;
-
- spin_lock_bh(&local->sta_bss_lock);
- bss = local->sta_bss_hash[STA_HASH(bssid)];
- while (bss) {
- if (!bss_mesh_cfg(bss) &&
- !memcmp(bss->bssid, bssid, ETH_ALEN) &&
- bss->freq == freq &&
- bss->ssid_len == ssid_len &&
- (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
- atomic_inc(&bss->users);
- break;
- }
- bss = bss->hnext;
- }
- spin_unlock_bh(&local->sta_bss_lock);
- return bss;
-}
-
-#ifdef CONFIG_MAC80211_MESH
-static struct ieee80211_sta_bss *
-ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
- u8 *mesh_cfg, int freq)
-{
- struct ieee80211_sta_bss *bss;