mlme.c 68 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
31
32
33

#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
#define IEEE80211_AUTH_MAX_TRIES 3
#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
#define IEEE80211_ASSOC_MAX_TRIES 3
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

/*
 * beacon loss detection timeout
 * XXX: should depend on beacon interval
 */
#define IEEE80211_BEACON_LOSS_TIME	(2 * HZ)
/*
 * Time the connection can be idle before we probe
 * it to see if we can still talk to the AP.
 */
#define IEEE80211_CONNECTION_IDLE_TIME	(2 * HZ)
/*
 * Time we wait for a probe response after sending
 * a probe request because of beacon loss or for
 * checking the connection still works.
 */
#define IEEE80211_PROBE_WAIT		(HZ / 5)
51

52
53
54
#define TMR_RUNNING_TIMER	0
#define TMR_RUNNING_CHANSW	1

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/*
 * 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_rx_auth() */
	RX_MGMT_CFG80211_AUTH,

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

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

	/* caller must call cfg80211_send_disassoc() */
	RX_MGMT_CFG80211_DISASSOC,

	/* caller must call cfg80211_auth_timeout() & free work */
	RX_MGMT_CFG80211_AUTH_TO,

	/* caller must call cfg80211_assoc_timeout() & free work */
	RX_MGMT_CFG80211_ASSOC_TO,
};

84
/* utils */
85
86
87
88
89
static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
{
	WARN_ON(!mutex_is_locked(&ifmgd->mtx));
}

Johannes Berg's avatar
Johannes Berg committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/*
 * 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.
 */
static void run_again(struct ieee80211_if_managed *ifmgd,
			     unsigned long timeout)
{
	ASSERT_MGD_MTX(ifmgd);

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

110
111
112
113
114
115
116
117
118
static void mod_beacon_timer(struct ieee80211_sub_if_data *sdata)
{
	if (sdata->local->hw.flags & IEEE80211_HW_BEACON_FILTER)
		return;

	mod_timer(&sdata->u.mgd.bcn_mon_timer,
		  round_jiffies_up(jiffies + IEEE80211_BEACON_LOSS_TIME));
}

119
static int ecw2cw(int ecw)
Johannes Berg's avatar
Johannes Berg committed
120
{
121
	return (1 << ecw) - 1;
Johannes Berg's avatar
Johannes Berg committed
122
123
}

124
static int ieee80211_compatible_rates(struct ieee80211_bss *bss,
125
				      struct ieee80211_supported_band *sband,
126
				      u32 *rates)
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
{
	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;
}

145
146
147
148
149
150
151
/*
 * 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,
152
			       const u8 *bssid, u16 ap_ht_cap_flags)
153
154
155
156
157
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_supported_band *sband;
	struct sta_info *sta;
	u32 changed = 0;
158
	u16 ht_opmode;
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
	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:
181
182
183
				if (!(local->hw.conf.channel->flags &
				    IEEE80211_CHAN_NO_HT40PLUS))
					channel_type = NL80211_CHAN_HT40PLUS;
184
185
				break;
			case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
186
187
188
				if (!(local->hw.conf.channel->flags &
				    IEEE80211_CHAN_NO_HT40MINUS))
					channel_type = NL80211_CHAN_HT40MINUS;
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
				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();
204
		sta = sta_info_get(local, bssid);
205
206
207
208
209
210
211
212
213
214
		if (sta)
			rate_control_rate_update(local, sband, sta,
						 IEEE80211_RC_HT_CHANGED);
		rcu_read_unlock();
        }

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

215
	ht_opmode = le16_to_cpu(hti->operation_mode);
216
217

	/* if bss configuration changed store the new one */
218
219
	if (!sdata->ht_opmode_valid ||
	    sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
220
		changed |= BSS_CHANGED_HT;
221
		sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
222
		sdata->ht_opmode_valid = true;
223
224
225
226
227
	}

	return changed;
}

228
229
/* frame sending functions */

230
231
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
				 struct ieee80211_mgd_work *wk)
232
{
233
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
234
235
236
	struct ieee80211_local *local = sdata->local;
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
237
238
	u8 *pos;
	const u8 *ies, *ht_ie;
239
240
241
242
	int i, len, count, rates_len, supp_rates_len;
	u16 capab;
	int wmm = 0;
	struct ieee80211_supported_band *sband;
243
	u32 rates = 0;
244
245

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
246
247
			    sizeof(*mgmt) + 200 + wk->ie_len +
			    wk->ssid_len);
248
249
250
251
252
253
254
255
256
	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];

257
	capab = ifmgd->capab;
258
259
260
261
262
263
264
265

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

266
267
268
269
	if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
		capab |= WLAN_CAPABILITY_PRIVACY;
	if (wk->bss->wmm_used)
		wmm = 1;
270

271
272
273
274
275
	/* 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(wk->bss, sband, &rates);
276

277
278
279
	if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
	    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
		capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
280
281
282

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
283
	memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN);
284
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
285
	memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN);
286

287
	if (!is_zero_ether_addr(wk->prev_bssid)) {
288
289
290
291
292
293
		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);
294
		memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid,
295
296
297
298
299
300
		       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);
301
		mgmt->u.assoc_req.listen_interval =
302
303
304
305
				cpu_to_le16(local->hw.conf.listen_interval);
	}

	/* SSID */
306
	ies = pos = skb_put(skb, 2 + wk->ssid_len);
307
	*pos++ = WLAN_EID_SSID;
308
309
	*pos++ = wk->ssid_len;
	memcpy(pos, wk->ssid, wk->ssid_len);
310
311
312
313
314
315
316
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
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

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

364
365
366
	if (wk->ie_len && wk->ie) {
		pos = skb_put(skb, wk->ie_len);
		memcpy(pos, wk->ie, wk->ie_len);
367
368
	}

369
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) {
370
371
372
373
374
375
376
377
378
379
380
381
382
		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 */
383
384
385
386
387
388
	/*
	 * 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.
	 */
389
	if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) &&
390
	    sband->ht_cap.ht_supported &&
391
	    (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) &&
392
	    ht_ie[1] >= sizeof(struct ieee80211_ht_info) &&
393
	    (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) {
394
395
396
		struct ieee80211_ht_info *ht_info =
			(struct ieee80211_ht_info *)(ht_ie + 2);
		u16 cap = sband->ht_cap.cap;
397
398
399
		__le16 tmp;
		u32 flags = local->hw.conf.channel->flags;

400
401
		switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
		case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
402
			if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
403
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
404
405
406
				cap &= ~IEEE80211_HT_CAP_SGI_40;
			}
			break;
407
		case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
408
			if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
409
				cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
410
411
412
413
414
415
416
417
418
419
420
421
422
				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 */
423
424
425
		*pos++ = sband->ht_cap.ampdu_factor |
			 (sband->ht_cap.ampdu_density << 2);
		memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
426
427
	}

428
	ieee80211_tx_skb(sdata, skb, 0);
429
430
431
}


432
static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
Johannes Berg's avatar
Johannes Berg committed
433
434
					   const u8 *bssid, u16 stype, u16 reason,
					   void *cookie)
435
436
{
	struct ieee80211_local *local = sdata->local;
437
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
438
439
	struct sk_buff *skb;
	struct ieee80211_mgmt *mgmt;
440

441
	skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt));
442
	if (!skb) {
443
444
		printk(KERN_DEBUG "%s: failed to allocate buffer for "
		       "deauth/disassoc frame\n", sdata->dev->name);
445
446
447
448
449
450
		return;
	}
	skb_reserve(skb, local->hw.extra_tx_headroom);

	mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
	memset(mgmt, 0, 24);
451
	memcpy(mgmt->da, bssid, ETH_ALEN);
452
	memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
453
	memcpy(mgmt->bssid, bssid, ETH_ALEN);
454
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
455
	skb_put(skb, 2);
456
	/* u.deauth.reason_code == u.disassoc.reason_code */
457
458
	mgmt->u.deauth.reason_code = cpu_to_le16(reason);

459
	if (stype == IEEE80211_STYPE_DEAUTH)
Johannes Berg's avatar
Johannes Berg committed
460
		cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len, cookie);
461
	else
Johannes Berg's avatar
Johannes Berg committed
462
		cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len, cookie);
463
	ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED);
464
465
}

466
467
468
void ieee80211_send_pspoll(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata)
{
469
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
	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);
486
	pspoll->aid = cpu_to_le16(ifmgd->aid);
487
488
489
490

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

491
	memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN);
492
493
494
495
496
	memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN);

	ieee80211_tx_skb(sdata, skb, 0);
}

497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
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);
}

530
531
532
533
534
535
536
537
538
539
/* 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;

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

540
541
542
	mutex_lock(&ifmgd->mtx);
	if (!ifmgd->associated)
		goto out;
543
544

	sdata->local->oper_channel = sdata->local->csa_channel;
545
546
	ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);

547
	/* XXX: shouldn't really modify cfg80211-owned data! */
548
	ifmgd->associated->cbss.channel = sdata->local->oper_channel;
549
550
551

	ieee80211_wake_queues_by_reason(&sdata->local->hw,
					IEEE80211_QUEUE_STOP_REASON_CSA);
552
553
554
 out:
	ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
	mutex_unlock(&ifmgd->mtx);
555
556
557
558
559
560
561
562
}

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;

563
564
565
566
567
	if (sdata->local->quiescing) {
		set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
		return;
	}

568
	ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
569
570
571
572
573
574
575
576
577
578
}

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

579
580
581
	ASSERT_MGD_MTX(ifmgd);

	if (!ifmgd->associated)
582
583
		return;

584
	if (sdata->local->scanning)
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
		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) {
600
		ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
	} 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);
	}
}

632
633
634
635
636
637
/* 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
638
639
640
641
	/*
	 * If we are scanning right now then the parameters will
	 * take effect when scan finishes.
	 */
642
	if (local->scanning)
Johannes Berg's avatar
Johannes Berg committed
643
644
		return;

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
	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 */
672
void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
{
	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++;
	}

691
	if (count == 1 && found->u.mgd.powersave &&
692
	    found->u.mgd.associated && list_empty(&found->u.mgd.work_list) &&
693
694
	    !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
				    IEEE80211_STA_CONNECTION_POLL))) {
695
696
697
698
699
700
701
702
		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);

703
		if (beaconint_us > latency) {
704
			local->ps_sdata = NULL;
705
706
707
708
709
710
711
712
		} else {
			u8 dtimper = found->vif.bss_conf.dtim_period;
			int maxslp = 1;

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

713
			local->hw.conf.max_sleep_period = maxslp;
714
			local->ps_sdata = found;
715
		}
716
	} else {
717
		local->ps_sdata = NULL;
718
	}
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762

	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;

763
	if (local->quiescing || local->suspended)
764
765
		return;

766
	ieee80211_queue_work(&local->hw, &local->dynamic_ps_enable_work);
767
768
}

Johannes Berg's avatar
Johannes Berg committed
769
/* MLME */
770
static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
771
				     struct ieee80211_if_managed *ifmgd,
772
773
774
775
776
777
778
				     u8 *wmm_param, size_t wmm_param_len)
{
	struct ieee80211_tx_queue_params params;
	size_t left;
	int count;
	u8 *pos;

779
	if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED))
780
781
782
783
784
		return;

	if (!wmm_param)
		return;

785
786
787
	if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1)
		return;
	count = wmm_param[6] & 0x0f;
788
	if (count == ifmgd->wmm_last_param_set)
789
		return;
790
	ifmgd->wmm_last_param_set = count;
791
792
793
794
795
796
797
798
799
800
801
802
803

	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) {
804
		case 1: /* AC_BK */
Johannes Berg's avatar
Johannes Berg committed
805
			queue = 3;
Johannes Berg's avatar
Johannes Berg committed
806
			if (acm)
807
				local->wmm_acm |= BIT(1) | BIT(2); /* BK/- */
808
			break;
809
		case 2: /* AC_VI */
Johannes Berg's avatar
Johannes Berg committed
810
			queue = 1;
Johannes Berg's avatar
Johannes Berg committed
811
			if (acm)
812
				local->wmm_acm |= BIT(4) | BIT(5); /* CL/VI */
813
			break;
814
		case 3: /* AC_VO */
Johannes Berg's avatar
Johannes Berg committed
815
			queue = 0;
Johannes Berg's avatar
Johannes Berg committed
816
			if (acm)
817
				local->wmm_acm |= BIT(6) | BIT(7); /* VO/NC */
818
			break;
819
		case 0: /* AC_BE */
820
		default:
Johannes Berg's avatar
Johannes Berg committed
821
			queue = 2;
Johannes Berg's avatar
Johannes Berg committed
822
			if (acm)
823
				local->wmm_acm |= BIT(0) | BIT(3); /* BE/EE */
824
825
826
827
828
829
			break;
		}

		params.aifs = pos[0] & 0x0f;
		params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
		params.cw_min = ecw2cw(pos[1] & 0x0f);
830
		params.txop = get_unaligned_le16(pos + 2);
831
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
832
		printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
833
		       "cWmin=%d cWmax=%d txop=%d\n",
834
835
		       wiphy_name(local->hw.wiphy), queue, aci, acm,
		       params.aifs, params.cw_min, params.cw_max, params.txop);
836
#endif
837
		if (drv_conf_tx(local, queue, &params) && local->ops->conf_tx)
838
			printk(KERN_DEBUG "%s: failed to set TX queue "
839
840
			       "parameters for queue %d\n",
			       wiphy_name(local->hw.wiphy), queue);
841
842
843
	}
}

844
845
static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
					   u16 capab, bool erp_valid, u8 erp)
846
{
847
	struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
848
	u32 changed = 0;
849
850
851
852
853
854
855
856
857
858
859
860
861
	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);
862

863
864
865
	if (use_protection != bss_conf->use_cts_prot) {
		bss_conf->use_cts_prot = use_protection;
		changed |= BSS_CHANGED_ERP_CTS_PROT;
866
	}
867

868
869
	if (use_short_preamble != bss_conf->use_short_preamble) {
		bss_conf->use_short_preamble = use_short_preamble;
870
		changed |= BSS_CHANGED_ERP_PREAMBLE;
871
	}
872

873
874
875
	if (use_short_slot != bss_conf->use_short_slot) {
		bss_conf->use_short_slot = use_short_slot;
		changed |= BSS_CHANGED_ERP_SLOT;
876
877
878
879
880
	}

	return changed;
}

881
static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
882
				     struct ieee80211_bss *bss,
Johannes Berg's avatar
Johannes Berg committed
883
				     u32 bss_info_changed)
884
{
885
	struct ieee80211_local *local = sdata->local;
886

Johannes Berg's avatar
Johannes Berg committed
887
	bss_info_changed |= BSS_CHANGED_ASSOC;
888
889
890
891
	/* set timing information */
	sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
	sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
	sdata->vif.bss_conf.dtim_period = bss->dtim_period;
892

893
894
895
	bss_info_changed |= BSS_CHANGED_BEACON_INT;
	bss_info_changed |= ieee80211_handle_bss_capability(sdata,
		bss->cbss.capability, bss->has_erp_value, bss->erp_value);
896

897
898
	sdata->u.mgd.associated = bss;
	memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
899

900
901
902
903
	/* just to be sure */
	sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL |
				IEEE80211_STA_BEACON_POLL);

904
	ieee80211_led_assoc(local, 1);
905

906
	sdata->vif.bss_conf.assoc = 1;
907
908
909
910
911
	/*
	 * 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
912
	bss_info_changed |= BSS_CHANGED_BASIC_RATES;
913
914
915
916

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

Johannes Berg's avatar
Johannes Berg committed
917
	ieee80211_bss_info_change_notify(sdata, bss_info_changed);
918

Johannes Berg's avatar
Johannes Berg committed
919
920
921
	mutex_lock(&local->iflist_mtx);
	ieee80211_recalc_ps(local, -1);
	mutex_unlock(&local->iflist_mtx);
922

923
924
	netif_tx_start_all_queues(sdata->dev);
	netif_carrier_on(sdata->dev);
925
926
}

927
928
929
static enum rx_mgmt_action __must_check
ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata,
		       struct ieee80211_mgd_work *wk)
930
{
931
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
932
	struct ieee80211_local *local = sdata->local;
933

934
935
	wk->tries++;
	if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
936
		printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n",
937
		       sdata->dev->name, wk->bss->cbss.bssid);
938
939
940

		/*
		 * Most likely AP is not in the range so remove the
941
		 * bss struct for that AP.
942
		 */
943
		cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
944
945
946

		/*
		 * We might have a pending scan which had no chance to run yet
947
948
		 * due to work needing to be done. Hence, queue the STAs work
		 * again for that.
949
		 */
950
		ieee80211_queue_work(&local->hw, &ifmgd->work);
951
		return RX_MGMT_CFG80211_AUTH_TO;
952
953
	}

954
955
956
	printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n",
			sdata->dev->name, wk->bss->cbss.bssid,
			wk->tries);
957

958
959
	/*
	 * Direct probe is sent to broadcast address as some APs
960
961
	 * will not answer to direct packet in unassociated state.
	 */
962
963
964
	ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0);

	wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
Johannes Berg's avatar
Johannes Berg committed
965
	run_again(ifmgd, wk->timeout);
966

967
	return RX_MGMT_NONE;
Johannes Berg's avatar
Johannes Berg committed
968
}
969

970

971
972
973
static enum rx_mgmt_action __must_check
ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
		       struct ieee80211_mgd_work *wk)
974
{
975
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
976
	struct ieee80211_local *local = sdata->local;
977

978
979
	wk->tries++;
	if (wk->tries > IEEE80211_AUTH_MAX_TRIES) {
980
		printk(KERN_DEBUG "%s: authentication with AP %pM"
981
		       " timed out\n",
982
983
984
985
986
987
988
		       sdata->dev->name, wk->bss->cbss.bssid);

		/*
		 * Most likely AP is not in the range so remove the
		 * bss struct for that AP.
		 */
		cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);
989
990
991

		/*
		 * We might have a pending scan which had no chance to run yet
992
993
		 * due to work needing to be done. Hence, queue the STAs work
		 * again for that.
994
		 */
995
		ieee80211_queue_work(&local->hw, &ifmgd->work);
996
		return RX_MGMT_CFG80211_AUTH_TO;
997
998
	}

999
1000
1001
1002
	printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n",
	       sdata->dev->name, wk->bss->cbss.bssid, wk->tries);

	ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len,
Johannes Berg's avatar
Johannes Berg committed
1003
			    wk->bss->cbss.bssid, NULL, 0, 0);
1004
	wk->auth_transaction = 2;
1005

1006
	wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
Johannes Berg's avatar
Johannes Berg committed
1007
	run_again(ifmgd, wk->timeout);
1008

1009
	return RX_MGMT_NONE;
1010
1011
}

1012
static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
1013
{
1014
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1015
1016
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
1017
	u32 changed = 0, config_changed = 0;
1018
	u8 bssid[ETH_ALEN];
1019

1020
1021
	ASSERT_MGD_MTX(ifmgd);

1022
1023
1024
1025
1026
	if (WARN_ON(!ifmgd->associated))
		return;

	memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN);

1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
	ifmgd->associated = NULL;
	memset(ifmgd->bssid, 0, ETH_ALEN);

	/*
	 * we need to commit the associated = NULL change because the
	 * scan code uses that to determine whether this iface should
	 * go to/wake up from powersave or not -- and could otherwise
	 * wake the queues erroneously.
	 */
	smp_mb();

	/*
	 * Thus, we can only afterwards stop the queues -- to account
	 * for the case where another CPU is finishing a scan at this
	 * time -- we don't want the scan code to enable queues.
	 */
1043

1044
	netif_tx_stop_all_queues(sdata->dev);
1045
1046
	netif_carrier_off(sdata->dev);

1047
	rcu_read_lock();
1048
	sta = sta_info_get(local, bssid);
1049
1050
1051
	if (sta)
		ieee80211_sta_tear_down_BA_sessions(sta);
	rcu_read_unlock();
1052

1053
1054
1055
	changed |= ieee80211_reset_erp_info(sdata);

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

1059
1060
	ieee80211_set_wmm_default(sdata);

1061
1062
	ieee80211_recalc_idle(local);

1063
	/* channel(_type) changes are handled by ieee80211_hw_config */
Sujith's avatar
Sujith committed
1064
	local->oper_channel_type = NL80211_CHAN_NO_HT;
1065

1066
1067
1068
	/* on the next assoc, re-program HT parameters */
	sdata->ht_opmode_valid = false;

1069
1070
	local->power_constr_level = 0;

1071
1072
1073
	del_timer_sync(&local->dynamic_ps_timer);
	cancel_work_sync(&local->dynamic_ps_enable_work);

1074
1075
1076
1077
	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
1078

1079
	ieee80211_hw_config(local, config_changed);
1080
1081
1082

	/* And the BSSID changed -- not very interesting here */
	changed |= BSS_CHANGED_BSSID;
Johannes Berg's avatar
Johannes Berg committed
1083
	ieee80211_bss_info_change_notify(sdata, changed);
1084
1085
1086

	rcu_read_lock();

1087
	sta = sta_info_get(local, bssid);
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
	if (!sta) {
		rcu_read_unlock();
		return;
	}

	sta_info_unlink(&sta);

	rcu_read_unlock();

	sta_info_destroy(sta);
1098
}
1099

1100
1101
1102
static enum rx_mgmt_action __must_check
ieee80211_associate(struct ieee80211_sub_if_data *sdata,
		    struct ieee80211_mgd_work *wk)
1103
{
1104
	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1105
	struct ieee80211_local *local = sdata->local;
1106

1107
1108
	wk->tries++;
	if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) {
1109
		printk(KERN_DEBUG "%s: association with AP %pM"
1110
		       " timed out\n",
1111
1112
1113
1114
1115
1116
1117
1118
		       sdata->dev->name, wk->bss->cbss.bssid);

		/*
		 * Most likely AP is not in the range so remove the
		 * bss struct for that AP.
		 */
		cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss);

1119
1120
		/*
		 * We might have a pending scan which had no chance to run yet
1121
1122
		 * due to work needing to be done. Hence, queue the STAs work
		 * again for that.
1123
		 */
1124
		ieee80211_queue_work(&local->hw, &ifmgd->work);