mac80211: add ssid config to bss information in AP-mode
[pandora-kernel.git] / net / mac80211 / util.c
index 5bfb80c..4b1466d 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
 #include <linux/bitmap.h>
-#include <linux/crc32.h>
 #include <net/net_namespace.h>
 #include <net/cfg80211.h>
 #include <net/rtnetlink.h>
@@ -573,172 +572,6 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
        ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
 }
 
-u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
-                              struct ieee802_11_elems *elems,
-                              u64 filter, u32 crc)
-{
-       size_t left = len;
-       u8 *pos = start;
-       bool calc_crc = filter != 0;
-
-       memset(elems, 0, sizeof(*elems));
-       elems->ie_start = start;
-       elems->total_len = len;
-
-       while (left >= 2) {
-               u8 id, elen;
-
-               id = *pos++;
-               elen = *pos++;
-               left -= 2;
-
-               if (elen > left)
-                       break;
-
-               if (calc_crc && id < 64 && (filter & (1ULL << id)))
-                       crc = crc32_be(crc, pos - 2, elen + 2);
-
-               switch (id) {
-               case WLAN_EID_SSID:
-                       elems->ssid = pos;
-                       elems->ssid_len = elen;
-                       break;
-               case WLAN_EID_SUPP_RATES:
-                       elems->supp_rates = pos;
-                       elems->supp_rates_len = elen;
-                       break;
-               case WLAN_EID_FH_PARAMS:
-                       elems->fh_params = pos;
-                       elems->fh_params_len = elen;
-                       break;
-               case WLAN_EID_DS_PARAMS:
-                       elems->ds_params = pos;
-                       elems->ds_params_len = elen;
-                       break;
-               case WLAN_EID_CF_PARAMS:
-                       elems->cf_params = pos;
-                       elems->cf_params_len = elen;
-                       break;
-               case WLAN_EID_TIM:
-                       if (elen >= sizeof(struct ieee80211_tim_ie)) {
-                               elems->tim = (void *)pos;
-                               elems->tim_len = elen;
-                       }
-                       break;
-               case WLAN_EID_IBSS_PARAMS:
-                       elems->ibss_params = pos;
-                       elems->ibss_params_len = elen;
-                       break;
-               case WLAN_EID_CHALLENGE:
-                       elems->challenge = pos;
-                       elems->challenge_len = elen;
-                       break;
-               case WLAN_EID_VENDOR_SPECIFIC:
-                       if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
-                           pos[2] == 0xf2) {
-                               /* Microsoft OUI (00:50:F2) */
-
-                               if (calc_crc)
-                                       crc = crc32_be(crc, pos - 2, elen + 2);
-
-                               if (pos[3] == 1) {
-                                       /* OUI Type 1 - WPA IE */
-                                       elems->wpa = pos;
-                                       elems->wpa_len = elen;
-                               } else if (elen >= 5 && pos[3] == 2) {
-                                       /* OUI Type 2 - WMM IE */
-                                       if (pos[4] == 0) {
-                                               elems->wmm_info = pos;
-                                               elems->wmm_info_len = elen;
-                                       } else if (pos[4] == 1) {
-                                               elems->wmm_param = pos;
-                                               elems->wmm_param_len = elen;
-                                       }
-                               }
-                       }
-                       break;
-               case WLAN_EID_RSN:
-                       elems->rsn = pos;
-                       elems->rsn_len = elen;
-                       break;
-               case WLAN_EID_ERP_INFO:
-                       elems->erp_info = pos;
-                       elems->erp_info_len = elen;
-                       break;
-               case WLAN_EID_EXT_SUPP_RATES:
-                       elems->ext_supp_rates = pos;
-                       elems->ext_supp_rates_len = elen;
-                       break;
-               case WLAN_EID_HT_CAPABILITY:
-                       if (elen >= sizeof(struct ieee80211_ht_cap))
-                               elems->ht_cap_elem = (void *)pos;
-                       break;
-               case WLAN_EID_HT_INFORMATION:
-                       if (elen >= sizeof(struct ieee80211_ht_info))
-                               elems->ht_info_elem = (void *)pos;
-                       break;
-               case WLAN_EID_MESH_ID:
-                       elems->mesh_id = pos;
-                       elems->mesh_id_len = elen;
-                       break;
-               case WLAN_EID_MESH_CONFIG:
-                       if (elen >= sizeof(struct ieee80211_meshconf_ie))
-                               elems->mesh_config = (void *)pos;
-                       break;
-               case WLAN_EID_PEER_LINK:
-                       elems->peer_link = pos;
-                       elems->peer_link_len = elen;
-                       break;
-               case WLAN_EID_PREQ:
-                       elems->preq = pos;
-                       elems->preq_len = elen;
-                       break;
-               case WLAN_EID_PREP:
-                       elems->prep = pos;
-                       elems->prep_len = elen;
-                       break;
-               case WLAN_EID_PERR:
-                       elems->perr = pos;
-                       elems->perr_len = elen;
-                       break;
-               case WLAN_EID_RANN:
-                       if (elen >= sizeof(struct ieee80211_rann_ie))
-                               elems->rann = (void *)pos;
-                       break;
-               case WLAN_EID_CHANNEL_SWITCH:
-                       elems->ch_switch_elem = pos;
-                       elems->ch_switch_elem_len = elen;
-                       break;
-               case WLAN_EID_QUIET:
-                       if (!elems->quiet_elem) {
-                               elems->quiet_elem = pos;
-                               elems->quiet_elem_len = elen;
-                       }
-                       elems->num_of_quiet_elem++;
-                       break;
-               case WLAN_EID_COUNTRY:
-                       elems->country_elem = pos;
-                       elems->country_elem_len = elen;
-                       break;
-               case WLAN_EID_PWR_CONSTRAINT:
-                       elems->pwr_constr_elem = pos;
-                       elems->pwr_constr_elem_len = elen;
-                       break;
-               case WLAN_EID_TIMEOUT_INTERVAL:
-                       elems->timeout_int = pos;
-                       elems->timeout_int_len = elen;
-                       break;
-               default:
-                       break;
-               }
-
-               left -= elen;
-               pos += elen;
-       }
-
-       return crc;
-}
-
 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
@@ -799,6 +632,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
 
                qparam.uapsd = false;
 
+               local->tx_conf[queue] = qparam;
                drv_conf_tx(local, queue, &qparam);
        }
 
@@ -873,11 +707,9 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom +
                            sizeof(*mgmt) + 6 + extra_len);
-       if (!skb) {
-               printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
-                      "frame\n", sdata->name);
+       if (!skb)
                return;
-       }
+
        skb_reserve(skb, local->hw.extra_tx_headroom);
 
        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
@@ -1016,7 +848,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 }
 
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-                                         u8 *dst,
+                                         u8 *dst, u32 ratemask,
                                          const u8 *ssid, size_t ssid_len,
                                          const u8 *ie, size_t ie_len,
                                          bool directed)
@@ -1030,11 +862,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 
        /* FIXME: come up with a proper value */
        buf = kmalloc(200 + ie_len, GFP_KERNEL);
-       if (!buf) {
-               printk(KERN_DEBUG "%s: failed to allocate temporary IE "
-                      "buffer\n", sdata->name);
+       if (!buf)
                return NULL;
-       }
 
        /*
         * Do not send DS Channel parameter for directed probe requests
@@ -1049,9 +878,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 
        buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
                                           local->hw.conf.channel->band,
-                                          sdata->rc_rateidx_mask
-                                          [local->hw.conf.channel->band],
-                                          chan);
+                                          ratemask, chan);
 
        skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
                                     ssid, ssid_len,
@@ -1072,12 +899,12 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                              const u8 *ssid, size_t ssid_len,
                              const u8 *ie, size_t ie_len,
-                             bool directed)
+                             u32 ratemask, bool directed)
 {
        struct sk_buff *skb;
 
-       skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len,
-                                       directed);
+       skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len,
+                                       ie, ie_len, directed);
        if (skb)
                ieee80211_tx_skb(sdata, skb);
 }
@@ -1134,7 +961,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        struct ieee80211_hw *hw = &local->hw;
        struct ieee80211_sub_if_data *sdata;
        struct sta_info *sta;
-       int res;
+       int res, i;
 
 #ifdef CONFIG_PM
        if (local->suspended)
@@ -1157,27 +984,37 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        }
 #endif
 
-       /* restart hardware */
-       if (local->open_count) {
-               /*
-                * Upon resume hardware can sometimes be goofy due to
-                * various platform / driver / bus issues, so restarting
-                * the device may at times not work immediately. Propagate
-                * the error.
-                */
-               res = drv_start(local);
-               if (res) {
-                       WARN(local->suspended, "Hardware became unavailable "
-                            "upon resume. This could be a software issue "
-                            "prior to suspend or a hardware issue.\n");
-                       return res;
-               }
+       /* setup fragmentation threshold */
+       drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
 
-               ieee80211_led_radio(local, true);
-               ieee80211_mod_tpt_led_trig(local,
-                                          IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
+       /* setup RTS threshold */
+       drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
+
+       /* reset coverage class */
+       drv_set_coverage_class(local, hw->wiphy->coverage_class);
+
+       /* everything else happens only if HW was up & running */
+       if (!local->open_count)
+               goto wake_up;
+
+       /*
+        * Upon resume hardware can sometimes be goofy due to
+        * various platform / driver / bus issues, so restarting
+        * the device may at times not work immediately. Propagate
+        * the error.
+        */
+       res = drv_start(local);
+       if (res) {
+               WARN(local->suspended, "Hardware became unavailable "
+                    "upon resume. This could be a software issue "
+                    "prior to suspend or a hardware issue.\n");
+               return res;
        }
 
+       ieee80211_led_radio(local, true);
+       ieee80211_mod_tpt_led_trig(local,
+                                  IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
+
        /* add interfaces */
        list_for_each_entry(sdata, &local->interfaces, list) {
                if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
@@ -1196,16 +1033,15 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                                             struct ieee80211_sub_if_data,
                                             u.ap);
 
+                       memset(&sta->sta.drv_priv, 0, hw->sta_data_size);
                        WARN_ON(drv_sta_add(local, sdata, &sta->sta));
                }
        }
        mutex_unlock(&local->sta_mtx);
 
-       /* setup fragmentation threshold */
-       drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
-
-       /* setup RTS threshold */
-       drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
+       /* reconfigure tx conf */
+       for (i = 0; i < hw->queues; i++)
+               drv_conf_tx(local, i, &local->tx_conf[i]);
 
        /* reconfigure hardware */
        ieee80211_hw_config(local, ~0);
@@ -1241,6 +1077,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                        changed |= BSS_CHANGED_IBSS;
                        /* fall through */
                case NL80211_IFTYPE_AP:
+                       changed |= BSS_CHANGED_SSID;
+                       /* fall through */
                case NL80211_IFTYPE_MESH_POINT:
                        changed |= BSS_CHANGED_BEACON |
                                   BSS_CHANGED_BEACON_ENABLED;
@@ -1287,9 +1125,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                if (ieee80211_sdata_running(sdata))
                        ieee80211_enable_keys(sdata);
 
-#ifdef CONFIG_PM
  wake_up:
-#endif
        ieee80211_wake_queues_by_reason(hw,
                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);