rt2x00mac.c 19.2 KB
Newer Older
1
/*
2
	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
	<http://rt2x00.serialmonkey.com>

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the
	Free Software Foundation, Inc.,
	59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
	Module: rt2x00mac
	Abstract: rt2x00 generic mac80211 routines.
 */

#include <linux/kernel.h>
#include <linux/module.h>

#include "rt2x00.h"
#include "rt2x00lib.h"

static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
33
				struct data_queue *queue,
34
				struct sk_buff *frag_skb)
35
{
36
37
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb);
	struct ieee80211_tx_info *rts_info;
38
	struct sk_buff *skb;
39
	unsigned int data_length;
40
	int retval = 0;
41

42
	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
43
		data_length = sizeof(struct ieee80211_cts);
44
	else
45
		data_length = sizeof(struct ieee80211_rts);
46

47
	skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom);
48
	if (unlikely(!skb)) {
49
		WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n");
50
		return -ENOMEM;
51
52
53
	}

	skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom);
54
	skb_put(skb, data_length);
55

56
57
58
59
60
61
62
63
64
65
66
	/*
	 * Copy TX information over from original frame to
	 * RTS/CTS frame. Note that we set the no encryption flag
	 * since we don't want this frame to be encrypted.
	 * RTS frames should be acked, while CTS-to-self frames
	 * should not. The ready for TX flag is cleared to prevent
	 * it being automatically send when the descriptor is
	 * written to the hardware.
	 */
	memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
	rts_info = IEEE80211_SKB_CB(skb);
67
68
	rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
	rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT;
69
70
	rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;

71
	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
72
73
74
75
		rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
	else
		rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;

76
77
	/* Disable hardware encryption */
	rts_info->control.hw_key = NULL;
78
79
80
81
82

	/*
	 * RTS/CTS frame should use the length of the frame plus any
	 * encryption overhead that will be added by the hardware.
	 */
83
	data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb);
84

85
	if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
86
		ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
87
					frag_skb->data, data_length, tx_info,
88
89
					(struct ieee80211_cts *)(skb->data));
	else
90
		ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif,
91
				  frag_skb->data, data_length, tx_info,
92
93
				  (struct ieee80211_rts *)(skb->data));

94
95
	retval = rt2x00queue_write_tx_frame(queue, skb);
	if (retval) {
96
		dev_kfree_skb_any(skb);
97
98
99
		WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n");
	}

100
	return retval;
101
102
}

103
int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
104
105
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
106
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
107
	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
108
	enum data_queue_qid qid = skb_get_queue_mapping(skb);
109
	struct data_queue *queue;
110
111
	u16 frame_control;

112
113
114
115
116
117
	/*
	 * Mac80211 might be calling this function while we are trying
	 * to remove the device or perhaps suspending it.
	 * Note that we can only stop the TX queues inside the TX path
	 * due to possible race conditions in mac80211.
	 */
118
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
119
		goto exit_fail;
120

121
	/*
122
	 * Determine which queue to put packet on.
123
	 */
124
	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
125
	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
126
		queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM);
127
	else
128
		queue = rt2x00queue_get_queue(rt2x00dev, qid);
129
	if (unlikely(!queue)) {
130
131
		ERROR(rt2x00dev,
		      "Attempt to send packet over invalid queue %d.\n"
132
		      "Please file bug report to %s.\n", qid, DRV_PROJECT);
Ivo van Doorn's avatar
Ivo van Doorn committed
133
		goto exit_fail;
134
135
136
	}

	/*
137
138
139
	 * If CTS/RTS is required. create and queue that frame first.
	 * Make sure we have at least enough entries available to send
	 * this CTS/RTS frame as well as the data frame.
140
141
	 * Note that when the driver has set the set_rts_threshold()
	 * callback function it doesn't need software generation of
142
	 * either RTS or CTS-to-self frame and handles everything
143
	 * inside the hardware.
144
145
	 */
	frame_control = le16_to_cpu(ieee80211hdr->frame_control);
146
147
	if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
						IEEE80211_TX_RC_USE_CTS_PROTECT)) &&
148
	    !rt2x00dev->ops->hw->set_rts_threshold) {
149
150
		if (rt2x00queue_available(queue) <= 1)
			goto exit_fail;
151

152
153
		if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb))
			goto exit_fail;
154
155
	}

156
157
158
	if (rt2x00queue_write_tx_frame(queue, skb))
		goto exit_fail;

159
	if (rt2x00queue_threshold(queue))
160
		ieee80211_stop_queue(rt2x00dev->hw, qid);
161
162

	return NETDEV_TX_OK;
163
164
165
166
167

 exit_fail:
	ieee80211_stop_queue(rt2x00dev->hw, qid);
	dev_kfree_skb_any(skb);
	return NETDEV_TX_OK;
168
169
170
171
172
173
174
}
EXPORT_SYMBOL_GPL(rt2x00mac_tx);

int rt2x00mac_start(struct ieee80211_hw *hw)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;

175
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
176
177
		return 0;

178
	return rt2x00lib_start(rt2x00dev);
179
180
181
182
183
184
185
}
EXPORT_SYMBOL_GPL(rt2x00mac_start);

void rt2x00mac_stop(struct ieee80211_hw *hw)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;

186
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
187
188
		return;

189
	rt2x00lib_stop(rt2x00dev);
190
191
192
193
194
195
196
}
EXPORT_SYMBOL_GPL(rt2x00mac_stop);

int rt2x00mac_add_interface(struct ieee80211_hw *hw,
			    struct ieee80211_if_init_conf *conf)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
197
	struct rt2x00_intf *intf = vif_to_intf(conf->vif);
198
	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
199
200
	struct queue_entry *entry = NULL;
	unsigned int i;
201
202

	/*
203
204
	 * Don't allow interfaces to be added
	 * the device has disappeared.
205
	 */
206
207
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
	    !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags))
208
209
		return -ENODEV;

210
	switch (conf->type) {
211
	case NL80211_IFTYPE_AP:
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
		/*
		 * We don't support mixed combinations of
		 * sta and ap interfaces.
		 */
		if (rt2x00dev->intf_sta_count)
			return -ENOBUFS;

		/*
		 * Check if we exceeded the maximum amount
		 * of supported interfaces.
		 */
		if (rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf)
			return -ENOBUFS;

		break;
227
228
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_ADHOC:
Andrey Yurovsky's avatar
Andrey Yurovsky committed
229
	case NL80211_IFTYPE_MESH_POINT:
Ivo van Doorn's avatar
Ivo van Doorn committed
230
	case NL80211_IFTYPE_WDS:
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
		/*
		 * We don't support mixed combinations of
		 * sta and ap interfaces.
		 */
		if (rt2x00dev->intf_ap_count)
			return -ENOBUFS;

		/*
		 * Check if we exceeded the maximum amount
		 * of supported interfaces.
		 */
		if (rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf)
			return -ENOBUFS;

		break;
	default:
		return -EINVAL;
	}
249
250
251
252
253
254
255
256
257

	/*
	 * Loop through all beacon queues to find a free
	 * entry. Since there are as much beacon entries
	 * as the maximum interfaces, this search shouldn't
	 * fail.
	 */
	for (i = 0; i < queue->limit; i++) {
		entry = &queue->entries[i];
258
		if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
259
260
261
262
			break;
	}

	if (unlikely(i == queue->limit))
263
264
		return -ENOBUFS;

265
266
267
268
269
	/*
	 * We are now absolutely sure the interface can be created,
	 * increase interface count and start initialization.
	 */

270
	if (conf->type == NL80211_IFTYPE_AP)
271
272
273
274
275
		rt2x00dev->intf_ap_count++;
	else
		rt2x00dev->intf_sta_count++;

	spin_lock_init(&intf->lock);
276
	spin_lock_init(&intf->seqlock);
277
278
	intf->beacon = entry;

279
	if (conf->type == NL80211_IFTYPE_AP)
280
281
		memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
	memcpy(&intf->mac, conf->mac_addr, ETH_ALEN);
282
283
284

	/*
	 * The MAC adddress must be configured after the device
285
286
	 * has been initialized. Otherwise the device can reset
	 * the MAC registers.
287
	 */
288
	rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL);
289

290
291
292
293
294
295
296
	/*
	 * Some filters depend on the current working mode. We can force
	 * an update during the next configure_filter() run by mac80211 by
	 * resetting the current packet_filter state.
	 */
	rt2x00dev->packet_filter = 0;

297
298
299
300
301
302
303
304
	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_add_interface);

void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
				struct ieee80211_if_init_conf *conf)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
305
	struct rt2x00_intf *intf = vif_to_intf(conf->vif);
306
307

	/*
308
309
310
	 * Don't allow interfaces to be remove while
	 * either the device has disappeared or when
	 * no interface is present.
311
	 */
312
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
313
314
	    (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) ||
	    (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count))
315
316
		return;

317
	if (conf->type == NL80211_IFTYPE_AP)
318
319
320
321
322
323
324
325
		rt2x00dev->intf_ap_count--;
	else
		rt2x00dev->intf_sta_count--;

	/*
	 * Release beacon entry so it is available for
	 * new interfaces again.
	 */
326
	clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags);
327
328
329
330
331

	/*
	 * Make sure the bssid and mac address registers
	 * are cleared to prevent false ACKing of frames.
	 */
332
	rt2x00lib_config_intf(rt2x00dev, intf,
333
			      NL80211_IFTYPE_UNSPECIFIED, NULL, NULL);
334
335
336
}
EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);

337
int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
338
339
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
340
	struct ieee80211_conf *conf = &hw->conf;
341
	int status;
342
343

	/*
344
345
	 * Mac80211 might be calling this function while we are trying
	 * to remove the device or perhaps suspending it.
346
	 */
347
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
348
349
350
		return 0;

	/*
351
352
353
354
355
	 * Only change device state when the radio is enabled. It does not
	 * matter what parameters we have configured when the radio is disabled
	 * because we won't be able to send or receive anyway. Also note that
	 * some configuration parameters (e.g. channel and antenna values) can
	 * only be set when the radio is enabled.
356
	 */
357
358
359
	if (conf->radio_enabled) {
		/* For programming the values, we have to turn RX off */
		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
360

361
362
363
364
		/* Enable the radio */
		status = rt2x00lib_enable_radio(rt2x00dev);
		if (unlikely(status))
			return status;
365

366
367
368
369
		/*
		 * When we've just turned on the radio, we want to reprogram
		 * everything to ensure a consistent state
		 */
370
		rt2x00lib_config(rt2x00dev, conf, changed);
371

372
373
374
375
376
377
378
379
380
381
382
		/*
		 * The radio was enabled, configure the antenna to the
		 * default settings, the link tuner will later start
		 * continue configuring the antenna based on the software
		 * diversity. But for non-diversity configurations, we need
		 * to have configured the correct state now.
		 */
		if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED)
			rt2x00lib_config_antenna(rt2x00dev,
						 &rt2x00dev->default_ant);

383
		/* Turn RX back on */
384
		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
385
386
387
388
	} else {
		/* Disable the radio */
		rt2x00lib_disable_radio(rt2x00dev);
	}
389
390
391
392
393

	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_config);

Ivo van Doorn's avatar
Ivo van Doorn committed
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
				unsigned int changed_flags,
				unsigned int *total_flags,
				int mc_count, struct dev_addr_list *mc_list)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;

	/*
	 * Mask off any flags we are going to ignore
	 * from the total_flags field.
	 */
	*total_flags &=
	    FIF_ALLMULTI |
	    FIF_FCSFAIL |
	    FIF_PLCPFAIL |
	    FIF_CONTROL |
	    FIF_OTHER_BSS |
	    FIF_PROMISC_IN_BSS;

	/*
	 * Apply some rules to the filters:
	 * - Some filters imply different filters to be set.
	 * - Some things we can't filter out at all.
	 * - Multicast filter seems to kill broadcast traffic so never use it.
	 */
	*total_flags |= FIF_ALLMULTI;
	if (*total_flags & FIF_OTHER_BSS ||
	    *total_flags & FIF_PROMISC_IN_BSS)
		*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;

	/*
	 * Check if there is any work left for us.
	 */
	if (rt2x00dev->packet_filter == *total_flags)
		return;
	rt2x00dev->packet_filter = *total_flags;

	if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
		rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags);
433
	else
434
		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
Ivo van Doorn's avatar
Ivo van Doorn committed
435
436
437
}
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);

438
#ifdef CONFIG_RT2X00_LIB_CRYPTO
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len)
{
	if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
		memcpy(&crypto->key,
		       &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
		       sizeof(crypto->key));

	if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY)
		memcpy(&crypto->tx_mic,
		       &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY],
		       sizeof(crypto->tx_mic));

	if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
		memcpy(&crypto->rx_mic,
		       &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
		       sizeof(crypto->rx_mic));
}

457
int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
458
		      struct ieee80211_vif *vif, struct ieee80211_sta *sta,
459
460
461
		      struct ieee80211_key_conf *key)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
462
	struct rt2x00_intf *intf = vif_to_intf(vif);
463
464
465
466
	int (*set_key) (struct rt2x00_dev *rt2x00dev,
			struct rt2x00lib_crypto *crypto,
			struct ieee80211_key_conf *key);
	struct rt2x00lib_crypto crypto;
467
468
	static const u8 bcast_addr[ETH_ALEN] =
		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, };
469

470
471
472
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
		return 0;
	else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
473
474
475
476
477
478
479
480
481
482
483
484
485
		return -EOPNOTSUPP;
	else if (key->keylen > 32)
		return -ENOSPC;

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

	/*
	 * When in STA mode, bssidx is always 0 otherwise local_address[5]
	 * contains the bss number, see BSS_ID_MASK comments for details.
	 */
	if (rt2x00dev->intf_sta_count)
		crypto.bssidx = 0;
	else
486
		crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1);
487
488
489
490
491
492

	crypto.cipher = rt2x00crypto_key_to_cipher(key);
	if (crypto.cipher == CIPHER_NONE)
		return -EOPNOTSUPP;

	crypto.cmd = cmd;
493
494
495
496
497
498
499

	if (sta) {
		/* some drivers need the AID */
		crypto.aid = sta->aid;
		crypto.address = sta->addr;
	} else
		crypto.address = bcast_addr;
500

501
502
503
	if (crypto.cipher == CIPHER_TKIP)
		memcpy_tkip(&crypto, &key->key[0], key->keylen);
	else
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
		memcpy(&crypto.key, &key->key[0], key->keylen);
	/*
	 * Each BSS has a maximum of 4 shared keys.
	 * Shared key index values:
	 *	0) BSS0 key0
	 *	1) BSS0 key1
	 *	...
	 *	4) BSS1 key0
	 *	...
	 *	8) BSS2 key0
	 *	...
	 * Both pairwise as shared key indeces are determined by
	 * driver. This is required because the hardware requires
	 * keys to be assigned in correct order (When key 1 is
	 * provided but key 0 is not, then the key is not found
	 * by the hardware during RX).
	 */
521
522
	if (cmd == SET_KEY)
		key->hw_key_idx = 0;
523
524
525
526
527
528
529
530
531
532
533
534
535
536

	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
		set_key = rt2x00dev->ops->lib->config_pairwise_key;
	else
		set_key = rt2x00dev->ops->lib->config_shared_key;

	if (!set_key)
		return -EOPNOTSUPP;

	return set_key(rt2x00dev, &crypto, key);
}
EXPORT_SYMBOL_GPL(rt2x00mac_set_key);
#endif /* CONFIG_RT2X00_LIB_CRYPTO */

537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
			struct ieee80211_low_level_stats *stats)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;

	/*
	 * The dot11ACKFailureCount, dot11RTSFailureCount and
	 * dot11RTSSuccessCount are updated in interrupt time.
	 * dot11FCSErrorCount is updated in the link tuner.
	 */
	memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats));

	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_stats);

int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
			   struct ieee80211_tx_queue_stats *stats)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	unsigned int i;

559
	for (i = 0; i < rt2x00dev->ops->tx_queues; i++) {
560
561
562
		stats[i].len = rt2x00dev->tx[i].length;
		stats[i].limit = rt2x00dev->tx[i].limit;
		stats[i].count = rt2x00dev->tx[i].count;
563
	}
564
565
566
567
568

	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);

569
570
571
572
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
				struct ieee80211_vif *vif,
				struct ieee80211_bss_conf *bss_conf,
				u32 changes)
573
574
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
575
	struct rt2x00_intf *intf = vif_to_intf(vif);
Ivo van Doorn's avatar
Ivo van Doorn committed
576
	unsigned int delayed = 0;
577
578
579
580
581
582
583
584
585
586
587
588
589
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
	int update_bssid = 0;

	/*
	 * Mac80211 might be calling this function while we are trying
	 * to remove the device or perhaps suspending it.
	 */
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
		return;

	spin_lock(&intf->lock);

	/*
	 * conf->bssid can be NULL if coming from the internal
	 * beacon update routine.
	 */
	if (changes & BSS_CHANGED_BSSID) {
		update_bssid = 1;
		memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN);
	}

	spin_unlock(&intf->lock);

	/*
	 * Call rt2x00_config_intf() outside of the spinlock context since
	 * the call will sleep for USB drivers. By using the ieee80211_if_conf
	 * values as arguments we make keep access to rt2x00_intf thread safe
	 * even without the lock.
	 */
	if (changes & BSS_CHANGED_BSSID)
		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
				      update_bssid ? bss_conf->bssid : NULL);

	/*
	 * Update the beacon.
	 */
	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED))
		rt2x00queue_update_beacon(rt2x00dev, vif,
					  bss_conf->enable_beacon);
615
616

	/*
617
618
619
620
	 * When the association status has changed we must reset the link
	 * tuner counter. This is because some drivers determine if they
	 * should perform link tuning based on the number of seconds
	 * while associated or not associated.
621
	 */
622
623
	if (changes & BSS_CHANGED_ASSOC) {
		rt2x00dev->link.count = 0;
624

625
626
627
628
		if (bss_conf->assoc)
			rt2x00dev->intf_associated++;
		else
			rt2x00dev->intf_associated--;
629
630
631
632
633
634

		if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
			rt2x00leds_led_assoc(rt2x00dev,
					     !!rt2x00dev->intf_associated);
		else
			delayed |= DELAYED_LED_ASSOC;
635
	}
636

637
	/*
638
639
	 * When the erp information has changed, we should perform
	 * additional configuration steps. For all other changes we are done.
640
	 */
641
	if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
Ivo van Doorn's avatar
Ivo van Doorn committed
642
643
644
645
646
		if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
			rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
		else
			delayed |= DELAYED_CONFIG_ERP;
	}
647

648
	spin_lock(&intf->lock);
Ivo van Doorn's avatar
Ivo van Doorn committed
649
650
	if (delayed) {
		intf->delayed_flags |= delayed;
651
		schedule_work(&rt2x00dev->intf_work);
Ivo van Doorn's avatar
Ivo van Doorn committed
652
	}
653
	spin_unlock(&intf->lock);
654
}
655
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
656

Johannes Berg's avatar
Johannes Berg committed
657
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
658
659
660
		      const struct ieee80211_tx_queue_params *params)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
661
	struct data_queue *queue;
662

663
664
	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
	if (unlikely(!queue))
665
666
667
668
669
670
		return -EINVAL;

	/*
	 * The passed variables are stored as real value ((2^n)-1).
	 * Ralink registers require to know the bit number 'n'.
	 */
671
	if (params->cw_min > 0)
672
		queue->cw_min = fls(params->cw_min);
673
	else
674
		queue->cw_min = 5; /* cw_min: 2^5 = 32. */
675

676
	if (params->cw_max > 0)
677
		queue->cw_max = fls(params->cw_max);
678
	else
679
		queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
680

681
	queue->aifs = params->aifs;
682
	queue->txop = params->txop;
683
684

	INFO(rt2x00dev,
685
686
	     "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n",
	     queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop);
687
688
689
690

	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);