Pull ia64-clocksource into release branch
[pandora-kernel.git] / net / mac80211 / ieee80211_sta.c
index 9f30ae4..22b1178 100644 (file)
@@ -76,33 +76,36 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
 
 /* Parsed Information Elements */
 struct ieee802_11_elems {
+       /* pointers to IEs */
        u8 *ssid;
-       u8 ssid_len;
        u8 *supp_rates;
-       u8 supp_rates_len;
        u8 *fh_params;
-       u8 fh_params_len;
        u8 *ds_params;
-       u8 ds_params_len;
        u8 *cf_params;
-       u8 cf_params_len;
        u8 *tim;
-       u8 tim_len;
        u8 *ibss_params;
-       u8 ibss_params_len;
        u8 *challenge;
-       u8 challenge_len;
        u8 *wpa;
-       u8 wpa_len;
        u8 *rsn;
-       u8 rsn_len;
        u8 *erp_info;
-       u8 erp_info_len;
        u8 *ext_supp_rates;
-       u8 ext_supp_rates_len;
        u8 *wmm_info;
-       u8 wmm_info_len;
        u8 *wmm_param;
+
+       /* length of them, respectively */
+       u8 ssid_len;
+       u8 supp_rates_len;
+       u8 fh_params_len;
+       u8 ds_params_len;
+       u8 cf_params_len;
+       u8 tim_len;
+       u8 ibss_params_len;
+       u8 challenge_len;
+       u8 wpa_len;
+       u8 rsn_len;
+       u8 erp_info_len;
+       u8 ext_supp_rates_len;
+       u8 wmm_info_len;
        u8 wmm_param_len;
 };
 
@@ -311,6 +314,25 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
 }
 
 
+static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+       int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
+
+       if (use_protection != sdata->use_protection) {
+               if (net_ratelimit()) {
+                       printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
+                              MAC_FMT ")\n",
+                              dev->name,
+                              use_protection ? "enabled" : "disabled",
+                              MAC_ARG(ifsta->bssid));
+               }
+               sdata->use_protection = use_protection;
+       }
+}
+
+
 static void ieee80211_sta_send_associnfo(struct net_device *dev,
                                         struct ieee80211_if_sta *ifsta)
 {
@@ -366,6 +388,7 @@ static void ieee80211_set_associated(struct net_device *dev,
                                     struct ieee80211_if_sta *ifsta, int assoc)
 {
        union iwreq_data wrqu;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        if (ifsta->associated == assoc)
                return;
@@ -374,9 +397,18 @@ static void ieee80211_set_associated(struct net_device *dev,
 
        if (assoc) {
                struct ieee80211_sub_if_data *sdata;
+               struct ieee80211_sta_bss *bss;
                sdata = IEEE80211_DEV_TO_SUB_IF(dev);
                if (sdata->type != IEEE80211_IF_TYPE_STA)
                        return;
+
+               bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
+               if (bss) {
+                       if (bss->has_erp_value)
+                               ieee80211_handle_erp_ie(dev, bss->erp_value);
+                       ieee80211_rx_bss_put(dev, bss);
+               }
+
                netif_carrier_on(dev);
                ifsta->prev_bssid_set = 1;
                memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -384,6 +416,7 @@ static void ieee80211_set_associated(struct net_device *dev,
                ieee80211_sta_send_associnfo(dev, ifsta);
        } else {
                netif_carrier_off(dev);
+               sdata->use_protection = 0;
                memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
        }
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -1174,6 +1207,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
                return;
        }
 
+       /* it probably doesn't, but if the frame includes an ERP value then
+        * update our stored copy */
+       if (elems.erp_info && elems.erp_info_len >= 1) {
+               struct ieee80211_sta_bss *bss
+                       = ieee80211_rx_bss_get(dev, ifsta->bssid);
+               if (bss) {
+                       bss->erp_value = elems.erp_info[0];
+                       bss->has_erp_value = 1;
+                       ieee80211_rx_bss_put(dev, bss);
+               }
+       }
+
        printk(KERN_DEBUG "%s: associated\n", dev->name);
        ifsta->aid = aid;
        ifsta->ap_capab = capab_info;
@@ -1282,10 +1327,9 @@ ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_sta_bss *bss;
 
-       bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
+       bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
        if (!bss)
                return NULL;
-       memset(bss, 0, sizeof(*bss));
        atomic_inc(&bss->users);
        atomic_inc(&bss->users);
        memcpy(bss->bssid, bssid, ETH_ALEN);
@@ -1496,6 +1540,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
                return;
        }
 
+       /* save the ERP value so that it is available at association time */
+       if (elems.erp_info && elems.erp_info_len >= 1) {
+               bss->erp_value = elems.erp_info[0];
+               bss->has_erp_value = 1;
+       }
+
        bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
        bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
        if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
@@ -1611,10 +1661,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
                                     size_t len,
                                     struct ieee80211_rx_status *rx_status)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_if_sta *ifsta;
-       int use_protection;
        size_t baselen;
        struct ieee802_11_elems elems;
 
@@ -1638,23 +1686,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
                                   &elems) == ParseFailed)
                return;
 
-       use_protection = 0;
-       if (elems.erp_info && elems.erp_info_len >= 1) {
-               use_protection =
-                       (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
-       }
-
-       if (use_protection != !!ifsta->use_protection) {
-               if (net_ratelimit()) {
-                       printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
-                              MAC_FMT ")\n",
-                              dev->name,
-                              use_protection ? "enabled" : "disabled",
-                              MAC_ARG(ifsta->bssid));
-               }
-               ifsta->use_protection = use_protection ? 1 : 0;
-               local->cts_protect_erp_frames = use_protection;
-       }
+       if (elems.erp_info && elems.erp_info_len >= 1)
+               ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
 
        if (elems.wmm_param && ifsta->wmm_enabled) {
                ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
@@ -2592,11 +2625,17 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
 
        read_lock(&local->sub_if_lock);
        list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+               /* No need to wake the master device. */
+               if (sdata->dev == local->mdev)
+                       continue;
+
                if (sdata->type == IEEE80211_IF_TYPE_STA) {
                        if (sdata->u.sta.associated)
                                ieee80211_send_nullfunc(local, sdata, 0);
                        ieee80211_sta_timer((unsigned long)sdata);
                }
+
                netif_wake_queue(sdata->dev);
        }
        read_unlock(&local->sub_if_lock);
@@ -2738,6 +2777,12 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
 
        read_lock(&local->sub_if_lock);
        list_for_each_entry(sdata, &local->sub_if_list, list) {
+
+               /* Don't stop the master interface, otherwise we can't transmit
+                * probes! */
+               if (sdata->dev == local->mdev)
+                       continue;
+
                netif_stop_queue(sdata->dev);
                if (sdata->type == IEEE80211_IF_TYPE_STA &&
                    sdata->u.sta.associated)