mlme.c 105 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/moduleparam.h>
20
#include <linux/rtnetlink.h>
21
#include <linux/pm_qos.h>
22
#include <linux/crc32.h>
23
#include <linux/slab.h>
24
#include <linux/export.h>
25
#include <net/mac80211.h>
26
#include <asm/unaligned.h>
Johannes Berg's avatar
Johannes Berg committed
27

28
#include "ieee80211_i.h"
29
#include "driver-ops.h"
Johannes Berg's avatar
Johannes Berg committed
30
31
#include "rate.h"
#include "led.h"
32

Johannes Berg's avatar
Johannes Berg committed
33
34
35
36
37
38
#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_MAX_TRIES 3
#define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5)
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_MAX_TRIES 3

39
40
41
42
43
44
45
46
47
static int max_nullfunc_tries = 2;
module_param(max_nullfunc_tries, int, 0644);
MODULE_PARM_DESC(max_nullfunc_tries,
		 "Maximum nullfunc tx tries before disconnecting (reason 4).");

static int max_probe_tries = 5;
module_param(max_probe_tries, int, 0644);
MODULE_PARM_DESC(max_probe_tries,
		 "Maximum probe tries before disconnecting (reason 4).");
48
49

/*
50
51
52
53
54
55
 * Beacon loss timeout is calculated as N frames times the
 * advertised beacon interval.  This may need to be somewhat
 * higher than what hardware might detect to account for
 * delays in the host processing frames. But since we also
 * probe on beacon miss before declaring the connection lost
 * default to what we want.
56
 */
57
58
#define IEEE80211_BEACON_LOSS_COUNT	7

59
60
61
62
/*
 * Time the connection can be idle before we probe
 * it to see if we can still talk to the AP.
 */
63
#define IEEE80211_CONNECTION_IDLE_TIME	(30 * HZ)
64
65
66
67
68
/*
 * Time we wait for a probe response after sending
 * a probe request because of beacon loss or for
 * checking the connection still works.
 */
69
70
71
72
73
static int probe_wait_ms = 500;
module_param(probe_wait_ms, int, 0644);
MODULE_PARM_DESC(probe_wait_ms,
		 "Maximum time(ms) to wait for probe response"
		 " before disconnecting (reason 4).");
74

75
76
77
78
79
80
81
/*
 * Weight given to the latest Beacon frame when calculating average signal
 * strength for Beacon frames received in the current BSS. This must be
 * between 1 and 15.
 */
#define IEEE80211_SIGNAL_AVE_WEIGHT	3

82
83
84
85
86
87
/*
 * How many Beacon frames need to have been used in average signal strength
 * before starting to indicate signal change events.
 */
#define IEEE80211_SIGNAL_AVE_MIN_COUNT	4

88
89
90
#define TMR_RUNNING_TIMER	0
#define TMR_RUNNING_CHANSW	1

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
 * All cfg80211 functions have to be called outside a locked
 * section so that they can acquire a lock themselves... This
 * is much simpler than queuing up things in cfg80211, but we
 * do need some indirection for that here.
 */
enum rx_mgmt_action {
	/* no action required */
	RX_MGMT_NONE,

	/* caller must call cfg80211_send_deauth() */
	RX_MGMT_CFG80211_DEAUTH,

	/* caller must call cfg80211_send_disassoc() */
	RX_MGMT_CFG80211_DISASSOC,
Johannes Berg's avatar
Johannes Berg committed
106
107
108
109
110
111
112
113
114

	/* caller must call cfg80211_send_rx_auth() */
	RX_MGMT_CFG80211_RX_AUTH,

	/* caller must call cfg80211_send_rx_assoc() */
	RX_MGMT_CFG80211_RX_ASSOC,

	/* caller must call cfg80211_send_assoc_timeout() */
	RX_MGMT_CFG80211_ASSOC_TIMEOUT,
115
116
};

117
/* utils */
118
119
static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
{
120
	lockdep_assert_held(&ifmgd->mtx);
121
122
}

Johannes Berg's avatar
Johannes Berg committed
123
124
125
126
127
128
129
130
131
132
/*
 * We can have multiple work items (and connection probing)
 * scheduling this timer, but we need to take care to only
 * reschedule it when it should fire _earlier_ than it was
 * asked for before, or if it's not pending right now. This
 * function ensures that. Note that it then is required to
 * run this function for all timeouts after the first one
 * has happened -- the work that runs from this timer will
 * do that.
 */
Johannes Berg's avatar
Johannes Berg committed
133
static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout)
Johannes Berg's avatar
Johannes Berg committed
134
135
136
137
138
139
140
141
{
	ASSERT_MGD_MTX(ifmgd);

	if (!timer_pending(&ifmgd->timer) ||
	    time_before(timeout, ifmgd->timer.expires))
		mod_timer(&ifmgd->timer, timeout);
}

142
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
143
{
144
	if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
145
146
		return;

147
148
149
	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
		return;

150
	mod_timer(&sdata->u.mgd.bcn_mon_timer,
151
		  round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout));
152
153
}

154
155
void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata)
{
156
157
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

158
159
160
	if (unlikely(!sdata->u.mgd.associated))
		return;

161
162
163
164
165
	if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
		return;

	mod_timer(&sdata->u.mgd.conn_mon_timer,
		  round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME));
166
167

	ifmgd->probe_send_count = 0;
168
169
}

170
static int ecw2cw(int ecw)
Johannes Berg's avatar
Johannes Berg committed
171
{
172
	return (1 << ecw) - 1;
Johannes Berg's avatar
Johannes Berg committed
173
174
}

175
176
177
static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
				  struct ieee80211_ht_operation *ht_oper,
				  const u8 *bssid, bool reconfig)
178
179
180
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_supported_band *sband;
Johannes Berg's avatar
Johannes Berg committed
181
182
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_channel *chan;
183
184
	struct sta_info *sta;
	u32 changed = 0;
185
	u16 ht_opmode;
186
	bool disable_40 = false;
187

Johannes Berg's avatar
Johannes Berg committed
188
189
190
191
192
193
	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
	if (WARN_ON(!chanctx_conf)) {
		rcu_read_unlock();
		return 0;
	}
194
	chan = chanctx_conf->def.chan;
Johannes Berg's avatar
Johannes Berg committed
195
196
	rcu_read_unlock();
	sband = local->hw.wiphy->bands[chan->band];
197

198
199
200
201
202
	switch (sdata->vif.bss_conf.chandef.width) {
	case NL80211_CHAN_WIDTH_40:
		if (sdata->vif.bss_conf.chandef.chan->center_freq >
				sdata->vif.bss_conf.chandef.center_freq1 &&
		    chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
203
			disable_40 = true;
204
205
206
		if (sdata->vif.bss_conf.chandef.chan->center_freq <
				sdata->vif.bss_conf.chandef.center_freq1 &&
		    chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
207
208
209
210
211
			disable_40 = true;
		break;
	default:
		break;
	}
212

213
214
	/* This can change during the lifetime of the BSS */
	if (!(ht_oper->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
215
216
217
218
		disable_40 = true;

	mutex_lock(&local->sta_mtx);
	sta = sta_info_get(sdata, bssid);
219

220
221
222
223
224
225
	WARN_ON_ONCE(!sta);

	if (sta && !sta->supports_40mhz)
		disable_40 = true;

	if (sta && (!reconfig ||
226
		    (disable_40 != !(sta->sta.ht_cap.cap &
227
					IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) {
228

229
230
231
232
		if (disable_40)
			sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
		else
			sta->sta.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
233

234
		rate_control_rate_update(local, sband, sta,
235
					 IEEE80211_RC_BW_CHANGED);
236
	}
237
	mutex_unlock(&local->sta_mtx);
238

239
	ht_opmode = le16_to_cpu(ht_oper->operation_mode);
240
241

	/* if bss configuration changed store the new one */
242
	if (!reconfig || (sdata->vif.bss_conf.ht_operation_mode != ht_opmode)) {
243
		changed |= BSS_CHANGED_HT;
244
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
245
246
247
248
249
	}

	return changed;
}

250
251
/* frame sending functions */

Johannes Berg's avatar
Johannes Berg committed
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
				      struct ieee80211_supported_band *sband,
				      u32 *rates)
{
	int i, j, count;
	*rates = 0;
	count = 0;
	for (i = 0; i < supp_rates_len; i++) {
		int rate = (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;
}

static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
274
				struct sk_buff *skb, u8 ap_ht_param,
Johannes Berg's avatar
Johannes Berg committed
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
				struct ieee80211_supported_band *sband,
				struct ieee80211_channel *channel,
				enum ieee80211_smps_mode smps)
{
	u8 *pos;
	u32 flags = channel->flags;
	u16 cap;
	struct ieee80211_sta_ht_cap ht_cap;

	BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));

	memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
	ieee80211_apply_htcap_overrides(sdata, &ht_cap);

	/* determine capability flags */
	cap = ht_cap.cap;

292
	switch (ap_ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
Johannes Berg's avatar
Johannes Berg committed
293
294
295
296
297
298
299
300
301
302
303
304
305
306
	case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
		if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
			cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
			cap &= ~IEEE80211_HT_CAP_SGI_40;
		}
		break;
	case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
		if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
			cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
			cap &= ~IEEE80211_HT_CAP_SGI_40;
		}
		break;
	}

307
308
309
310
311
312
313
314
315
316
	/*
	 * If 40 MHz was disabled associate as though we weren't
	 * capable of 40 MHz -- some broken APs will never fall
	 * back to trying to transmit in 20 MHz.
	 */
	if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_40MHZ) {
		cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
		cap &= ~IEEE80211_HT_CAP_SGI_40;
	}

Johannes Berg's avatar
Johannes Berg committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
	/* set SM PS mode properly */
	cap &= ~IEEE80211_HT_CAP_SM_PS;
	switch (smps) {
	case IEEE80211_SMPS_AUTOMATIC:
	case IEEE80211_SMPS_NUM_MODES:
		WARN_ON(1);
	case IEEE80211_SMPS_OFF:
		cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
			IEEE80211_HT_CAP_SM_PS_SHIFT;
		break;
	case IEEE80211_SMPS_STATIC:
		cap |= WLAN_HT_CAP_SM_PS_STATIC <<
			IEEE80211_HT_CAP_SM_PS_SHIFT;
		break;
	case IEEE80211_SMPS_DYNAMIC:
		cap |= WLAN_HT_CAP_SM_PS_DYNAMIC <<
			IEEE80211_HT_CAP_SM_PS_SHIFT;
		break;
	}

	/* reserve and fill IE */
	pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
	ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
}

342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
				 struct sk_buff *skb,
				 struct ieee80211_supported_band *sband)
{
	u8 *pos;
	u32 cap;
	struct ieee80211_sta_vht_cap vht_cap;

	BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap));

	memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap));

	/* determine capability flags */
	cap = vht_cap.cap;

	/* reserve and fill IE */
358
	pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2);
359
360
361
	ieee80211_ie_build_vht_cap(pos, &vht_cap, cap);
}

Johannes Berg's avatar
Johannes Berg committed
362
363
364
365
366
367
368
369
370
371
372
373
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
	struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
	u8 *pos, qos_info;
	size_t offset = 0, noffset;
	int i, count, rates_len, supp_rates_len;
	u16 capab;
	struct ieee80211_supported_band *sband;
Johannes Berg's avatar
Johannes Berg committed
374
375
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_channel *chan;
Johannes Berg's avatar
Johannes Berg committed
376
377
378
379
	u32 rates = 0;

	lockdep_assert_held(&ifmgd->mtx);

Johannes Berg's avatar
Johannes Berg committed
380
381
382
383
384
385
	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
	if (WARN_ON(!chanctx_conf)) {
		rcu_read_unlock();
		return;
	}
386
	chan = chanctx_conf->def.chan;
Johannes Berg's avatar
Johannes Berg committed
387
388
	rcu_read_unlock();
	sband = local->hw.wiphy->bands[chan->band];
Johannes Berg's avatar
Johannes Berg committed
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

	if (assoc_data->supp_rates_len) {
		/*
		 * 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(assoc_data->supp_rates,
						       assoc_data->supp_rates_len,
						       sband, &rates);
	} else {
		/*
		 * In case AP not provide any supported rates information
		 * before association, we send information element(s) with
		 * all rates that we support.
		 */
		rates = ~0;
		rates_len = sband->n_bitrates;
	}

	skb = alloc_skb(local->hw.extra_tx_headroom +
			sizeof(*mgmt) + /* bit too much but doesn't matter */
			2 + assoc_data->ssid_len + /* SSID */
			4 + rates_len + /* (extended) rates */
			4 + /* power capability */
			2 + 2 * sband->n_channels + /* supported channels */
			2 + sizeof(struct ieee80211_ht_cap) + /* HT */
417
			2 + sizeof(struct ieee80211_vht_cap) + /* VHT */
Johannes Berg's avatar
Johannes Berg committed
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
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
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
			assoc_data->ie_len + /* extra IEs */
			9, /* WMM */
			GFP_KERNEL);
	if (!skb)
		return;

	skb_reserve(skb, local->hw.extra_tx_headroom);

	capab = WLAN_CAPABILITY_ESS;

	if (sband->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;
	}

	if (assoc_data->capability & WLAN_CAPABILITY_PRIVACY)
		capab |= WLAN_CAPABILITY_PRIVACY;

	if ((assoc_data->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
	    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
		capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
	memcpy(mgmt->da, assoc_data->bss->bssid, ETH_ALEN);
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
	memcpy(mgmt->bssid, assoc_data->bss->bssid, ETH_ALEN);

	if (!is_zero_ether_addr(assoc_data->prev_bssid)) {
		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);
		memcpy(mgmt->u.reassoc_req.current_ap, assoc_data->prev_bssid,
		       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);
		mgmt->u.assoc_req.listen_interval =
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
	pos = skb_put(skb, 2 + assoc_data->ssid_len);
	*pos++ = WLAN_EID_SSID;
	*pos++ = assoc_data->ssid_len;
	memcpy(pos, assoc_data->ssid, assoc_data->ssid_len);

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

	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 */
Johannes Berg's avatar
Johannes Berg committed
510
		*pos++ = chan->max_power; /* max tx power */
Johannes Berg's avatar
Johannes Berg committed
511
512
513
514
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

		/* 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*/
		}
	}

	/* if present, add any custom IEs that go before HT */
	if (assoc_data->ie_len && assoc_data->ie) {
		static const u8 before_ht[] = {
			WLAN_EID_SSID,
			WLAN_EID_SUPP_RATES,
			WLAN_EID_EXT_SUPP_RATES,
			WLAN_EID_PWR_CAPABILITY,
			WLAN_EID_SUPPORTED_CHANNELS,
			WLAN_EID_RSN,
			WLAN_EID_QOS_CAPA,
			WLAN_EID_RRM_ENABLED_CAPABILITIES,
			WLAN_EID_MOBILITY_DOMAIN,
			WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
		};
		noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
					     before_ht, ARRAY_SIZE(before_ht),
					     offset);
		pos = skb_put(skb, noffset - offset);
		memcpy(pos, assoc_data->ie + offset, noffset - offset);
		offset = noffset;
	}

546
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
547
		ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param,
548
				    sband, chan, sdata->smps_mode);
Johannes Berg's avatar
Johannes Berg committed
549

550
551
552
	if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
		ieee80211_add_vht_ie(sdata, skb, sband);

Johannes Berg's avatar
Johannes Berg committed
553
554
555
556
557
558
559
560
561
562
	/* if present, add any custom non-vendor IEs that go after HT */
	if (assoc_data->ie_len && assoc_data->ie) {
		noffset = ieee80211_ie_split_vendor(assoc_data->ie,
						    assoc_data->ie_len,
						    offset);
		pos = skb_put(skb, noffset - offset);
		memcpy(pos, assoc_data->ie + offset, noffset - offset);
		offset = noffset;
	}

563
564
	if (assoc_data->wmm) {
		if (assoc_data->uapsd) {
565
566
			qos_info = ifmgd->uapsd_queues;
			qos_info |= (ifmgd->uapsd_max_sp_len <<
Johannes Berg's avatar
Johannes Berg committed
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
				     IEEE80211_WMM_IE_STA_QOSINFO_SP_SHIFT);
		} else {
			qos_info = 0;
		}

		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++ = qos_info;
	}

	/* add any remaining custom (i.e. vendor specific here) IEs */
	if (assoc_data->ie_len && assoc_data->ie) {
		noffset = assoc_data->ie_len;
		pos = skb_put(skb, noffset - offset);
		memcpy(pos, assoc_data->ie + offset, noffset - offset);
	}

Johannes Berg's avatar
Johannes Berg committed
591
592
	drv_mgd_prepare_tx(local, sdata);

Johannes Berg's avatar
Johannes Berg committed
593
594
595
596
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
	ieee80211_tx_skb(sdata, skb);
}

597
598
599
600
601
602
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_pspoll *pspoll;
	struct sk_buff *skb;

603
604
	skb = ieee80211_pspoll_get(&local->hw, &sdata->vif);
	if (!skb)
605
606
		return;

607
608
	pspoll = (struct ieee80211_pspoll *) skb->data;
	pspoll->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
609

610
611
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
	ieee80211_tx_skb(sdata, skb);
612
613
}

614
615
616
617
618
void ieee80211_send_nullfunc(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
			     int powersave)
{
	struct sk_buff *skb;
619
	struct ieee80211_hdr_3addr *nullfunc;
620
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
621

622
623
	skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif);
	if (!skb)
624
625
		return;

626
	nullfunc = (struct ieee80211_hdr_3addr *) skb->data;
627
	if (powersave)
628
		nullfunc->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
629

630
	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
631
632
633
634
	if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
			    IEEE80211_STA_CONNECTION_POLL))
		IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_USE_MINRATE;

635
	ieee80211_tx_skb(sdata, skb);
636
637
}

638
639
640
641
642
643
644
645
646
647
648
static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
					  struct ieee80211_sub_if_data *sdata)
{
	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 + 30);
649
	if (!skb)
650
		return;
651

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
	skb_reserve(skb, local->hw.extra_tx_headroom);

	nullfunc = (struct ieee80211_hdr *) skb_put(skb, 30);
	memset(nullfunc, 0, 30);
	fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
			 IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
	nullfunc->frame_control = fc;
	memcpy(nullfunc->addr1, sdata->u.mgd.bssid, ETH_ALEN);
	memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
	memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN);
	memcpy(nullfunc->addr4, sdata->vif.addr, ETH_ALEN);

	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
	ieee80211_tx_skb(sdata, skb);
}

668
669
670
671
672
673
674
/* 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_if_managed *ifmgd = &sdata->u.mgd;

675
	if (!ieee80211_sdata_running(sdata))
676
677
		return;

678
679
680
	mutex_lock(&ifmgd->mtx);
	if (!ifmgd->associated)
		goto out;
681

Johannes Berg's avatar
Johannes Berg committed
682
	sdata->local->_oper_channel = sdata->local->csa_channel;
683
684
685
686
	if (!sdata->local->ops->channel_switch) {
		/* call "hw_config" only if doing sw channel switch */
		ieee80211_hw_config(sdata->local,
			IEEE80211_CONF_CHANGE_CHANNEL);
687
688
	} else {
		/* update the device channel directly */
Johannes Berg's avatar
Johannes Berg committed
689
		sdata->local->hw.conf.channel = sdata->local->_oper_channel;
690
	}
691

692
	/* XXX: shouldn't really modify cfg80211-owned data! */
Johannes Berg's avatar
Johannes Berg committed
693
	ifmgd->associated->channel = sdata->local->_oper_channel;
694

695
	/* XXX: wait for a beacon first? */
696
697
	ieee80211_wake_queues_by_reason(&sdata->local->hw,
					IEEE80211_QUEUE_STOP_REASON_CSA);
698
699
700
 out:
	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
	mutex_unlock(&ifmgd->mtx);
701
702
}

703
704
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
{
Johannes Berg's avatar
Johannes Berg committed
705
706
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
707
708
709

	trace_api_chswitch_done(sdata, success);
	if (!success) {
710
711
712
713
714
715
		sdata_info(sdata,
			   "driver channel switch failed, disconnecting\n");
		ieee80211_queue_work(&sdata->local->hw,
				     &ifmgd->csa_connection_drop_work);
	} else {
		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
716
717
718
719
	}
}
EXPORT_SYMBOL(ieee80211_chswitch_done);

720
721
722
723
724
725
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;

726
727
728
729
730
	if (sdata->local->quiescing) {
		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
		return;
	}

731
	ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
732
733
734
735
}

void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
				      struct ieee80211_channel_sw_ie *sw_elem,
736
737
				      struct ieee80211_bss *bss,
				      u64 timestamp)
738
{
739
740
	struct cfg80211_bss *cbss =
		container_of((void *)bss, struct cfg80211_bss, priv);
741
742
	struct ieee80211_channel *new_ch;
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
743
744
	int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num,
						      cbss->channel->band);
Johannes Berg's avatar
Johannes Berg committed
745
	struct ieee80211_chanctx *chanctx;
746

747
748
749
	ASSERT_MGD_MTX(ifmgd);

	if (!ifmgd->associated)
750
751
		return;

752
	if (sdata->local->scanning)
753
754
755
756
757
758
759
760
761
		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);
762
763
764
765
766
767
	if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED) {
		sdata_info(sdata,
			   "AP %pM switches to unsupported channel (%d MHz), disconnecting\n",
			   ifmgd->associated->bssid, new_freq);
		ieee80211_queue_work(&sdata->local->hw,
				     &ifmgd->csa_connection_drop_work);
768
		return;
769
	}
770

771
772
	ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;

Johannes Berg's avatar
Johannes Berg committed
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
	if (sdata->local->use_chanctx) {
		sdata_info(sdata,
			   "not handling channel switch with channel contexts\n");
		ieee80211_queue_work(&sdata->local->hw,
				     &ifmgd->csa_connection_drop_work);
	}

	mutex_lock(&sdata->local->chanctx_mtx);
	if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) {
		mutex_unlock(&sdata->local->chanctx_mtx);
		return;
	}
	chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf),
			       struct ieee80211_chanctx, conf);
	if (chanctx->refcount > 1) {
		sdata_info(sdata,
			   "channel switch with multiple interfaces on the same channel, disconnecting\n");
		ieee80211_queue_work(&sdata->local->hw,
				     &ifmgd->csa_connection_drop_work);
		mutex_unlock(&sdata->local->chanctx_mtx);
		return;
	}
	mutex_unlock(&sdata->local->chanctx_mtx);

	sdata->local->csa_channel = new_ch;

799
800
801
802
	if (sw_elem->mode)
		ieee80211_stop_queues_by_reason(&sdata->local->hw,
				IEEE80211_QUEUE_STOP_REASON_CSA);

803
804
	if (sdata->local->ops->channel_switch) {
		/* use driver's channel switch callback */
805
806
807
808
809
810
811
		struct ieee80211_channel_switch ch_switch = {
			.timestamp = timestamp,
			.block_tx = sw_elem->mode,
			.channel = new_ch,
			.count = sw_elem->count,
		};

812
813
814
815
816
		drv_channel_switch(sdata->local, &ch_switch);
		return;
	}

	/* channel switch handled in software */
817
	if (sw_elem->count <= 1)
818
		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
819
	else
820
		mod_timer(&ifmgd->chswitch_timer,
821
822
			  TU_TO_EXP_TIME(sw_elem->count *
					 cbss->beacon_interval));
823
824
}

825
826
827
828
static u32 ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
				       struct ieee80211_channel *channel,
				       const u8 *country_ie, u8 country_ie_len,
				       const u8 *pwr_constr_elem)
829
{
830
831
832
833
	struct ieee80211_country_ie_triplet *triplet;
	int chan = ieee80211_frequency_to_channel(channel->center_freq);
	int i, chan_pwr, chan_increment, new_ap_level;
	bool have_chan_pwr = false;
834

835
836
	/* Invalid IE */
	if (country_ie_len % 2 || country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
837
		return 0;
838

839
840
841
842
843
844
845
846
847
848
849
850
851
852
	triplet = (void *)(country_ie + 3);
	country_ie_len -= 3;

	switch (channel->band) {
	default:
		WARN_ON_ONCE(1);
		/* fall through */
	case IEEE80211_BAND_2GHZ:
	case IEEE80211_BAND_60GHZ:
		chan_increment = 1;
		break;
	case IEEE80211_BAND_5GHZ:
		chan_increment = 4;
		break;
853
	}
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877

	/* find channel */
	while (country_ie_len >= 3) {
		u8 first_channel = triplet->chans.first_channel;

		if (first_channel >= IEEE80211_COUNTRY_EXTENSION_ID)
			goto next;

		for (i = 0; i < triplet->chans.num_channels; i++) {
			if (first_channel + i * chan_increment == chan) {
				have_chan_pwr = true;
				chan_pwr = triplet->chans.max_power;
				break;
			}
		}
		if (have_chan_pwr)
			break;

 next:
		triplet++;
		country_ie_len -= 3;
	}

	if (!have_chan_pwr)
878
		return 0;
879
880
881

	new_ap_level = max_t(int, 0, chan_pwr - *pwr_constr_elem);

882
883
	if (sdata->ap_power_level == new_ap_level)
		return 0;
884
885
886
887
888

	sdata_info(sdata,
		   "Limiting TX power to %d (%d - %d) dBm as advertised by %pM\n",
		   new_ap_level, chan_pwr, *pwr_constr_elem,
		   sdata->u.mgd.bssid);
889
890
891
892
	sdata->ap_power_level = new_ap_level;
	if (__ieee80211_recalc_txpower(sdata))
		return BSS_CHANGED_TXPOWER;
	return 0;
893
894
}

895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_conf *conf = &local->hw.conf;

	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
		!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
		(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));

	local->disable_dynamic_ps = false;
	conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout;
}
EXPORT_SYMBOL(ieee80211_enable_dyn_ps);

void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif)
{
	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_conf *conf = &local->hw.conf;

	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
		!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
		(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));

	local->disable_dynamic_ps = true;
	conf->dynamic_ps_timeout = 0;
	del_timer_sync(&local->dynamic_ps_timer);
	ieee80211_queue_work(&local->hw,
			     &local->dynamic_ps_enable_work);
}
EXPORT_SYMBOL(ieee80211_disable_dyn_ps);

928
929
930
931
932
933
/* 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
934
935
936
937
	/*
	 * If we are scanning right now then the parameters will
	 * take effect when scan finishes.
	 */
938
	if (local->scanning)
Johannes Berg's avatar
Johannes Berg committed
939
940
		return;

941
942
943
944
945
946
947
	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);
948

949
950
951
952
953
954
		if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
		    (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
			return;

		conf->flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
	}
}

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);
	}
}

972
973
974
975
static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_managed *mgd = &sdata->u.mgd;
	struct sta_info *sta = NULL;
976
	bool authorized = false;
977
978
979
980

	if (!mgd->powersave)
		return false;

981
982
983
	if (mgd->broken_ap)
		return false;

984
985
986
987
988
989
990
991
992
993
	if (!mgd->associated)
		return false;

	if (mgd->flags & (IEEE80211_STA_BEACON_POLL |
			  IEEE80211_STA_CONNECTION_POLL))
		return false;

	rcu_read_lock();
	sta = sta_info_get(sdata, mgd->bssid);
	if (sta)
994
		authorized = test_sta_flag(sta, WLAN_STA_AUTHORIZED);
995
996
	rcu_read_unlock();

997
	return authorized;
998
999
}

1000
/* need to hold RTNL or interface lock */
1001
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
1002
1003
1004
{
	struct ieee80211_sub_if_data *sdata, *found = NULL;
	int count = 0;
1005
	int timeout;
1006
1007
1008
1009
1010
1011
1012

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

	list_for_each_entry(sdata, &local->interfaces, list) {
1013
		if (!ieee80211_sdata_running(sdata))
1014
			continue;
1015
1016
1017
1018
1019
1020
1021
1022
		if (sdata->vif.type == NL80211_IFTYPE_AP) {
			/* If an AP vif is found, then disable PS
			 * by setting the count to zero thereby setting
			 * ps_sdata to NULL.
			 */
			count = 0;
			break;
		}
1023
1024
1025
1026
1027
1028
		if (sdata->vif.type != NL80211_IFTYPE_STATION)
			continue;
		found = sdata;
		count++;
	}

1029
	if (count == 1 && ieee80211_powersave_allowed(found)) {
1030
		struct ieee80211_conf *conf = &local->hw.conf;
1031
1032
1033
		s32 beaconint_us;

		if (latency < 0)
Mark Gross's avatar
Mark Gross committed
1034
			latency = pm_qos_request(PM_QOS_NETWORK_LATENCY);
1035
1036
1037
1038

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

1039
		timeout = local->dynamic_ps_forced_timeout;
1040
1041
		if (timeout < 0) {
			/*
1042
1043
			 * Go to full PSM if the user configures a very low
			 * latency requirement.
1044
1045
1046
			 * The 2000 second value is there for compatibility
			 * until the PM_QOS_NETWORK_LATENCY is configured
			 * with real values.
1047
			 */
1048
1049
			if (latency > (1900 * USEC_PER_MSEC) &&
			    latency != (2000 * USEC_PER_SEC))
1050
				timeout = 0;
1051
1052
			else
				timeout = 100;
1053
		}
1054
1055
1056
1057
		local->dynamic_ps_user_timeout = timeout;
		if (!local->disable_dynamic_ps)
			conf->dynamic_ps_timeout =
				local->dynamic_ps_user_timeout;
1058

1059
		if (beaconint_us > latency) {
1060
			local->ps_sdata = NULL;
1061
		} else {
1062
			struct ieee80211_bss *bss;
1063
			int maxslp = 1;
1064
			u8 dtimper;
1065

1066
1067
1068
1069
1070
1071
1072
			bss = (void *)found->u.mgd.associated->priv;
			dtimper = bss->dtim_period;

			/* If the TIM IE is invalid, pretend the value is 1 */
			if (!dtimper)
				dtimper = 1;
			else if (dtimper > 1)
1073
1074
1075
				maxslp = min_t(int, dtimper,
						    latency / beaconint_us);

1076
			local->hw.conf.max_sleep_period = maxslp;
1077
			local->hw.conf.ps_dtim_period = dtimper;
1078
			local->ps_sdata = found;
1079
		}
1080
	} else {
1081
		local->ps_sdata = NULL;
1082
	}
1083
1084
1085
1086

	ieee80211_change_ps(local);
}

1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata)
{
	bool ps_allowed = ieee80211_powersave_allowed(sdata);

	if (sdata->vif.bss_conf.ps != ps_allowed) {
		sdata->vif.bss_conf.ps = ps_allowed;
		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_PS);
	}
}

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
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;
1118
	struct ieee80211_if_managed *ifmgd;
1119
1120
	unsigned long flags;
	int q;
1121
1122
1123
1124
1125

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

1126
1127
	ifmgd = &sdata->u.mgd;

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

1131
1132
1133
1134
	if (!local->disable_dynamic_ps &&
	    local->hw.conf.dynamic_ps_timeout > 0) {
		/* don't enter PS if TX frames are pending */
		if (drv_tx_frames_pending(local)) {
1135
1136
1137
1138
1139
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(
				  local->hw.conf.dynamic_ps_timeout));
			return;
		}
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157

		/*
		 * transmission can be stopped by others which leads to
		 * dynamic_ps_timer expiry. Postpone the ps timer if it
		 * is not the actual idle state.
		 */
		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
		for (q = 0; q < local->hw.queues; q++) {
			if (local->queue_stop_reasons[q]) {
				spin_unlock_irqrestore(&local->queue_stop_reason_lock,
						       flags);
				mod_timer(&local->dynamic_ps_timer, jiffies +
					  msecs_to_jiffies(
					  local->hw.conf.dynamic_ps_timeout));
				return;
			}
		}
		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
1158
1159
	}

1160
	if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
1161
	    !(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
1162
		netif_tx_stop_all_queues(sdata->dev);
1163

1164
1165
1166
1167
1168
1169
1170
1171
1172
		if (drv_tx_frames_pending(local))
			mod_timer(&local->dynamic_ps_timer, jiffies +
				  msecs_to_jiffies(
				  local->hw.conf.dynamic_ps_timeout));
		else {
			ieee80211_send_nullfunc(local, sdata, 1);
			/* Flush to get the tx status of nullfunc frame */
			drv_flush(local, false);
		}
1173
1174
	}

1175
1176
	if (!((local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) &&
	      (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) ||
1177
1178
1179
1180
1181
	    (ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED)) {
		ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED;
		local->hw.conf.flags |= IEEE80211_CONF_PS;
		ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
	}
1182

1183
1184
	if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)
		netif_tx_wake_all_queues(sdata->dev);
1185
1186
1187
1188
1189
1190
}

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

1191
	if (local->quiescing || local->suspended)
1192
1193
		return;

1194
	ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
1195
1196
}

Johannes Berg's avatar
Johannes Berg committed
1197
/* MLME */
1198
static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
1199
				     struct ieee80211_sub_if_data *sdata,
1200
1201
1202
				     u8 *wmm_param, size_t wmm_param_len)
{
	struct ieee80211_tx_queue_params params;
1203
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1204
1205
	size_t left;
	int count;
1206
	u8 *pos, uapsd_queues = 0;
1207

1208
	if (!local->ops->conf_tx)
1209
		return false;
1210

1211
	if (local->hw.queues < IEEE80211_NUM_ACS)
1212
		return false;
1213
1214

	if (!wmm_param)
1215
		return false;
1216

1217
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
1218
		return false;
1219
1220

	if (ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
1221
		uapsd_queues = ifmgd->uapsd_queues;
1222

1223
	count = wmm_param[6] & 0x0f;
1224
	if (count == ifmgd->wmm_last_param_set)
1225
		return false;
1226
	ifmgd->wmm_last_param_set = count;
1227
1228
1229
1230
1231
1232

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

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

1233
	sdata->wmm_acm = 0;
1234
1235
1236
	for (; left >= 4; left -= 4, pos += 4) {
		int aci = (pos[0] >> 5) & 0x03;
		int acm = (pos[0] >> 4) & 0x01;
1237
		bool uapsd = false;
1238
1239
1240
		int queue;

		switch (aci) {
1241
		case 1: /* AC_BK */
Johannes Berg's avatar
Johannes Berg committed
1242
			queue = 3;
Johannes Berg's avatar
Johannes Berg committed
1243
			if (acm)
1244
				sdata->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
1245
1246
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK)
				uapsd = true;
1247
			break;
1248
		case 2: /* AC_VI */
Johannes Berg's avatar
Johannes Berg committed
1249
			queue = 1;
Johannes Berg's avatar
Johannes Berg committed
1250
			if (acm)
1251
				sdata->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
1252
1253
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI)
				uapsd = true;
1254
			break;
1255
		case 3: /* AC_VO */
Johannes Berg's avatar
Johannes Berg committed
1256
			queue = 0;
Johannes Berg's avatar
Johannes Berg committed
1257
			if (acm)
1258
				sdata->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
1259
1260
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
				uapsd = true;
1261
			break;
1262
		case 0: /* AC_BE */
1263
		default:
Johannes Berg's avatar
Johannes Berg committed
1264
			queue = 2;
Johannes Berg's avatar
Johannes Berg committed
1265
			if (acm)
1266
				sdata->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
1267
1268
			if (uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE)
				uapsd = true;