aboutsummaryrefslogtreecommitdiffstats
path: root/package/mac80211/src/mac80211/ieee80211_sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'package/mac80211/src/mac80211/ieee80211_sta.c')
-rw-r--r--package/mac80211/src/mac80211/ieee80211_sta.c1306
1 files changed, 217 insertions, 1089 deletions
diff --git a/package/mac80211/src/mac80211/ieee80211_sta.c b/package/mac80211/src/mac80211/ieee80211_sta.c
index 0e4501db74..7c93f29c8b 100644
--- a/package/mac80211/src/mac80211/ieee80211_sta.c
+++ b/package/mac80211/src/mac80211/ieee80211_sta.c
@@ -25,14 +25,13 @@
#include <linux/wireless.h>
#include <linux/random.h>
#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
#include <net/iw_handler.h>
#include <asm/types.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "ieee80211_rate.h"
-#include "hostapd_ioctl.h"
+#include "ieee80211_led.h"
#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_MAX_TRIES 3
@@ -59,9 +58,6 @@
#define ERP_INFO_USE_PROTECTION BIT(1)
-/* mgmt header + 1 byte action code */
-#define IEEE80211_MIN_ACTION_SIZE (24 + 1)
-
static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
u8 *ssid, size_t ssid_len);
static struct ieee80211_sta_bss *
@@ -79,47 +75,43 @@ 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 *ht_cap_param;
- u8 ht_cap_param_len;
- u8 *ht_extra_param;
- u8 ht_extra_param_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;
- u8 *tspec;
- u8 tspec_len;
};
-typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes;
+enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 };
-
-static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
- struct ieee802_11_elems *elems)
+static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
+ struct ieee802_11_elems *elems)
{
size_t left = len;
u8 *pos = start;
@@ -181,34 +173,17 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
pos[2] == 0xf2) {
/* Microsoft OUI (00:50:F2) */
- if (pos[3] == WIFI_OUI_TYPE_WPA) {
+ if (pos[3] == 1) {
/* OUI Type 1 - WPA IE */
elems->wpa = pos;
elems->wpa_len = elen;
- } else if (elen >= 5 &&
- pos[3] == WIFI_OUI_TYPE_WMM) {
- switch (pos[4]) {
- case WIFI_OUI_STYPE_WMM_INFO:
+ } else if (elen >= 5 && pos[3] == 2) {
+ if (pos[4] == 0) {
elems->wmm_info = pos;
elems->wmm_info_len = elen;
- break;
- case WIFI_OUI_STYPE_WMM_PARAM:
+ } else if (pos[4] == 1) {
elems->wmm_param = pos;
elems->wmm_param_len = elen;
- break;
- case WIFI_OUI_STYPE_WMM_TSPEC:
- if (elen != 61) {
- printk(KERN_ERR "Wrong "
- "TSPEC size.\n");
- break;
- }
- elems->tspec = pos + 6;
- elems->tspec_len = elen - 6;
- break;
- default:
- //printk(KERN_ERR "Unsupported "
- // "WiFi OUI %d\n", pos[4]);
- break;
}
}
}
@@ -225,22 +200,6 @@ static ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
elems->ext_supp_rates = pos;
elems->ext_supp_rates_len = elen;
break;
- case WLAN_EID_HT_CAPABILITY:
- elems->ht_cap_param = pos;
- elems->ht_cap_param_len = elen;
- break;
- case WLAN_EID_HT_EXTRA_INFO:
- elems->ht_extra_param = pos;
- elems->ht_extra_param_len = elen;
- break;
- case WLAN_EID_TSPEC:
- if (elen != 55) {
- printk(KERN_ERR "Wrong TSPEC size.\n");
- break;
- }
- elems->tspec = pos;
- elems->tspec_len = elen;
- break;
default:
#if 0
printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
@@ -352,6 +311,50 @@ 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;
+ int preamble_mode = (erp_value & WLAN_ERP_BARKER_PREAMBLE) != 0;
+ u8 changes = 0;
+
+ if (use_protection != !!(sdata->flags & IEEE80211_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));
+ }
+ if (use_protection)
+ sdata->flags |= IEEE80211_SDATA_USE_PROTECTION;
+ else
+ sdata->flags &= ~IEEE80211_SDATA_USE_PROTECTION;
+ changes |= IEEE80211_ERP_CHANGE_PROTECTION;
+ }
+
+ if (preamble_mode != !(sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE)) {
+ if (net_ratelimit()) {
+ printk(KERN_DEBUG "%s: switched to %s barker preamble"
+ " (BSSID=" MAC_FMT ")\n",
+ dev->name,
+ (preamble_mode == WLAN_ERP_PREAMBLE_SHORT) ?
+ "short" : "long",
+ MAC_ARG(ifsta->bssid));
+ }
+ if (preamble_mode)
+ sdata->flags &= ~IEEE80211_SDATA_SHORT_PREAMBLE;
+ else
+ sdata->flags |= IEEE80211_SDATA_SHORT_PREAMBLE;
+ changes |= IEEE80211_ERP_CHANGE_PREAMBLE;
+ }
+
+ if (changes)
+ ieee80211_erp_info_change_notify(dev, changes);
+}
+
+
static void ieee80211_sta_send_associnfo(struct net_device *dev,
struct ieee80211_if_sta *ifsta)
{
@@ -364,7 +367,7 @@ static void ieee80211_sta_send_associnfo(struct net_device *dev,
return;
buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len +
- ifsta->assocresp_ies_len), GFP_ATOMIC);
+ ifsta->assocresp_ies_len), GFP_KERNEL);
if (!buf)
return;
@@ -404,32 +407,48 @@ static void ieee80211_sta_send_associnfo(struct net_device *dev,
static void ieee80211_set_associated(struct net_device *dev,
- struct ieee80211_if_sta *ifsta, int assoc)
+ struct ieee80211_if_sta *ifsta,
+ bool assoc)
{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
union iwreq_data wrqu;
- if (ifsta->associated == assoc)
+ if (!!(ifsta->flags & IEEE80211_STA_ASSOCIATED) == assoc)
return;
- ifsta->associated = assoc;
-
if (assoc) {
struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_sta_bss *bss;
+
+ ifsta->flags |= IEEE80211_STA_ASSOCIATED;
+
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;
+ ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET;
memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN);
ieee80211_sta_send_associnfo(dev, ifsta);
} else {
+ ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
+
netif_carrier_off(dev);
+ ieee80211_reset_erp_info(dev);
memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
}
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
ifsta->last_probe = jiffies;
+ ieee80211_led_assoc(local, assoc);
}
static void ieee80211_set_disassoc(struct net_device *dev,
@@ -456,8 +475,8 @@ static void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb,
pkt_data = (struct ieee80211_tx_packet_data *) skb->cb;
memset(pkt_data, 0, sizeof(struct ieee80211_tx_packet_data));
pkt_data->ifindex = sdata->dev->ifindex;
- pkt_data->mgmt_iface = (sdata->type == IEEE80211_IF_TYPE_MGMT);
- pkt_data->do_not_encrypt = !encrypt;
+ if (!encrypt)
+ pkt_data->flags |= IEEE80211_TXPD_DO_NOT_ENCRYPT;
dev_queue_xmit(skb);
}
@@ -535,7 +554,6 @@ static void ieee80211_send_assoc(struct net_device *dev,
u16 capab;
struct ieee80211_sta_bss *bss;
int wmm = 0;
- int ht_enabled = 0;
skb = dev_alloc_skb(local->hw.extra_tx_headroom +
sizeof(*mgmt) + 200 + ifsta->extra_ie_len +
@@ -559,8 +577,6 @@ static void ieee80211_send_assoc(struct net_device *dev,
capab |= WLAN_CAPABILITY_PRIVACY;
if (bss->wmm_ie) {
wmm = 1;
-
- ht_enabled = 1;
}
ieee80211_rx_bss_put(dev, bss);
}
@@ -571,7 +587,7 @@ static void ieee80211_send_assoc(struct net_device *dev,
memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- if (ifsta->prev_bssid_set) {
+ if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) {
skb_put(skb, 10);
mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
IEEE80211_STYPE_REASSOC_REQ);
@@ -601,8 +617,6 @@ static void ieee80211_send_assoc(struct net_device *dev,
*pos++ = len;
for (i = 0; i < len; i++) {
int rate = mode->rates[i].rate;
- if (mode->mode == MODE_ATHEROS_TURBO)
- rate /= 2;
*pos++ = (u8) (rate / 5);
}
@@ -612,8 +626,6 @@ static void ieee80211_send_assoc(struct net_device *dev,
*pos++ = mode->num_rates - len;
for (i = len; i < mode->num_rates; i++) {
int rate = mode->rates[i].rate;
- if (mode->mode == MODE_ATHEROS_TURBO)
- rate /= 2;
*pos++ = (u8) (rate / 5);
}
}
@@ -623,7 +635,7 @@ static void ieee80211_send_assoc(struct net_device *dev,
memcpy(pos, ifsta->extra_ie, ifsta->extra_ie_len);
}
- if (wmm && ifsta->wmm_enabled) {
+ if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
pos = skb_put(skb, 9);
*pos++ = WLAN_EID_VENDOR_SPECIFIC;
*pos++ = 7; /* len */
@@ -636,19 +648,9 @@ static void ieee80211_send_assoc(struct net_device *dev,
*pos++ = 0;
}
- /* if low level driver supports 11n, fill in 11n IE */
- if (ht_enabled && ifsta->ht_enabled && local->ops->get_ht_capab) {
- pos = skb_put(skb, sizeof(struct ieee80211_ht_capability)+2);
- *pos++ = WLAN_EID_HT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_ht_capability);
- memset(pos, 0, sizeof(struct ieee80211_ht_capability));
- local->ops->get_ht_capab(local_to_hw(local),
- (struct ieee80211_ht_capability *)pos);
- }
-
kfree(ifsta->assocreq_ies);
ifsta->assocreq_ies_len = (skb->data + skb->len) - ies;
- ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_ATOMIC);
+ ifsta->assocreq_ies = kmalloc(ifsta->assocreq_ies_len, GFP_KERNEL);
if (ifsta->assocreq_ies)
memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len);
@@ -714,410 +716,14 @@ static void ieee80211_send_disassoc(struct net_device *dev,
}
-static int ieee80211_ts_index(u8 direction)
-{
- if (direction == WLAN_TSINFO_DOWNLINK ||
- direction == WLAN_TSINFO_DIRECTLINK)
- return STA_TS_DOWNLINK;
- return STA_TS_UPLINK; /* UP and Bidirectional LINK */
-}
-
-
-void ieee80211_send_addts(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_elem_tspec *tspec)
-{
- struct ieee80211_mgmt *mgmt;
- struct sk_buff *skb;
- static u8 token;
- struct ieee80211_elem_tspec *ptspec;
- u8 *pos;
-
- skb = dev_alloc_skb(sizeof(*mgmt) + sizeof(*tspec));
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for addts "
- "frame\n", dev->name);
- return;
- }
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
-
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.addts_req));
- mgmt->u.action.category = WLAN_CATEGORY_QOS;
- mgmt->u.action.u.addts_req.action_code = WLAN_ACTION_QOS_ADDTS_REQ;
- mgmt->u.action.u.addts_req.dialog_token = ++token % 127;
-
- skb_put(skb, 2 + sizeof(*tspec));
- pos = mgmt->u.action.u.addts_req.variable;
- pos[0] = WLAN_EID_TSPEC;
- pos[1] = sizeof(*tspec);
- pos += 2;
- ptspec = (struct ieee80211_elem_tspec *)pos;
- memcpy(ptspec, tspec, sizeof(*tspec));
-
- ieee80211_sta_tx(dev, skb, 0);
-}
-
-
-void wmm_send_addts(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_elem_tspec *tspec)
-{
- struct ieee80211_mgmt *mgmt;
- struct sk_buff *skb;
- static u8 token;
- struct ieee80211_elem_tspec *ptspec;
- u8 *pos;
-
- skb = dev_alloc_skb(sizeof(*mgmt) + 2 + 6 + sizeof(*tspec));
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for addts "
- "frame\n", dev->name);
- return;
- }
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
-
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.wme_action));
- mgmt->u.action.category = WLAN_CATEGORY_WMM;
- mgmt->u.action.u.wme_action.action_code = WLAN_ACTION_QOS_ADDTS_REQ;
- mgmt->u.action.u.wme_action.dialog_token = ++token % 127;
- mgmt->u.action.u.wme_action.status_code = 0;
-
- skb_put(skb, 2 + 6 + sizeof(*tspec));
- pos = mgmt->u.action.u.wme_action.variable;
- pos[0] = WLAN_EID_GENERIC;
- pos[1] = 61;
- pos += 2;
- pos[0] = 0x00; pos[1] = 0x50; pos[2] = 0xf2; /* Wi-Fi OUI (00:50:F2)*/
- pos += 3;
- pos[0] = WIFI_OUI_TYPE_WMM;
- pos[1] = WIFI_OUI_STYPE_WMM_TSPEC;
- pos[2] = 1; /* Version */
- pos += 3;
- ptspec = (struct ieee80211_elem_tspec *)pos;
- memcpy(ptspec, tspec, sizeof(*tspec));
-
- ieee80211_sta_tx(dev, skb, 0);
-}
-
-
-void ieee80211_send_delts(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_elem_tspec *tp)
-{
- struct ieee80211_mgmt *mgmt;
- struct sk_buff *skb;
- u8 tsid = IEEE80211_TSINFO_TSID(tp->ts_info);
- u8 direction = IEEE80211_TSINFO_DIR(tp->ts_info);
- u16 medium_time = le16_to_cpu(tp->medium_time);
- u8 index = ieee80211_ts_index(direction);
-
- if (ifsta->ts_data[tsid][index].status == TS_STATUS_UNUSED) {
- printk(KERN_DEBUG "%s: Trying to delete an ACM disabled TS "
- "(%u:%u)\n", dev->name, tsid, direction);
- return;
- }
- skb = dev_alloc_skb(sizeof(*mgmt));
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for delts "
- "frame\n", dev->name);
- return;
- }
-
- /* recompute admitted time */
- ifsta->ts_data[tsid][index].admitted_time_usec -=
- ifsta->dot11EDCAAveragingPeriod * medium_time * 32;
- if ((s32)(ifsta->ts_data[tsid][index].admitted_time_usec) < 0)
- ifsta->ts_data[tsid][index].admitted_time_usec = 0;
-
- ifsta->ts_data[tsid][index].status = TS_STATUS_INACTIVE;
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.delts));
- mgmt->u.action.category = WLAN_CATEGORY_QOS;
- mgmt->u.action.u.delts.action_code = WLAN_ACTION_QOS_DELTS;
- mgmt->u.action.u.delts.reason_code = 0;
- memset(&mgmt->u.action.u.delts.ts_info, 0,
- sizeof(struct ieee80211_ts_info));
-
- IEEE80211_SET_TSINFO_TSID(tp->ts_info, tsid);
- IEEE80211_SET_TSINFO_DIR(tp->ts_info, direction);
- IEEE80211_SET_TSINFO_POLICY(tp->ts_info, WLAN_TSINFO_EDCA);
- IEEE80211_SET_TSINFO_APSD(tp->ts_info, WLAN_TSINFO_PSB_LEGACY);
- IEEE80211_SET_TSINFO_UP(tp->ts_info, ifsta->ts_data[tsid][index].up);
-
- ieee80211_sta_tx(dev, skb, 0);
-}
-
-
-void wmm_send_delts(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_elem_tspec *tp)
-{
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_elem_tspec *tspec;
- struct sk_buff *skb;
- u8 tsid = IEEE80211_TSINFO_TSID(tp->ts_info);
- u8 direction = IEEE80211_TSINFO_DIR(tp->ts_info);
- u16 medium_time = le16_to_cpu(tp->medium_time);
- u8 index = ieee80211_ts_index(direction);
- u8 *pos;
-
- if (ifsta->ts_data[tsid][index].status == TS_STATUS_UNUSED) {
- printk(KERN_DEBUG "%s: Tring to delete a non-Actived TS "
- "(%u %u)\n", dev->name, tsid, direction);
- return;
- }
- skb = dev_alloc_skb(sizeof(*mgmt) + 2 + 6 + sizeof(*tspec));
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for delts "
- "frame\n", dev->name);
- return;
- }
-
- /* recompute admitted time */
- ifsta->ts_data[tsid][index].admitted_time_usec -=
- ifsta->dot11EDCAAveragingPeriod * medium_time * 32;
- if ((s32)(ifsta->ts_data[tsid][index].admitted_time_usec < 0))
- ifsta->ts_data[tsid][index].admitted_time_usec = 0;
-
- ifsta->ts_data[tsid][index].status = TS_STATUS_INACTIVE;
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
-
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.wme_action));
- mgmt->u.action.category = WLAN_CATEGORY_WMM;
- mgmt->u.action.u.wme_action.action_code = WLAN_ACTION_QOS_DELTS;
- mgmt->u.action.u.wme_action.dialog_token = 0;
- mgmt->u.action.u.wme_action.status_code = 0;
-
- skb_put(skb, 2 + 6 + sizeof(*tspec));
- pos = mgmt->u.action.u.wme_action.variable;
- pos[0] = WLAN_EID_GENERIC;
- pos[1] = 61;
- pos += 2;
- pos[0] = 0x00; pos[1] = 0x50; pos[2] = 0xf2; /* Wi-Fi OUI (00:50:F2)*/
- pos += 3;
- pos[0] = WIFI_OUI_TYPE_WMM;
- pos[1] = WIFI_OUI_STYPE_WMM_TSPEC;
- pos[2] = 1; /* Version */
- pos += 3;
- tspec = (struct ieee80211_elem_tspec *)pos;
- memset(tspec, 0, sizeof(*tspec));
-
- IEEE80211_SET_TSINFO_TSID(tspec->ts_info, tsid);
- IEEE80211_SET_TSINFO_DIR(tspec->ts_info, direction);
- IEEE80211_SET_TSINFO_POLICY(tspec->ts_info, WLAN_TSINFO_EDCA);
- IEEE80211_SET_TSINFO_APSD(tspec->ts_info, WLAN_TSINFO_PSB_LEGACY);
- IEEE80211_SET_TSINFO_UP(tspec->ts_info, ifsta->ts_data[tsid][index].up);
-
- ieee80211_sta_tx(dev, skb, 0);
-}
-
-
-void ieee80211_send_dls_req(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- u8 *addr, u16 timeout)
-{
- struct ieee80211_hw_mode *mode;
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- u8 *pos, *supp_rates, *esupp_rates = NULL;
- int i;
-
- skb = dev_alloc_skb(sizeof(*mgmt) + 200 /* rates + ext_rates Size */);
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for DLS REQ "
- "frame\n", dev->name);
- return;
- }
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
-
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.dls_req));
- mgmt->u.action.category = WLAN_CATEGORY_DLS;
- mgmt->u.action.u.dls_req.action_code = WLAN_ACTION_DLS_REQ;
- memcpy(mgmt->u.action.u.dls_req.dest, addr, ETH_ALEN);
- memcpy(mgmt->u.action.u.dls_req.src, dev->dev_addr, ETH_ALEN);
- mgmt->u.action.u.dls_req.capab_info = cpu_to_le16(ifsta->ap_capab);
- mgmt->u.action.u.dls_req.timeout = cpu_to_le16(timeout);
-
- /* Add supported rates and extended supported rates */
- supp_rates = skb_put(skb, 2);
- supp_rates[0] = WLAN_EID_SUPP_RATES;
- supp_rates[1] = 0;
- mode = local->oper_hw_mode;
- for (i = 0; i < mode->num_rates; i++) {
- struct ieee80211_rate *rate = &mode->rates[i];
- if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
- continue;
- if (esupp_rates) {
- pos = skb_put(skb, 1);
- esupp_rates[1]++;
- } else if (supp_rates[1] == 8) {
- esupp_rates = skb_put(skb, 3);
- esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
- esupp_rates[1] = 1;
- pos = &esupp_rates[2];
- } else {
- pos = skb_put(skb, 1);
- supp_rates[1]++;
- }
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
- *pos = rate->rate / 10;
- else
- *pos = rate->rate / 5;
- }
-
- ieee80211_sta_tx(dev, skb, 0);
-}
-
-
-static void ieee80211_send_dls_resp(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- u8 *mac_addr, u16 status)
-{
- struct ieee80211_hw_mode *mode;
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- u8 *pos, *supp_rates, *esupp_rates = NULL;
- int i;
-
- skb = dev_alloc_skb(sizeof(*mgmt) + 200 /* rates + ext_rates Size */);
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for dls resp "
- "frame\n", dev->name);
- return;
- }
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
-
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.dls_resp));
- mgmt->u.action.category = WLAN_CATEGORY_DLS;
- mgmt->u.action.u.dls_resp.action_code = WLAN_ACTION_DLS_RESP;
- memcpy(mgmt->u.action.u.dls_resp.dest, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->u.action.u.dls_resp.src, mac_addr, ETH_ALEN);
- mgmt->u.action.u.dls_resp.status_code = cpu_to_le16(status);
-
- if (!mgmt->u.action.u.dls_resp.status_code) {
- ieee80211_sta_tx(dev, skb, 0);
- return;
- }
-
- /* Add capability information */
- pos = skb_put(skb, 2);
- *(__le16 *)pos = cpu_to_le16(ifsta->ap_capab);
-
- /* Add supported rates and extended supported rates */
- supp_rates = skb_put(skb, 2);
- supp_rates[0] = WLAN_EID_SUPP_RATES;
- supp_rates[1] = 0;
- mode = local->oper_hw_mode;
- for (i = 0; i < mode->num_rates; i++) {
- struct ieee80211_rate *rate = &mode->rates[i];
- if (!(rate->flags & IEEE80211_RATE_SUPPORTED))
- continue;
- if (esupp_rates) {
- pos = skb_put(skb, 1);
- esupp_rates[1]++;
- } else if (supp_rates[1] == 8) {
- esupp_rates = skb_put(skb, 3);
- esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
- esupp_rates[1] = 1;
- pos = &esupp_rates[2];
- } else {
- pos = skb_put(skb, 1);
- supp_rates[1]++;
- }
- if (local->hw.conf.phymode == MODE_ATHEROS_TURBO)
- *pos = rate->rate / 10;
- else
- *pos = rate->rate / 5;
- }
-
- ieee80211_sta_tx(dev, skb, 0);
-}
-
-
-void ieee80211_send_dls_teardown(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- u8 *mac_addr, u16 reason)
-{
- struct ieee80211_mgmt *mgmt;
- struct sk_buff *skb;
-
- skb = dev_alloc_skb(sizeof(*mgmt));
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer for DLS "
- "Teardown frame\n", dev->name);
- return;
- }
-
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.dls_teardown));
- mgmt->u.action.category = WLAN_CATEGORY_DLS;
- mgmt->u.action.u.dls_teardown.action_code = WLAN_ACTION_DLS_TEARDOWN;
- memcpy(mgmt->u.action.u.dls_teardown.dest, mac_addr, ETH_ALEN);
- memcpy(mgmt->u.action.u.dls_teardown.src, dev->dev_addr, ETH_ALEN);
- mgmt->u.action.u.dls_teardown.reason_code = cpu_to_le16(reason);
-
- ieee80211_sta_tx(dev, skb, 0);
-}
-
-
static int ieee80211_privacy_mismatch(struct net_device *dev,
struct ieee80211_if_sta *ifsta)
{
struct ieee80211_sta_bss *bss;
int res = 0;
- if (!ifsta || ifsta->mixed_cell ||
- ifsta->key_mgmt != IEEE80211_KEY_MGMT_NONE)
+ if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL) ||
+ ifsta->key_management_enabled)
return 0;
bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
@@ -1185,22 +791,20 @@ static void ieee80211_associated(struct net_device *dev,
disassoc = 0;
if (time_after(jiffies,
sta->last_rx + IEEE80211_MONITORING_INTERVAL)) {
- if (ifsta->probereq_poll) {
+ if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) {
printk(KERN_DEBUG "%s: No ProbeResp from "
"current AP " MAC_FMT " - assume out of "
"range\n",
dev->name, MAC_ARG(ifsta->bssid));
disassoc = 1;
- sta_info_free(sta, 0);
- ifsta->probereq_poll = 0;
- } else {
+ sta_info_free(sta);
+ } else
ieee80211_send_probe_req(dev, ifsta->bssid,
local->scan_ssid,
local->scan_ssid_len);
- ifsta->probereq_poll = 1;
- }
+ ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL;
} else {
- ifsta->probereq_poll = 0;
+ ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
if (time_after(jiffies, ifsta->last_probe +
IEEE80211_PROBE_INTERVAL)) {
ifsta->last_probe = jiffies;
@@ -1280,10 +884,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
pos = skb_put(skb, 1);
supp_rates[1]++;
}
- if (mode->mode == MODE_ATHEROS_TURBO)
- *pos = rate->rate / 10;
- else
- *pos = rate->rate / 5;
+ *pos = rate->rate / 5;
}
ieee80211_sta_tx(dev, skb, 0);
@@ -1294,7 +895,7 @@ static int ieee80211_sta_wep_configured(struct net_device *dev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (!sdata || !sdata->default_key ||
- sdata->default_key->alg != ALG_WEP)
+ sdata->default_key->conf.alg != ALG_WEP)
return 0;
return 1;
}
@@ -1304,7 +905,7 @@ static void ieee80211_auth_completed(struct net_device *dev,
struct ieee80211_if_sta *ifsta)
{
printk(KERN_DEBUG "%s: authenticated\n", dev->name);
- ifsta->authenticated = 1;
+ ifsta->flags |= IEEE80211_STA_AUTHENTICATED;
ieee80211_associate(dev, ifsta);
}
@@ -1491,7 +1092,7 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
" (reason=%d)\n",
dev->name, MAC_ARG(mgmt->sa), reason_code);
- if (ifsta->authenticated) {
+ if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) {
printk(KERN_DEBUG "%s: deauthenticated\n", dev->name);
}
@@ -1504,7 +1105,7 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev,
}
ieee80211_set_disassoc(dev, ifsta, 1);
- ifsta->authenticated = 0;
+ ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED;
}
@@ -1536,7 +1137,7 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev,
" (reason=%d)\n",
dev->name, MAC_ARG(mgmt->sa), reason_code);
- if (ifsta->associated)
+ if (ifsta->flags & IEEE80211_STA_ASSOCIATED)
printk(KERN_DEBUG "%s: disassociated\n", dev->name);
if (ifsta->state == IEEE80211_ASSOCIATED) {
@@ -1605,8 +1206,10 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
if (status_code != WLAN_STATUS_SUCCESS) {
printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
dev->name, status_code);
- if (status_code == WLAN_STATUS_REASSOC_NO_ASSOC)
- ifsta->prev_bssid_set = 0;
+ /* if this was a reassociation, ensure we try a "full"
+ * association next time. This works around some broken APs
+ * which do not correctly reject reassociation requests. */
+ ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
return;
}
@@ -1624,13 +1227,25 @@ 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;
kfree(ifsta->assocresp_ies);
ifsta->assocresp_ies_len = len - (pos - (u8 *) mgmt);
- ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_ATOMIC);
+ ifsta->assocresp_ies = kmalloc(ifsta->assocresp_ies_len, GFP_KERNEL);
if (ifsta->assocresp_ies)
memcpy(ifsta->assocresp_ies, pos, ifsta->assocresp_ies_len);
@@ -1640,7 +1255,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
sta = sta_info_get(local, ifsta->bssid);
if (!sta) {
struct ieee80211_sta_bss *bss;
- sta = sta_info_add(local, dev, ifsta->bssid, GFP_ATOMIC);
+ sta = sta_info_add(local, dev, ifsta->bssid, GFP_KERNEL);
if (!sta) {
printk(KERN_DEBUG "%s: failed to add STA entry for the"
" AP\n", dev->name);
@@ -1656,46 +1271,27 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
}
sta->dev = dev;
- sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
- sta->assoc_ap = 1;
+ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP;
rates = 0;
mode = local->oper_hw_mode;
for (i = 0; i < elems.supp_rates_len; i++) {
int rate = (elems.supp_rates[i] & 0x7f) * 5;
- if (mode->mode == MODE_ATHEROS_TURBO)
- rate *= 2;
for (j = 0; j < mode->num_rates; j++)
if (mode->rates[j].rate == rate)
rates |= BIT(j);
}
for (i = 0; i < elems.ext_supp_rates_len; i++) {
int rate = (elems.ext_supp_rates[i] & 0x7f) * 5;
- if (mode->mode == MODE_ATHEROS_TURBO)
- rate *= 2;
for (j = 0; j < mode->num_rates; j++)
if (mode->rates[j].rate == rate)
rates |= BIT(j);
}
sta->supp_rates = rates;
- if (elems.ht_extra_param && elems.ht_cap_param && elems.wmm_param &&
- ifsta->ht_enabled && local->ops->conf_ht){
- int rc;
-
- rc = local->ops->conf_ht(local_to_hw(local),
- (struct ieee80211_ht_capability *)
- elems.ht_cap_param,
- (struct ieee80211_ht_additional_info *)
- elems.ht_extra_param);
- if (!rc)
- sta->flags |= WLAN_STA_HT;
- }
-
-
rate_control_rate_init(sta, local);
- if (elems.wmm_param && ifsta->wmm_enabled) {
+ if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
sta->flags |= WLAN_STA_WME;
ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
elems.wmm_param_len);
@@ -1707,258 +1303,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
ieee80211_associated(dev, ifsta);
}
-static u32 calculate_mpdu_exchange_time(struct ieee80211_local *local,
- struct ieee80211_elem_tspec *tspec)
-{
- /*
- * FIXME: MPDUExchangeTime = duration(Nominal MSDU Size, Min PHY Rate) +
- * SIFS + ACK duration
- */
- int extra = 0; /* SIFS + ACK */
-
- switch (local->hw.conf.phymode) {
- case MODE_IEEE80211A:
- extra = 16 + 24;
- break;
- case MODE_IEEE80211B:
- extra = 10 + 203;
- break;
- case MODE_IEEE80211G:
- default:
- extra = 10 + 30;
- break;
- }
- return (tspec->nominal_msdu_size * 8) /
- (tspec->min_phy_rate / 1000000) + extra;
-}
-
-static void sta_update_tspec(struct ieee80211_local *local,
- struct ieee80211_if_sta *ifsta,
- int action, struct ieee80211_elem_tspec *tspec)
-{
- u8 tsid = IEEE80211_TSINFO_TSID(tspec->ts_info);
- u8 index = ieee80211_ts_index(IEEE80211_TSINFO_DIR(tspec->ts_info));
-
- switch (action) {
- case WLAN_ACTION_QOS_ADDTS_RESP:
- ifsta->ts_data[tsid][index].status = TS_STATUS_ACTIVE;
- ifsta->ts_data[tsid][index].up =
- IEEE80211_TSINFO_UP(tspec->ts_info);
- ifsta->ts_data[tsid][index].used_time_usec = 0;
- ifsta->ts_data[tsid][index].admitted_time_usec +=
- ifsta->dot11EDCAAveragingPeriod * tspec->medium_time * 32;
- ifsta->MPDUExchangeTime =
- calculate_mpdu_exchange_time(local, tspec);
- break;
- case WLAN_ACTION_QOS_DELTS:
- ifsta->ts_data[tsid][index].status = TS_STATUS_INACTIVE;
- ifsta->ts_data[tsid][index].used_time_usec = 0;
- ifsta->ts_data[tsid][index].admitted_time_usec -=
- ifsta->dot11EDCAAveragingPeriod * tspec->medium_time * 32;
- if (ifsta->ts_data[tsid][index].admitted_time_usec < 0)
- ifsta->ts_data[tsid][index].admitted_time_usec = 0;
- ifsta->MPDUExchangeTime = 0;
- break;
- default:
- printk(KERN_ERR "%s: invalid action type %d\n", __FUNCTION__,
- action);
- break;
- }
-}
-
-static void sta_parse_tspec(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_mgmt *mgmt, size_t len, u8 prefix,
- struct ieee80211_elem_tspec *tspec)
-{
- struct ieee802_11_elems elems;
- u8 *pos;
-
- /*
- printk(KERN_DEBUG "Dialog_token: %d, TID: %u, Direction: %u, PSB: %d, "
- "UP: %d\n", mgmt->u.action.u.wme_action.dialog_token,
- IEEE80211_TSINFO_TSID(tspec->ts_info),
- IEEE80211_TSINFO_DIR(tspec->ts_info),
- IEEE80211_TSINFO_APSD(tspec->ts_info),
- IEEE80211_TSINFO_UP(tspec->ts_info));
- */
-
- if (mgmt->u.action.category == WLAN_CATEGORY_QOS)
- pos = mgmt->u.action.u.addts_resp.variable + prefix;
- else
- pos = mgmt->u.action.u.wme_action.variable + prefix;
-
- if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
- == ParseFailed) {
- printk(KERN_DEBUG "%s: failed to parse TSPEC\n", dev->name);
- return;
- }
- memcpy(tspec, elems.tspec, sizeof(*tspec));
-}
-
-int dls_link_status(struct ieee80211_local *local, u8 *addr)
-{
- struct sta_info *dls;
- int ret = DLS_STATUS_NOLINK;
-
- if ((dls = dls_info_get(local, addr)) != NULL) {
- ret = dls->dls_status;
- sta_info_put(dls);
- }
- return ret;
-}
-
-static void sta_process_dls_req(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_mgmt *mgmt, size_t len)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *dls;
- u8 *src = mgmt->u.action.u.dls_req.src;
- struct ieee802_11_elems elems;
- struct ieee80211_rate *rates;
- size_t baselen, num_rates;
- int i, j;
- struct ieee80211_hw_mode *mode;
- u32 supp_rates = 0;
-
- printk(KERN_DEBUG "Receive DLS request from "
- "%02X:%02X:%02X:%02X:%02X:%02X\n",
- src[0], src[1], src[2], src[3], src[4], src[5]);
-
- baselen = (u8 *)mgmt->u.action.u.dls_req.variable - (u8 *)mgmt;
- if (baselen > len)
- return;
-
- if (ieee802_11_parse_elems(mgmt->u.action.u.dls_req.variable,
- len - baselen, &elems) == ParseFailed) {
- printk(KERN_ERR "DLS Parse support rates failed.\n");
- return;
- }
- mode = local->sta_scanning ?
- local->scan_hw_mode : local->oper_hw_mode;
- rates = mode->rates;
- num_rates = mode->num_rates;
-
- for (i = 0; i < elems.supp_rates_len + elems.ext_supp_rates_len; i++) {
- u8 rate = 0;
- if (i < elems.supp_rates_len)
- rate = elems.supp_rates[i];
- else if (elems.ext_supp_rates)
- rate = elems.ext_supp_rates[i - elems.supp_rates_len];
- rate = 5 * (rate & 0x7f);
- if (mode->mode == MODE_ATHEROS_TURBO)
- rate *= 2;
- for (j = 0; j < num_rates; j++)
- if (rates[j].rate == rate)
- supp_rates |= BIT(j);
- }
- if (supp_rates == 0) {
- /* Send DLS failed Response to the peer because
- * the supported rates are mismatch */
- ieee80211_send_dls_resp(dev, ifsta, src,
- WLAN_REASON_QSTA_NOT_USE);
- return;
- }
-
- dls = dls_info_get(local, src);
- if (!dls)
- dls = sta_info_add(local, dev, src, GFP_ATOMIC);
- if (!dls)
- return;
-
- dls->dls_status = DLS_STATUS_OK;
- dls->dls_timeout = le16_to_cpu(mgmt->u.action.u.dls_req.timeout);
- dls->supp_rates = supp_rates;
-
- /* Send DLS successful Response to the peer */
- ieee80211_send_dls_resp(dev, ifsta, src, 0);
-}
-
-
-static void sta_process_dls_resp(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_mgmt *mgmt, size_t len)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sta_info *dls;
- u8 *src = mgmt->u.action.u.dls_resp.src;
- struct ieee802_11_elems elems;
- struct ieee80211_rate *rates;
- size_t baselen, num_rates;
- int i, j;
- struct ieee80211_hw_mode *mode;
- u32 supp_rates = 0;
-
- printk(KERN_DEBUG "Receive DLS response from "
- "%02X:%02X:%02X:%02X:%02X:%02X\n",
- src[0], src[1], src[2], src[3], src[4], src[5]);
-
- if (mgmt->u.action.u.dls_resp.status_code) {
- printk(KERN_ERR "DLS setup refused by peer. Reason %d\n",
- mgmt->u.action.u.dls_resp.status_code);
- return;
- }
-
- baselen = (u8 *)mgmt->u.action.u.dls_resp.variable - (u8 *)mgmt;
- if (baselen > len)
- return;
-
- if (ieee802_11_parse_elems(mgmt->u.action.u.dls_resp.variable,
- len - baselen, &elems) == ParseFailed) {
- printk(KERN_ERR "DLS Parse support rates failed.\n");
- return;
- }
- mode = local->sta_scanning ?
- local->scan_hw_mode : local->oper_hw_mode;
- rates = mode->rates;
- num_rates = mode->num_rates;
-
- for (i = 0; i < elems.supp_rates_len + elems.ext_supp_rates_len; i++) {
- u8 rate = 0;
- if (i < elems.supp_rates_len)
- rate = elems.supp_rates[i];
- else if (elems.ext_supp_rates)
- rate = elems.ext_supp_rates[i - elems.supp_rates_len];
- rate = 5 * (rate & 0x7f);
- if (mode->mode == MODE_ATHEROS_TURBO)
- rate *= 2;
- for (j = 0; j < num_rates; j++)
- if (rates[j].rate == rate)
- supp_rates |= BIT(j);
- }
-
- dls = dls_info_get(local, src);
- if (!dls)
- dls = sta_info_add(local, dev, src, GFP_ATOMIC);
- if (!dls)
- return;
-
- dls->supp_rates = supp_rates;
- dls->dls_status = DLS_STATUS_OK;
- sta_info_put(dls);
-}
-
-
-static void sta_process_dls_teardown(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_mgmt *mgmt, size_t len)
-{
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- u8 *src = mgmt->u.action.u.dls_teardown.src;
- struct sta_info *dls;
-
- printk(KERN_DEBUG "DLS Teardown received from "
- "%02X:%02X:%02X:%02X:%02X:%02X. Reason %d\n",
- src[0], src[1], src[2], src[3], src[4], src[5],
- mgmt->u.action.u.dls_teardown.reason_code);
-
- dls = dls_info_get(local, src);
- if (dls)
- sta_info_free(dls, 0);
- return;
-}
-
/* Caller must hold local->sta_bss_lock */
static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
@@ -1998,10 +1342,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);
@@ -2040,7 +1383,6 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
kfree(bss->wpa_ie);
kfree(bss->rsn_ie);
kfree(bss->wmm_ie);
- kfree(bss->ht_ie);
kfree(bss);
}
@@ -2160,8 +1502,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
rate = elems.ext_supp_rates
[i - elems.supp_rates_len];
own_rate = 5 * (rate & 0x7f);
- if (mode->mode == MODE_ATHEROS_TURBO)
- own_rate *= 2;
for (j = 0; j < num_rates; j++)
if (rates[j].rate == own_rate)
supp_rates |= BIT(j);
@@ -2213,6 +1553,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) {
@@ -2287,23 +1633,6 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
bss->wmm_ie_len = 0;
}
- if (elems.ht_cap_param &&
- (!bss->ht_ie || bss->ht_ie_len != elems.ht_cap_param_len ||
- memcmp(bss->ht_ie, elems.ht_cap_param, elems.ht_cap_param_len))) {
- if (bss->ht_ie)
- kfree(bss->ht_ie);
- bss->ht_ie = kmalloc(elems.ht_cap_param_len + 2, GFP_ATOMIC);
- if (bss->ht_ie) {
- memcpy(bss->ht_ie, elems.ht_cap_param - 2,
- elems.ht_cap_param_len + 2);
- bss->ht_ie_len = elems.ht_cap_param_len + 2;
- } else
- bss->ht_ie_len = 0;
- } else if (!elems.ht_cap_param && bss->ht_ie) {
- kfree(bss->ht_ie);
- bss->ht_ie = NULL;
- bss->ht_ie_len = 0;
- }
bss->hw_mode = rx_status->phymode;
bss->channel = channel;
@@ -2345,10 +1674,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;
@@ -2359,7 +1686,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
return;
ifsta = &sdata->u.sta;
- if (!ifsta->associated ||
+ if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED) ||
memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0)
return;
@@ -2372,25 +1699,10 @@ 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) {
+ if (elems.wmm_param && (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) {
ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,
elems.wmm_param_len);
}
@@ -2453,7 +1765,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
}
/* Reply with ProbeResp */
- skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC);
+ skb = skb_copy(ifsta->probe_resp, GFP_KERNEL);
if (!skb)
return;
@@ -2466,172 +1778,6 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev,
ieee80211_sta_tx(dev, skb, 0);
}
-static void ieee80211_send_addba_resp(struct net_device *dev,
- struct ieee80211_mgmt *mgmt_src,
- size_t len,
- u16 status)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_if_sta *ifsta = &sdata->u.sta;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
-
- skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
- if (!skb) {
- printk(KERN_DEBUG "%s: failed to allocate buffer "
- "for addba resp frame\n", dev->name);
- return;
- }
-
- skb_reserve(skb, local->hw.extra_tx_headroom);
- mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
- memset(mgmt, 0, 24);
- memcpy(mgmt->da, ifsta->bssid, ETH_ALEN);
- memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
- mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
- IEEE80211_STYPE_ACTION);
-
- skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp));
- mgmt->u.action.category = WLAN_CATEGORY_BACK;
- mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP;
- mgmt->u.action.u.addba_resp.dialog_token =
- mgmt_src->u.action.u.addba_req.dialog_token;
- mgmt->u.action.u.addba_resp.capab =
- mgmt_src->u.action.u.addba_req.capab;
- mgmt->u.action.u.addba_resp.timeout =
- mgmt_src->u.action.u.addba_req.timeout;
- mgmt->u.action.u.addba_resp.status = cpu_to_le16(status);
-
- ieee80211_sta_tx(dev, skb, 0);
-
- return;
-}
-
-static void ieee80211_rx_mgmt_action(struct net_device *dev,
- struct ieee80211_if_sta *ifsta,
- struct ieee80211_mgmt *mgmt,
- size_t len)
-{
- u8 prefix = 0;
- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct ieee80211_elem_tspec tspec;
-
- if (len < IEEE80211_MIN_ACTION_SIZE)
- return;
-
- switch (mgmt->u.action.category) {
- case WLAN_CATEGORY_QOS:
- case WLAN_CATEGORY_WMM:
- if (len < 24 + 4) {
- printk(KERN_DEBUG "%s: too short (%zd) QoS category "
- "frame received from " MAC_FMT " - ignored\n",
- dev->name, len, MAC_ARG(mgmt->sa));
- return;
- }
- switch (mgmt->u.action.u.wme_action.action_code) {
- case WLAN_ACTION_QOS_ADDTS_REQ:
- printk(KERN_DEBUG "%s: WLAN_ACTION_QOS_ADDTS_REQ "
- "received in Non-AP STA mode!\n", dev->name);
- return;
- case WLAN_ACTION_QOS_ADDTS_RESP:
- if (mgmt->u.action.u.wme_action.status_code == 47) {
- /* TODO: handle TS Delay */
- prefix = 6;
- }
- /* TODO: handle TCLAS, TCLAS Porcessing here */
-
- if (mgmt->u.action.u.wme_action.status_code == 0) {
- /* TODO: handle Schedule */
- sta_parse_tspec(dev, ifsta, mgmt, len,
- prefix, &tspec);
- sta_update_tspec(local, ifsta,
- WLAN_ACTION_QOS_ADDTS_RESP,
- &tspec);
- mod_timer(&ifsta->admit_timer, jiffies +
- ifsta->dot11EDCAAveragingPeriod * HZ);
- }
- break;
- case WLAN_ACTION_QOS_DELTS:
- sta_parse_tspec(dev, ifsta, mgmt, len, prefix, &tspec);
- sta_update_tspec(local, ifsta,
- WLAN_ACTION_QOS_DELTS, &tspec);
- break;
- default:
- printk(KERN_ERR "%s: unsupported QoS action code %d\n",
- dev->name,
- mgmt->u.action.u.wme_action.action_code);
- break;
- }
- break;
-
- case WLAN_CATEGORY_DLS:
- if (len < 24 + 16) {
- printk(KERN_DEBUG "%s: too short (%zd) DLS category "
- "frame received from " MAC_FMT " - ignored\n",
- dev->name, len, MAC_ARG(mgmt->sa));
- return;
- }
- switch (mgmt->u.action.u.dls_req.action_code) {
- case WLAN_ACTION_DLS_REQ:
- sta_process_dls_req(dev, ifsta, mgmt, len);
- break;
- case WLAN_ACTION_DLS_RESP:
- sta_process_dls_resp(dev, ifsta, mgmt, len);
- break;
- case WLAN_ACTION_DLS_TEARDOWN:
- sta_process_dls_teardown(dev, ifsta, mgmt, len);
- break;
- default:
- printk(KERN_ERR "%s: unsupported DLS action code %d\n",
- dev->name, mgmt->u.action.u.dls_req.action_code);
- break;
- }
- break;
-
- case WLAN_CATEGORY_BACK:
- switch (mgmt->u.action.u.addba_req.action_code) {
- case WLAN_ACTION_ADDBA_REQ:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.addba_req)))
- break;
- if (!local->ops->handle_ba_action ||
- (local->ops->handle_ba_action(local_to_hw(local),
- mgmt)))
- ieee80211_send_addba_resp(dev, mgmt, len,
- WLAN_STATUS_REQUEST_DECLINED);
- else
- ieee80211_send_addba_resp(dev, mgmt, len,
- WLAN_STATUS_SUCCESS);
- break;
- case WLAN_ACTION_ADDBA_RESP:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.addba_resp)))
- break;
- if (!local->ops->handle_ba_action)
- break;
- local->ops->handle_ba_action(local_to_hw(local), mgmt);
- break;
- case WLAN_ACTION_DELBA:
- if (len < (IEEE80211_MIN_ACTION_SIZE +
- sizeof(mgmt->u.action.u.delba)))
- break;
-
- if (!local->ops->handle_ba_action)
- break;
-
- local->ops->handle_ba_action(local_to_hw(local), mgmt);
- break;
- default:
- break;
- }
- break;
-
- default:
- break;
- }
-}
void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status)
@@ -2661,7 +1807,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb,
case IEEE80211_STYPE_REASSOC_RESP:
case IEEE80211_STYPE_DEAUTH:
case IEEE80211_STYPE_DISASSOC:
- case IEEE80211_STYPE_ACTION:
skb_queue_tail(&ifsta->skb_queue, skb);
queue_work(local->hw.workqueue, &ifsta->work);
return;
@@ -2719,9 +1864,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev,
case IEEE80211_STYPE_DISASSOC:
ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len);
break;
- case IEEE80211_STYPE_ACTION:
- ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len);
- break;
}
kfree_skb(skb);
@@ -2762,7 +1904,7 @@ static int ieee80211_sta_active_ibss(struct net_device *dev)
int active = 0;
struct sta_info *sta;
- spin_lock_bh(&local->sta_lock);
+ read_lock_bh(&local->sta_lock);
list_for_each_entry(sta, &local->sta_list, list) {
if (sta->dev == dev &&
time_after(sta->last_rx + IEEE80211_IBSS_MERGE_INTERVAL,
@@ -2771,7 +1913,7 @@ static int ieee80211_sta_active_ibss(struct net_device *dev)
break;
}
}
- spin_unlock_bh(&local->sta_lock);
+ read_unlock_bh(&local->sta_lock);
return active;
}
@@ -2781,16 +1923,24 @@ static void ieee80211_sta_expire(struct net_device *dev)
{
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
struct sta_info *sta, *tmp;
+ LIST_HEAD(tmp_list);
- spin_lock_bh(&local->sta_lock);
+ write_lock_bh(&local->sta_lock);
list_for_each_entry_safe(sta, tmp, &local->sta_list, list)
if (time_after(jiffies, sta->last_rx +
IEEE80211_IBSS_INACTIVITY_LIMIT)) {
printk(KERN_DEBUG "%s: expiring inactive STA " MAC_FMT
"\n", dev->name, MAC_ARG(sta->addr));
- sta_info_free(sta, 1);
+ __sta_info_get(sta);
+ sta_info_remove(sta);
+ list_add(&sta->list, &tmp_list);
}
- spin_unlock_bh(&local->sta_lock);
+ write_unlock_bh(&local->sta_lock);
+
+ list_for_each_entry_safe(sta, tmp, &tmp_list, list) {
+ sta_info_free(sta);
+ sta_info_put(sta);
+ }
}
@@ -2895,43 +2045,6 @@ void ieee80211_sta_work(struct work_struct *work)
}
-void ieee80211_admit_refresh(unsigned long ptr)
-{
- struct net_device *dev;
- struct ieee80211_sub_if_data *sdata;
- struct ieee80211_if_sta *ifsta;
- int i, j, find = 0;
-
- dev = (struct net_device *) ptr;
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- ifsta = &sdata->u.sta;
-
- for (i = 0; i < STA_TSID_NUM; i++) {
- for (j = 0; j < STA_TSDIR_NUM; j++) {
- if ((ifsta->ts_data[i][j].status != TS_STATUS_ACTIVE) &&
- (ifsta->ts_data[i][j].status != TS_STATUS_THROTTLING))
- continue;
- find = 1;
-
- ifsta->ts_data[i][j].used_time_usec -=
- ifsta->ts_data[i][j].admitted_time_usec;
- if ((s32)(ifsta->ts_data[i][j].used_time_usec) < 0)
- ifsta->ts_data[i][j].used_time_usec = 0;
-
- ifsta->ts_data[i][j].status =
- (ifsta->ts_data[i][j].used_time_usec >=
- ifsta->ts_data[i][j].admitted_time_usec) ?
- TS_STATUS_THROTTLING :
- TS_STATUS_ACTIVE;
- }
- }
-
- if (find)
- mod_timer(&ifsta->admit_timer, jiffies +
- ifsta->dot11EDCAAveragingPeriod * HZ);
-}
-
-
static void ieee80211_sta_reset_auth(struct net_device *dev,
struct ieee80211_if_sta *ifsta)
{
@@ -2956,7 +2069,8 @@ static void ieee80211_sta_reset_auth(struct net_device *dev,
printk(KERN_DEBUG "%s: Initial auth_alg=%d\n", dev->name,
ifsta->auth_alg);
ifsta->auth_transaction = -1;
- ifsta->associated = ifsta->auth_tries = ifsta->assoc_tries = 0;
+ ifsta->flags &= ~IEEE80211_STA_ASSOCIATED;
+ ifsta->auth_tries = ifsta->assoc_tries = 0;
netif_carrier_off(dev);
}
@@ -2970,8 +2084,10 @@ void ieee80211_sta_req_auth(struct net_device *dev,
if (sdata->type != IEEE80211_IF_TYPE_STA)
return;
- if ((ifsta->bssid_set || ifsta->auto_bssid_sel) &&
- (ifsta->ssid_set || ifsta->auto_ssid_sel)) {
+ if ((ifsta->flags & (IEEE80211_STA_BSSID_SET |
+ IEEE80211_STA_AUTO_BSSID_SEL)) &&
+ (ifsta->flags & (IEEE80211_STA_SSID_SET |
+ IEEE80211_STA_AUTO_SSID_SEL))) {
set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
queue_work(local->hw.workqueue, &ifsta->work);
}
@@ -2985,7 +2101,7 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
if (!memcmp(ifsta->ssid, ssid, ssid_len))
return 1;
- if (ifsta->auto_bssid_sel)
+ if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
return 0;
hidden_ssid = 1;
@@ -3014,12 +2130,9 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
struct ieee80211_sta_bss *bss, *selected = NULL;
int top_rssi = 0, freq;
- rtnl_lock();
-
- if (!ifsta->auto_channel_sel && !ifsta->auto_bssid_sel &&
- !ifsta->auto_ssid_sel) {
+ if (!(ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
+ IEEE80211_STA_AUTO_BSSID_SEL | IEEE80211_STA_AUTO_CHANNEL_SEL))) {
ifsta->state = IEEE80211_AUTHENTICATE;
- rtnl_unlock();
ieee80211_sta_reset_auth(dev, ifsta);
return 0;
}
@@ -3034,14 +2147,15 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
!!sdata->default_key)
continue;
- if (!ifsta->auto_channel_sel && bss->freq != freq)
+ if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
+ bss->freq != freq)
continue;
- if (!ifsta->auto_bssid_sel &&
+ if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
continue;
- if (!ifsta->auto_ssid_sel &&
+ if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
!ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
continue;
@@ -3056,24 +2170,26 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
if (selected) {
ieee80211_set_channel(local, -1, selected->freq);
- if (!ifsta->ssid_set)
+ if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
ieee80211_sta_set_ssid(dev, selected->ssid,
selected->ssid_len);
ieee80211_sta_set_bssid(dev, selected->bssid);
ieee80211_rx_bss_put(dev, selected);
ifsta->state = IEEE80211_AUTHENTICATE;
- rtnl_unlock();
ieee80211_sta_reset_auth(dev, ifsta);
return 0;
} else {
if (ifsta->state != IEEE80211_AUTHENTICATE) {
- ieee80211_sta_start_scan(dev, NULL, 0);
+ if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL)
+ ieee80211_sta_start_scan(dev, NULL, 0);
+ else
+ ieee80211_sta_start_scan(dev, ifsta->ssid,
+ ifsta->ssid_len);
ifsta->state = IEEE80211_AUTHENTICATE;
set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request);
} else
ifsta->state = IEEE80211_DISABLED;
}
- rtnl_unlock();
return -1;
}
@@ -3181,8 +2297,9 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
"for IBSS beacon\n", dev->name);
break;
}
- control.tx_rate = (local->short_preamble &&
- (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
+ control.tx_rate =
+ ((sdata->flags & IEEE80211_SDATA_SHORT_PREAMBLE) &&
+ (rate->flags & IEEE80211_RATE_PREAMBLE2)) ?
rate->val2 : rate->val;
control.antenna_sel_tx = local->hw.conf.antenna_sel_tx;
control.power_level = local->hw.conf.power_level;
@@ -3213,8 +2330,6 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
mode = local->oper_hw_mode;
for (i = 0; i < bss->supp_rates_len; i++) {
int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
- if (mode->mode == MODE_ATHEROS_TURBO)
- bitrate *= 2;
for (j = 0; j < mode->num_rates; j++)
if (mode->rates[j].rate == bitrate)
rates |= BIT(j);
@@ -3287,8 +2402,6 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
pos = bss->supp_rates;
for (i = 0; i < mode->num_rates; i++) {
int rate = mode->rates[i].rate;
- if (mode->mode == MODE_ATHEROS_TURBO)
- rate /= 2;
*pos++ = (u8) (rate / 5);
}
@@ -3361,10 +2474,10 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
if (time_after(jiffies, ifsta->ibss_join_req +
IEEE80211_IBSS_JOIN_TIMEOUT)) {
- if (ifsta->create_ibss &&
+ if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) &&
local->oper_channel->flag & IEEE80211_CHAN_W_IBSS)
return ieee80211_sta_create_ibss(dev, ifsta);
- if (ifsta->create_ibss) {
+ if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) {
printk(KERN_DEBUG "%s: IBSS not allowed on the"
" configured channel %d (%d MHz)\n",
dev->name, local->hw.conf.channel,
@@ -3425,13 +2538,17 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
ifsta = &sdata->u.sta;
if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
- ifsta->prev_bssid_set = 0;
+ ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
memcpy(ifsta->ssid, ssid, len);
memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
ifsta->ssid_len = len;
- ifsta->ssid_set = len ? 1 : 0;
- if (sdata->type == IEEE80211_IF_TYPE_IBSS && !ifsta->bssid_set) {
+ if (len)
+ ifsta->flags |= IEEE80211_STA_SSID_SET;
+ else
+ ifsta->flags &= ~IEEE80211_STA_SSID_SET;
+ if (sdata->type == IEEE80211_IF_TYPE_IBSS &&
+ !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
ifsta->ibss_join_req = jiffies;
ifsta->state = IEEE80211_IBSS_SEARCH;
return ieee80211_sta_find_ibss(dev, ifsta);
@@ -3469,10 +2586,11 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
}
}
- if (!is_valid_ether_addr(bssid))
- ifsta->bssid_set = 0;
+ if (is_valid_ether_addr(bssid))
+ ifsta->flags |= IEEE80211_STA_BSSID_SET;
else
- ifsta->bssid_set = 1;
+ ifsta->flags &= ~IEEE80211_STA_BSSID_SET;
+
return 0;
}
@@ -3523,35 +2641,41 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
printk(KERN_DEBUG "%s: failed to restore operational"
"channel after scan\n", dev->name);
- if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) &&
- ieee80211_if_config(dev))
- printk(KERN_DEBUG "%s: failed to restore operational"
- "BSSID after scan\n", dev->name);
+
+ netif_tx_lock_bh(local->mdev);
+ local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC;
+ local->ops->configure_filter(local_to_hw(local),
+ FIF_BCN_PRBRESP_PROMISC,
+ &local->filter_flags,
+ local->mdev->mc_count,
+ local->mdev->mc_list);
+
+ netif_tx_unlock_bh(local->mdev);
memset(&wrqu, 0, sizeof(wrqu));
wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
- read_lock(&local->sub_if_lock);
- list_for_each_entry(sdata, &local->sub_if_list, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, 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)
+ if (sdata->u.sta.flags & IEEE80211_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);
+ rcu_read_unlock();
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
if (sdata->type == IEEE80211_IF_TYPE_IBSS) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
- if (!ifsta->bssid_set ||
+ if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
(!ifsta->state == IEEE80211_IBSS_JOINED &&
!ieee80211_sta_active_ibss(dev)))
ieee80211_sta_find_ibss(dev, ifsta);
@@ -3683,8 +2807,8 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
local->sta_scanning = 1;
- read_lock(&local->sub_if_lock);
- list_for_each_entry(sdata, &local->sub_if_list, list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &local->interfaces, list) {
/* Don't stop the master interface, otherwise we can't transmit
* probes! */
@@ -3693,10 +2817,10 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
netif_stop_queue(sdata->dev);
if (sdata->type == IEEE80211_IF_TYPE_STA &&
- sdata->u.sta.associated)
+ (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
ieee80211_send_nullfunc(local, sdata, 1);
}
- read_unlock(&local->sub_if_lock);
+ rcu_read_unlock();
if (ssid) {
local->scan_ssid_len = ssid_len;
@@ -3710,10 +2834,14 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
local->scan_channel_idx = 0;
local->scan_dev = dev;
- if (!(local->hw.flags & IEEE80211_HW_NO_PROBE_FILTERING) &&
- ieee80211_if_config(dev))
- printk(KERN_DEBUG "%s: failed to set BSSID for scan\n",
- dev->name);
+ netif_tx_lock_bh(local->mdev);
+ local->filter_flags |= FIF_BCN_PRBRESP_PROMISC;
+ local->ops->configure_filter(local_to_hw(local),
+ FIF_BCN_PRBRESP_PROMISC,
+ &local->filter_flags,
+ local->mdev->mc_count,
+ local->mdev->mc_list);
+ netif_tx_unlock_bh(local->mdev);
/* TODO: start scan as soon as all nullfunc frames are ACKed */
queue_delayed_work(local->hw.workqueue, &local->scan_work,
@@ -3963,7 +3091,7 @@ struct sta_info * ieee80211_ibss_add_sta(struct net_device *dev,
}
printk(KERN_DEBUG "%s: Adding new IBSS station " MAC_FMT " (dev=%s)\n",
- local->mdev->name, MAC_ARG(addr), dev->name);
+ wiphy_name(local->hw.wiphy), MAC_ARG(addr), dev->name);
sta = sta_info_add(local, dev, addr, GFP_ATOMIC);
if (!sta)
@@ -4006,7 +3134,7 @@ int ieee80211_sta_disassociate(struct net_device *dev, u16 reason)
if (sdata->type != IEEE80211_IF_TYPE_STA)
return -EINVAL;
- if (!ifsta->associated)
+ if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED))
return -1;
ieee80211_send_disassoc(dev, ifsta, reason);