mlme.c 63.3 KB
Newer Older
1 2
/*
 * BSS client mode implementation
3
 * Copyright 2003-2008, Jouni Malinen <j@w1.fi>
4 5 6 7 8 9 10 11 12 13
 * Copyright 2004, Instant802 Networks, Inc.
 * Copyright 2005, Devicescape Software, Inc.
 * Copyright 2006-2007	Jiri Benc <jbenc@suse.cz>
 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

14
#include <linux/delay.h>
15 16 17 18
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
19
#include <linux/rtnetlink.h>
20
#include <linux/pm_qos_params.h>
21
#include <linux/crc32.h>
22
#include <net/mac80211.h>
23
#include <asm/unaligned.h>
Johannes Berg's avatar
Johannes Berg committed
24

25
#include "ieee80211_i.h"
26
#include "driver-ops.h"
Johannes Berg's avatar
Johannes Berg committed
27 28
#include "rate.h"
#include "led.h"
29

30
#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2
31 32 33 34 35
#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_MAX_TRIES 3
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_MAX_TRIES 3
#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
36
#define IEEE80211_PROBE_WAIT (HZ / 5)
37
#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
38 39
#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)

40 41 42
#define TMR_RUNNING_TIMER	0
#define TMR_RUNNING_CHANSW	1

43 44
/* utils */
static int ecw2cw(int ecw)
Johannes Berg's avatar
Johannes Berg committed
45
{
46
	return (1 << ecw) - 1;
Johannes Berg's avatar
Johannes Berg committed
47 48
}

49
static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
50
				      struct ieee80211_supported_band *sband,
51
				      u32 *rates)
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
{
	int i, j, count;
	*rates = 0;
	count = 0;
	for (i = 0; i < bss->supp_rates_len; i++) {
		int rate = (bss->supp_rates[i] & 0x7F) * 5;

		for (j = 0; j < sband->n_bitrates; j++)
			if (sband->bitrates[j].bitrate == rate) {
				*rates |= BIT(j);
				count++;
				break;
			}
	}

	return count;
}

70 71 72 73 74 75 76 77 78 79 80 81 82 83
/*
 * ieee80211_enable_ht should be called only after the operating band
 * has been determined as ht configuration depends on the hw's
 * HT abilities for a specific band.
 */
static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
			       struct ieee80211_ht_info *hti,
			       u16 ap_ht_cap_flags)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_supported_band *sband;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct sta_info *sta;
	u32 changed = 0;
84
	u16 ht_opmode;
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
	bool enable_ht = true, ht_changed;
	enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;

	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

	/* HT is not supported */
	if (!sband->ht_cap.ht_supported)
		enable_ht = false;

	/* check that channel matches the right operating channel */
	if (local->hw.conf.channel->center_freq !=
	    ieee80211_channel_to_frequency(hti->control_chan))
		enable_ht = false;

	if (enable_ht) {
		channel_type = NL80211_CHAN_HT20;

		if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
		    (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
		    (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
			switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
			case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
107 108 109
				if (!(local->hw.conf.channel->flags &
				    IEEE80211_CHAN_NO_HT40PLUS))
					channel_type = NL80211_CHAN_HT40PLUS;
110 111
				break;
			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
112 113 114
				if (!(local->hw.conf.channel->flags &
				    IEEE80211_CHAN_NO_HT40MINUS))
					channel_type = NL80211_CHAN_HT40MINUS;
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
				break;
			}
		}
	}

	ht_changed = conf_is_ht(&local->hw.conf) != enable_ht ||
		     channel_type != local->hw.conf.channel_type;

	local->oper_channel_type = channel_type;

	if (ht_changed) {
                /* channel_type change automatically detected */
		ieee80211_hw_config(local, 0);

		rcu_read_lock();

		sta = sta_info_get(local, ifmgd->bssid);
		if (sta)
			rate_control_rate_update(local, sband, sta,
						 IEEE80211_RC_HT_CHANGED);

		rcu_read_unlock();
        }

	/* disable HT */
	if (!enable_ht)
		return 0;

143
	ht_opmode = le16_to_cpu(hti->operation_mode);
144 145

	/* if bss configuration changed store the new one */
146 147
	if (!sdata->ht_opmode_valid ||
	    sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
148
		changed |= BSS_CHANGED_HT;
149
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
150
		sdata->ht_opmode_valid = true;
151 152 153 154 155
	}

	return changed;
}

156 157
/* frame sending functions */

158
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
159
{
160
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
161 162 163
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
164 165
	u8 *pos;
	const u8 *ies, *ht_ie;
166 167
	int i, len, count, rates_len, supp_rates_len;
	u16 capab;
168
	struct ieee80211_bss *bss;
169 170
	int wmm = 0;
	struct ieee80211_supported_band *sband;
171
	u32 rates = 0;
172 173

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
174
			    sizeof(*mgmt) + 200 + ifmgd->extra_ie_len +
175
			    ifmgd->ssid_len);
176 177 178 179 180 181 182 183 184
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for assoc "
		       "frame\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];

185
	capab = ifmgd->capab;
186 187 188 189 190 191 192 193

	if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) {
		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
			capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
		if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
			capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
	}

194
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
195
				   local->hw.conf.channel->center_freq,
196
				   ifmgd->ssid, ifmgd->ssid_len);
197
	if (bss) {
198
		if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
199 200 201 202 203 204 205 206 207 208
			capab |= WLAN_CAPABILITY_PRIVACY;
		if (bss->wmm_used)
			wmm = 1;

		/* get all rates supported by the device and the AP as
		 * some APs don't like getting a superset of their rates
		 * in the association request (e.g. D-Link DAP 1353 in
		 * b-only mode) */
		rates_len = ieee80211_compatible_rates(bss, sband, &rates);

209
		if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
210 211 212 213 214 215 216 217 218 219 220
		    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
			capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;

		ieee80211_rx_bss_put(local, bss);
	} else {
		rates = ~0;
		rates_len = sband->n_bitrates;
	}

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
221
	memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN);
222
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
223
	memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN);
224

225
	if (ifmgd->flags & IEEE80211_STA_PREV_BSSID_SET) {
226 227 228 229 230 231
		skb_put(skb, 10);
		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						  IEEE80211_STYPE_REASSOC_REQ);
		mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
		mgmt->u.reassoc_req.listen_interval =
				cpu_to_le16(local->hw.conf.listen_interval);
232
		memcpy(mgmt->u.reassoc_req.current_ap, ifmgd->prev_bssid,
233 234 235 236 237 238
		       ETH_ALEN);
	} else {
		skb_put(skb, 4);
		mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
						  IEEE80211_STYPE_ASSOC_REQ);
		mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
239
		mgmt->u.assoc_req.listen_interval =
240 241 242 243
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
244
	ies = pos = skb_put(skb, 2 + ifmgd->ssid_len);
245
	*pos++ = WLAN_EID_SSID;
246 247
	*pos++ = ifmgd->ssid_len;
	memcpy(pos, ifmgd->ssid, ifmgd->ssid_len);
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301

	/* add all rates which were marked to be used above */
	supp_rates_len = rates_len;
	if (supp_rates_len > 8)
		supp_rates_len = 8;

	len = sband->n_bitrates;
	pos = skb_put(skb, supp_rates_len + 2);
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos++ = supp_rates_len;

	count = 0;
	for (i = 0; i < sband->n_bitrates; i++) {
		if (BIT(i) & rates) {
			int rate = sband->bitrates[i].bitrate;
			*pos++ = (u8) (rate / 5);
			if (++count == 8)
				break;
		}
	}

	if (rates_len > count) {
		pos = skb_put(skb, rates_len - count + 2);
		*pos++ = WLAN_EID_EXT_SUPP_RATES;
		*pos++ = rates_len - count;

		for (i++; i < sband->n_bitrates; i++) {
			if (BIT(i) & rates) {
				int rate = sband->bitrates[i].bitrate;
				*pos++ = (u8) (rate / 5);
			}
		}
	}

	if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) {
		/* 1. power capabilities */
		pos = skb_put(skb, 4);
		*pos++ = WLAN_EID_PWR_CAPABILITY;
		*pos++ = 2;
		*pos++ = 0; /* min tx power */
		*pos++ = local->hw.conf.channel->max_power; /* max tx power */

		/* 2. supported channels */
		/* TODO: get this in reg domain format */
		pos = skb_put(skb, 2 * sband->n_channels + 2);
		*pos++ = WLAN_EID_SUPPORTED_CHANNELS;
		*pos++ = 2 * sband->n_channels;
		for (i = 0; i < sband->n_channels; i++) {
			*pos++ = ieee80211_frequency_to_channel(
					sband->channels[i].center_freq);
			*pos++ = 1; /* one channel in the subband*/
		}
	}

302 303 304
	if (ifmgd->extra_ie) {
		pos = skb_put(skb, ifmgd->extra_ie_len);
		memcpy(pos, ifmgd->extra_ie, ifmgd->extra_ie_len);
305 306
	}

307
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
308 309 310 311 312 313 314 315 316 317 318 319 320
		pos = skb_put(skb, 9);
		*pos++ = WLAN_EID_VENDOR_SPECIFIC;
		*pos++ = 7; /* len */
		*pos++ = 0x00; /* Microsoft OUI 00:50:F2 */
		*pos++ = 0x50;
		*pos++ = 0xf2;
		*pos++ = 2; /* WME */
		*pos++ = 0; /* WME info */
		*pos++ = 1; /* WME ver */
		*pos++ = 0;
	}

	/* wmm support is a must to HT */
321 322 323 324 325 326
	/*
	 * IEEE802.11n does not allow TKIP/WEP as pairwise
	 * ciphers in HT mode. We still associate in non-ht
	 * mode (11a/b/g) if any one of these ciphers is
	 * configured as pairwise.
	 */
327
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
328
	    sband->ht_cap.ht_supported &&
329
	    (ht_ie = ieee80211_bss_get_ie(&bss->cbss, WLAN_EID_HT_INFORMATION)) &&
330
	    ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
331
	    (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
332 333 334
		struct ieee80211_ht_info *ht_info =
			(struct ieee80211_ht_info *)(ht_ie + 2);
		u16 cap = sband->ht_cap.cap;
335 336 337
		__le16 tmp;
		u32 flags = local->hw.conf.channel->flags;

338 339
		switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
340
			if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
341
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
342 343 344
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
345
		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
346
			if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
347
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
348 349 350 351 352 353 354 355 356 357 358 359 360
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
		}

		tmp = cpu_to_le16(cap);
		pos = skb_put(skb, sizeof(struct ieee80211_ht_cap)+2);
		*pos++ = WLAN_EID_HT_CAPABILITY;
		*pos++ = sizeof(struct ieee80211_ht_cap);
		memset(pos, 0, sizeof(struct ieee80211_ht_cap));
		memcpy(pos, &tmp, sizeof(u16));
		pos += sizeof(u16);
		/* TODO: needs a define here for << 2 */
361 362 363
		*pos++ = sband->ht_cap.ampdu_factor |
			 (sband->ht_cap.ampdu_density << 2);
		memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
364 365
	}

366 367 368 369 370
	kfree(ifmgd->assocreq_ies);
	ifmgd->assocreq_ies_len = (skb->data + skb->len) - ies;
	ifmgd->assocreq_ies = kmalloc(ifmgd->assocreq_ies_len, GFP_KERNEL);
	if (ifmgd->assocreq_ies)
		memcpy(ifmgd->assocreq_ies, ies, ifmgd->assocreq_ies_len);
371

372
	ieee80211_tx_skb(sdata, skb, 0);
373 374 375
}


376 377
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
					   u16 stype, u16 reason)
378 379
{
	struct ieee80211_local *local = sdata->local;
380
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
381 382
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
383

384
	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
385
	if (!skb) {
386 387
		printk(KERN_DEBUG "%s: failed to allocate buffer for "
		       "deauth/disassoc frame\n", sdata->dev->name);
388 389 390 391 392 393
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
394
	memcpy(mgmt->da, ifmgd->bssid, ETH_ALEN);
395
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
396
	memcpy(mgmt->bssid, ifmgd->bssid, ETH_ALEN);
397
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
398
	skb_put(skb, 2);
399
	/* u.deauth.reason_code == u.disassoc.reason_code */
400 401
	mgmt->u.deauth.reason_code = cpu_to_le16(reason);

402
	if (stype == IEEE80211_STYPE_DEAUTH)
403 404
		cfg80211_send_deauth(sdata->dev, (u8 *) mgmt, skb->len,
				     GFP_KERNEL);
405
	else
406 407
		cfg80211_send_disassoc(sdata->dev, (u8 *) mgmt, skb->len,
				       GFP_KERNEL);
408
	ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
409 410
}

411 412 413
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
414
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
	struct ieee80211_pspoll *pspoll;
	struct sk_buff *skb;
	u16 fc;

	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*pspoll));
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for "
		       "pspoll frame\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	pspoll = (struct ieee80211_pspoll *) skb_put(skb, sizeof(*pspoll));
	memset(pspoll, 0, sizeof(*pspoll));
	fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM;
	pspoll->frame_control = cpu_to_le16(fc);
431
	pspoll->aid = cpu_to_le16(ifmgd->aid);
432 433 434 435

	/* aid in PS-Poll has its two MSBs each set to 1 */
	pspoll->aid |= cpu_to_le16(1 << 15 | 1 << 14);

436
	memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
437 438 439 440 441
	memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);

	ieee80211_tx_skb(sdata, skb, 0);
}

442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474
void ieee80211_send_nullfunc(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
			     int powersave)
{
	struct sk_buff *skb;
	struct ieee80211_hdr *nullfunc;
	__le16 fc;

	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
		return;

	skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24);
	if (!skb) {
		printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc "
		       "frame\n", sdata->dev->name);
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
	memset(nullfunc, 0, 24);
	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
			 IEEE80211_FCTL_TODS);
	if (powersave)
		fc |= cpu_to_le16(IEEE80211_FCTL_PM);
	nullfunc->frame_control = fc;
	memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
	memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN);
	memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);

	ieee80211_tx_skb(sdata, skb, 0);
}

475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
/* spectrum management related things */
static void ieee80211_chswitch_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
	struct ieee80211_bss *bss;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

	if (!netif_running(sdata->dev))
		return;

	bss = ieee80211_rx_bss_get(sdata->local, ifmgd->bssid,
				   sdata->local->hw.conf.channel->center_freq,
				   ifmgd->ssid, ifmgd->ssid_len);
	if (!bss)
		goto exit;

	sdata->local->oper_channel = sdata->local->csa_channel;
	/* XXX: shouldn't really modify cfg80211-owned data! */
	if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
		bss->cbss.channel = sdata->local->oper_channel;

	ieee80211_rx_bss_put(sdata->local, bss);
exit:
	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
	ieee80211_wake_queues_by_reason(&sdata->local->hw,
					IEEE80211_QUEUE_STOP_REASON_CSA);
}

static void ieee80211_chswitch_timer(unsigned long data)
{
	struct ieee80211_sub_if_data *sdata =
		(struct ieee80211_sub_if_data *) data;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

510 511 512 513 514
	if (sdata->local->quiescing) {
		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
		return;
	}

515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
	queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
}

void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
				      struct ieee80211_channel_sw_ie *sw_elem,
				      struct ieee80211_bss *bss)
{
	struct ieee80211_channel *new_ch;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);

	if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATED)
		return;

	if (sdata->local->sw_scanning || sdata->local->hw_scanning)
		return;

	/* Disregard subsequent beacons if we are already running a timer
	   processing a CSA */

	if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
		return;

	new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
	if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED)
		return;

	sdata->local->csa_channel = new_ch;

	if (sw_elem->count <= 1) {
		queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
	} else {
		ieee80211_stop_queues_by_reason(&sdata->local->hw,
					IEEE80211_QUEUE_STOP_REASON_CSA);
		ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
		mod_timer(&ifmgd->chswitch_timer,
			  jiffies +
			  msecs_to_jiffies(sw_elem->count *
					   bss->cbss.beacon_interval));
	}
}

static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
					u16 capab_info, u8 *pwr_constr_elem,
					u8 pwr_constr_elem_len)
{
	struct ieee80211_conf *conf = &sdata->local->hw.conf;

	if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
		return;

	/* Power constraint IE length should be 1 octet */
	if (pwr_constr_elem_len != 1)
		return;

	if ((*pwr_constr_elem <= conf->channel->max_power) &&
	    (*pwr_constr_elem != sdata->local->power_constr_level)) {
		sdata->local->power_constr_level = *pwr_constr_elem;
		ieee80211_hw_config(sdata->local, 0);
	}
}

577 578 579 580 581 582
/* powersave */
static void ieee80211_enable_ps(struct ieee80211_local *local,
				struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_conf *conf = &local->hw.conf;

Johannes Berg's avatar
Johannes Berg committed
583 584 585 586 587 588 589
	/*
	 * If we are scanning right now then the parameters will
	 * take effect when scan finishes.
	 */
	if (local->hw_scanning || local->sw_scanning)
		return;

590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616
	if (conf->dynamic_ps_timeout > 0 &&
	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
		mod_timer(&local->dynamic_ps_timer, jiffies +
			  msecs_to_jiffies(conf->dynamic_ps_timeout));
	} else {
		if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
			ieee80211_send_nullfunc(local, sdata, 1);
		conf->flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}
}

static void ieee80211_change_ps(struct ieee80211_local *local)
{
	struct ieee80211_conf *conf = &local->hw.conf;

	if (local->ps_sdata) {
		ieee80211_enable_ps(local, local->ps_sdata);
	} else if (conf->flags & IEEE80211_CONF_PS) {
		conf->flags &= ~IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
		del_timer_sync(&local->dynamic_ps_timer);
		cancel_work_sync(&local->dynamic_ps_enable_work);
	}
}

/* need to hold RTNL or interface lock */
617
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635
{
	struct ieee80211_sub_if_data *sdata, *found = NULL;
	int count = 0;

	if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) {
		local->ps_sdata = NULL;
		return;
	}

	list_for_each_entry(sdata, &local->interfaces, list) {
		if (!netif_running(sdata->dev))
			continue;
		if (sdata->vif.type != NL80211_IFTYPE_STATION)
			continue;
		found = sdata;
		count++;
	}

636
	if (count == 1 && found->u.mgd.powersave &&
637 638
	    (found->u.mgd.flags & IEEE80211_STA_ASSOCIATED) &&
	    !(found->u.mgd.flags & IEEE80211_STA_PROBEREQ_POLL)) {
639 640 641 642 643 644 645 646
		s32 beaconint_us;

		if (latency < 0)
			latency = pm_qos_requirement(PM_QOS_NETWORK_LATENCY);

		beaconint_us = ieee80211_tu_to_usec(
					found->vif.bss_conf.beacon_int);

647
		if (beaconint_us > latency) {
648
			local->ps_sdata = NULL;
649 650 651 652 653 654 655 656
		} else {
			u8 dtimper = found->vif.bss_conf.dtim_period;
			int maxslp = 1;

			if (dtimper > 1)
				maxslp = min_t(int, dtimper,
						    latency / beaconint_us);

657
			local->hw.conf.max_sleep_period = maxslp;
658
			local->ps_sdata = found;
659
		}
660
	} else {
661
		local->ps_sdata = NULL;
662
	}
663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706

	ieee80211_change_ps(local);
}

void ieee80211_dynamic_ps_disable_work(struct work_struct *work)
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     dynamic_ps_disable_work);

	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}

	ieee80211_wake_queues_by_reason(&local->hw,
					IEEE80211_QUEUE_STOP_REASON_PS);
}

void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
{
	struct ieee80211_local *local =
		container_of(work, struct ieee80211_local,
			     dynamic_ps_enable_work);
	struct ieee80211_sub_if_data *sdata = local->ps_sdata;

	/* can only happen when PS was just disabled anyway */
	if (!sdata)
		return;

	if (local->hw.conf.flags & IEEE80211_CONF_PS)
		return;

	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
		ieee80211_send_nullfunc(local, sdata, 1);

	local->hw.conf.flags |= IEEE80211_CONF_PS;
	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
}

void ieee80211_dynamic_ps_timer(unsigned long data)
{
	struct ieee80211_local *local = (void *) data;

707 708 709
	if (local->quiescing)
		return;

710 711 712
	queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
}

Johannes Berg's avatar
Johannes Berg committed
713
/* MLME */
714
static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
715
				     struct ieee80211_if_managed *ifmgd,
716 717 718 719 720 721 722
				     u8 *wmm_param, size_t wmm_param_len)
{
	struct ieee80211_tx_queue_params params;
	size_t left;
	int count;
	u8 *pos;

723
	if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
724 725 726 727 728
		return;

	if (!wmm_param)
		return;

729 730 731
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
		return;
	count = wmm_param[6] & 0x0f;
732
	if (count == ifmgd->wmm_last_param_set)
733
		return;
734
	ifmgd->wmm_last_param_set = count;
735 736 737 738 739 740 741 742 743 744 745 746 747

	pos = wmm_param + 8;
	left = wmm_param_len - 8;

	memset(&params, 0, sizeof(params));

	local->wmm_acm = 0;
	for (; left >= 4; left -= 4, pos += 4) {
		int aci = (pos[0] >> 5) & 0x03;
		int acm = (pos[0] >> 4) & 0x01;
		int queue;

		switch (aci) {
748
		case 1: /* AC_BK */
Johannes Berg's avatar
Johannes Berg committed
749
			queue = 3;
Johannes Berg's avatar
Johannes Berg committed
750
			if (acm)
751
				local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
752
			break;
753
		case 2: /* AC_VI */
Johannes Berg's avatar
Johannes Berg committed
754
			queue = 1;
Johannes Berg's avatar
Johannes Berg committed
755
			if (acm)
756
				local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
757
			break;
758
		case 3: /* AC_VO */
Johannes Berg's avatar
Johannes Berg committed
759
			queue = 0;
Johannes Berg's avatar
Johannes Berg committed
760
			if (acm)
761
				local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
762
			break;
763
		case 0: /* AC_BE */
764
		default:
Johannes Berg's avatar
Johannes Berg committed
765
			queue = 2;
Johannes Berg's avatar
Johannes Berg committed
766
			if (acm)
767
				local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
768 769 770 771 772 773
			break;
		}

		params.aifs = pos[0] & 0x0f;
		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params.cw_min = ecw2cw(pos[1] & 0x0f);
774
		params.txop = get_unaligned_le16(pos + 2);
775
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
776
		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
777
		       "cWmin=%d cWmax=%d txop=%d\n",
778 779
		       wiphy_name(local->hw.wiphy), queue, aci, acm,
		       params.aifs, params.cw_min, params.cw_max, params.txop);
780
#endif
781
		if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx)
782
			printk(KERN_DEBUG "%s: failed to set TX queue "
783 784
			       "parameters for queue %d\n",
			       wiphy_name(local->hw.wiphy), queue);
785 786 787
	}
}

788 789
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
790
{
791
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
792
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
793
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
794
#endif
795
	u32 changed = 0;
796 797 798 799 800 801 802 803 804 805 806 807 808
	bool use_protection;
	bool use_short_preamble;
	bool use_short_slot;

	if (erp_valid) {
		use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0;
		use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0;
	} else {
		use_protection = false;
		use_short_preamble = !!(capab & WLAN_CAPABILITY_SHORT_PREAMBLE);
	}

	use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME);
809

810
	if (use_protection != bss_conf->use_cts_prot) {
811
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
812
		if (net_ratelimit()) {
813
			printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n",
814
			       sdata->dev->name,
815
			       use_protection ? "enabled" : "disabled",
816
			       ifmgd->bssid);
817
		}
818
#endif
819 820
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
821
	}
822

823
	if (use_short_preamble != bss_conf->use_short_preamble) {
824
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
825 826
		if (net_ratelimit()) {
			printk(KERN_DEBUG "%s: switched to %s barker preamble"
827
			       " (BSSID=%pM)\n",
828
			       sdata->dev->name,
829
			       use_short_preamble ? "short" : "long",
830
			       ifmgd->bssid);
831
		}
832
#endif
833
		bss_conf->use_short_preamble = use_short_preamble;
834
		changed |= BSS_CHANGED_ERP_PREAMBLE;
835
	}
836

837 838 839
	if (use_short_slot != bss_conf->use_short_slot) {
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
		if (net_ratelimit()) {
840 841
			printk(KERN_DEBUG "%s: switched to %s slot time"
			       " (BSSID=%pM)\n",
842 843
			       sdata->dev->name,
			       use_short_slot ? "short" : "long",
844
			       ifmgd->bssid);
845 846 847 848
		}
#endif
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
849 850 851 852 853
	}

	return changed;
}

854
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
Johannes Berg's avatar
Johannes Berg committed
855
				     u32 bss_info_changed)
856
{
857
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
858
	struct ieee80211_local *local = sdata->local;
Tomas Winkler's avatar
Tomas Winkler committed
859
	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
860

861
	struct ieee80211_bss *bss;
862

Johannes Berg's avatar
Johannes Berg committed
863
	bss_info_changed |= BSS_CHANGED_ASSOC;
864
	ifmgd->flags |= IEEE80211_STA_ASSOCIATED;
865

866
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
867
				   conf->channel->center_freq,
868
				   ifmgd->ssid, ifmgd->ssid_len);
869 870
	if (bss) {
		/* set timing information */
871 872
		sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
		sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
873
		sdata->vif.bss_conf.dtim_period = bss->dtim_period;
874

875
		bss_info_changed |= BSS_CHANGED_BEACON_INT;
Johannes Berg's avatar
Johannes Berg committed
876
		bss_info_changed |= ieee80211_handle_bss_capability(sdata,
877
			bss->cbss.capability, bss->has_erp_value, bss->erp_value);
878 879

		ieee80211_rx_bss_put(local, bss);
880 881
	}

882
	ieee80211_led_assoc(local, 1);
883

884
	sdata->vif.bss_conf.assoc = 1;
885 886 887 888 889
	/*
	 * 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.
	 */
Johannes Berg's avatar
Johannes Berg committed
890
	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
891 892 893 894

	/* And the BSSID changed - we're associated now */
	bss_info_changed |= BSS_CHANGED_BSSID;

Johannes Berg's avatar
Johannes Berg committed
895
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
896

897
	/* will be same as sdata */
898 899 900 901 902
	if (local->ps_sdata) {
		mutex_lock(&local->iflist_mtx);
		ieee80211_recalc_ps(local, -1);
		mutex_unlock(&local->iflist_mtx);
	}
903

904 905
	netif_tx_start_all_queues(sdata->dev);
	netif_carrier_on(sdata->dev);
906 907
}

908
static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata)
909
{
910
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
911
	struct ieee80211_local *local = sdata->local;
912 913 914

	ifmgd->direct_probe_tries++;
	if (ifmgd->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) {
915
		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
916 917
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
918
		ieee80211_recalc_idle(local);
919 920
		cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid,
					   GFP_KERNEL);
921 922 923 924 925

		/*
		 * Most likely AP is not in the range so remove the
		 * bss information associated to the AP
		 */
926
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
927
				sdata->local->hw.conf.channel->center_freq,
928
				ifmgd->ssid, ifmgd->ssid_len);
929 930 931 932 933 934 935

		/*
		 * We might have a pending scan which had no chance to run yet
		 * due to state == IEEE80211_STA_MLME_DIRECT_PROBE.
		 * Hence, queue the STAs work again
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
936 937 938
		return;
	}

939
	printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n",
940 941
			sdata->dev->name, ifmgd->bssid,
			ifmgd->direct_probe_tries);
942

943
	ifmgd->state = IEEE80211_STA_MLME_DIRECT_PROBE;
944

945 946 947 948
	/* Direct probe is sent to broadcast address as some APs
	 * will not answer to direct packet in unassociated state.
	 */
	ieee80211_send_probe_req(sdata, NULL,
949
				 ifmgd->ssid, ifmgd->ssid_len, NULL, 0);
950

951
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
Johannes Berg's avatar
Johannes Berg committed
952
}
953

954

955
static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
956
{
957
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
958
	struct ieee80211_local *local = sdata->local;
959 960 961

	ifmgd->auth_tries++;
	if (ifmgd->auth_tries > IEEE80211_AUTH_MAX_TRIES) {
962
		printk(KERN_DEBUG "%s: authentication with AP %pM"
963
		       " timed out\n",
964 965
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
966
		ieee80211_recalc_idle(local);
967 968
		cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid,
					   GFP_KERNEL);
969
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
970
				sdata->local->hw.conf.channel->center_freq,
971
				ifmgd->ssid, ifmgd->ssid_len);
972 973 974 975 976 977 978

		/*
		 * We might have a pending scan which had no chance to run yet
		 * due to state == IEEE80211_STA_MLME_AUTHENTICATE.
		 * Hence, queue the STAs work again
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
979 980 981
		return;
	}

982
	ifmgd->state = IEEE80211_STA_MLME_AUTHENTICATE;
983
	printk(KERN_DEBUG "%s: authenticate with AP %pM\n",
984
	       sdata->dev->name, ifmgd->bssid);
985

986 987
	ieee80211_send_auth(sdata, 1, ifmgd->auth_alg, ifmgd->sme_auth_ie,
			    ifmgd->sme_auth_ie_len, ifmgd->bssid, 0);
988
	ifmgd->auth_transaction = 2;
989

990
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_AUTH_TIMEOUT);
991 992
}

993 994 995 996
/*
 * The disassoc 'reason' argument can be either our own reason
 * if self disconnected or a reason code from the AP.
 */
997
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
998 999
				   bool deauth, bool self_disconnected,
				   u16 reason)
1000
{
1001
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1002
	struct ieee80211_local *local = sdata->local;
1003 1004
	struct ieee80211_conf *conf = &local_to_hw(local)->conf;
	struct ieee80211_bss *bss;
1005
	struct sta_info *sta;
1006
	u32 changed = 0, config_changed = 0;
1007 1008

	if (deauth) {
1009 1010
		ifmgd->direct_probe_tries = 0;
		ifmgd->auth_tries = 0;
1011
	}
1012 1013
	ifmgd->assoc_scan_tries = 0;
	ifmgd->assoc_tries = 0;
1014

1015
	netif_tx_stop_all_queues(sdata->dev);
1016 1017
	netif_carrier_off(sdata->dev);

1018 1019 1020 1021 1022
	rcu_read_lock();
	sta = sta_info_get(local, ifmgd->bssid);
	if (sta)
		ieee80211_sta_tear_down_BA_sessions(sta);
	rcu_read_unlock();
1023

1024 1025 1026 1027
	bss = ieee80211_rx_bss_get(local, ifmgd->bssid,
				   conf->channel->center_freq,
				   ifmgd->ssid, ifmgd->ssid_len);

Johannes Berg's avatar
Johannes Berg committed
1028
	if (bss)
1029 1030
		ieee80211_rx_bss_put(local, bss);

1031 1032
	if (self_disconnected) {
		if (deauth)
1033 1034
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DEAUTH, reason);
1035
		else
1036 1037
			ieee80211_send_deauth_disassoc(sdata,
				IEEE80211_STYPE_DISASSOC, reason);
1038 1039
	}

1040
	ifmgd->flags &= ~IEEE80211_STA_ASSOCIATED;
1041 1042 1043
	changed |= ieee80211_reset_erp_info(sdata);

	ieee80211_led_assoc(local, 0);
Johannes Berg's avatar
Johannes Berg committed
1044 1045
	changed |= BSS_CHANGED_ASSOC;
	sdata->vif.bss_conf.assoc = false;
1046

1047
	if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) {
1048 1049
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
1050
				sdata->local->hw.conf.channel->center_freq,
1051
				ifmgd->ssid, ifmgd->ssid_len);
1052
	}
1053

1054 1055
	ieee80211_set_wmm_default(sdata);

1056 1057
	ieee80211_recalc_idle(local);

1058
	/* channel(_type) changes are handled by ieee80211_hw_config */
Sujith's avatar
Sujith committed
1059
	local->oper_channel_type = NL80211_CHAN_NO_HT;
1060

1061 1062 1063
	/* on the next assoc, re-program HT parameters */
	sdata->ht_opmode_valid = false;

1064 1065
	local->power_constr_level = 0;

1066 1067 1068
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

1069 1070 1071 1072
	if (local->hw.conf.flags & IEEE80211_CONF_PS) {
		local->hw.conf.flags &= ~IEEE80211_CONF_PS;
		config_changed |= IEEE80211_CONF_CHANGE_PS;
	}
Johannes Berg's avatar
Johannes Berg committed
1073

1074
	ieee80211_hw_config(local, config_changed);
1075 1076 1077

	/* And the BSSID changed -- not very interesting here */
	changed |= BSS_CHANGED_BSSID;
Johannes Berg's avatar
Johannes Berg committed
1078
	ieee80211_bss_info_change_notify(sdata, changed);
1079 1080 1081

	rcu_read_lock();

1082
	sta = sta_info_get(local, ifmgd->bssid);
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	sta_info_unlink(&sta);

	rcu_read_unlock();

	sta_info_destroy(sta);
1093
}
1094

1095
static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
1096
{
1097
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1098
	struct ieee80211_local *local = sdata->local;
1099 1100 1101

	ifmgd->assoc_tries++;
	if (ifmgd->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) {
1102
		printk(KERN_DEBUG "%s: association with AP %pM"
1103
		       " timed out\n",
1104 1105
		       sdata->dev->name, ifmgd->bssid);
		ifmgd->state = IEEE80211_STA_MLME_DISABLED;
1106
		ieee80211_recalc_idle(local);
1107 1108
		cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid,
					    GFP_KERNEL);
1109
		ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
1110
				sdata->local->hw.conf.channel->center_freq,
1111
				ifmgd->ssid, ifmgd->ssid_len);
1112 1113 1114 1115 1116 1117
		/*
		 * We might have a pending scan which had no chance to run yet
		 * due to state == IEEE80211_STA_MLME_ASSOCIATE.
		 * Hence, queue the STAs work again
		 */
		queue_work(local->hw.workqueue, &ifmgd->work);
1118 1119 1120
		return;
	}

1121
	ifmgd->state = IEEE80211_STA_MLME_ASSOCIATE;
1122
	printk(KERN_DEBUG "%s: associate with AP %pM\n",
1123 1124
	       sdata->dev->name, ifmgd->bssid);
	ieee80211_send_assoc(sdata);
1125

1126
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_ASSOC_TIMEOUT);
1127 1128
}

1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_hdr *hdr)
{
	/*
	 * We can postpone the mgd.timer whenever receiving unicast frames
	 * from AP because we know that the connection is working both ways
	 * at that time. But multicast frames (and hence also beacons) must
	 * be ignored here, because we need to trigger the timer during
	 * data idle periods for sending the periodical probe request to
	 * the AP.
	 */
	if (!is_multicast_ether_addr(hdr->addr1))
		mod_timer(&sdata->u.mgd.timer,
			  jiffies + IEEE80211_MONITORING_INTERVAL);
}
1144

1145 1146 1147 1148 1149 1150 1151
void ieee80211_beacon_loss_work(struct work_struct *work)
{
	struct ieee80211_sub_if_data *sdata =
		container_of(work, struct ieee80211_sub_if_data,
			     u.mgd.beacon_loss_work);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
	/*
	 * The driver has already reported this event and we have
	 * already sent a probe request. Maybe the AP died and the
	 * driver keeps reporting until we disassociate... We have
	 * to ignore that because otherwise we would continually
	 * reset the timer and never check whether we received a
	 * probe response!
	 */
	if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL)
		return;

1163 1164 1165 1166 1167 1168 1169
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
	if (net_ratelimit()) {
		printk(KERN_DEBUG "%s: driver reports beacon loss from AP %pM "
		       "- sending probe request\n", sdata->dev->name,
		       sdata->u.mgd.bssid);
	}
#endif
1170 1171

	ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
1172 1173 1174 1175 1176

	mutex_lock(&sdata->local->iflist_mtx);
	ieee80211_recalc_ps(sdata->local, -1);
	mutex_unlock(&sdata->local->iflist_mtx);

1177 1178 1179
	ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
				 ifmgd->ssid_len, NULL, 0);

1180
	mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191
}

void ieee80211_beacon_loss(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);

	queue_work(sdata->local->hw.workqueue,
		   &sdata->u.mgd.beacon_loss_work);
}
EXPORT_SYMBOL(ieee80211_beacon_loss);

1192
static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
1193
{