rt2x00mac.c 19.3 KB
Newer Older
1
/*
2
	Copyright (C) 2004 - 2008 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
78
79
80
81
82
83
84
	skb->do_not_encrypt = 1;

	/*
	 * RTS/CTS frame should use the length of the frame plus any
	 * encryption overhead that will be added by the hardware.
	 */
	if (!frag_skb->do_not_encrypt)
		data_length += rt2x00crypto_tx_overhead(tx_info);

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:
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
		/*
		 * 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;
	}
247
248
249
250
251
252
253
254
255

	/*
	 * 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];
256
		if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags))
257
258
259
260
			break;
	}

	if (unlikely(i == queue->limit))
261
262
		return -ENOBUFS;

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

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

	spin_lock_init(&intf->lock);
274
	spin_lock_init(&intf->seqlock);
275
276
	intf->beacon = entry;

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

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

288
289
290
291
292
293
294
	/*
	 * 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;

295
296
297
298
299
300
301
302
	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;
303
	struct rt2x00_intf *intf = vif_to_intf(conf->vif);
304
305

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

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

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

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

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

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

	/*
349
350
351
352
353
	 * 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.
354
	 */
355
356
357
	if (conf->radio_enabled) {
		/* For programming the values, we have to turn RX off */
		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
358

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

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

370
371
372
373
374
375
376
377
378
379
380
		/*
		 * 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);

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

	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_config);

392
393
int rt2x00mac_config_interface(struct ieee80211_hw *hw,
			       struct ieee80211_vif *vif,
394
395
396
			       struct ieee80211_if_conf *conf)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
397
	struct rt2x00_intf *intf = vif_to_intf(vif);
398
399
	int update_bssid = 0;
	int status = 0;
400
401

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

408
	spin_lock(&intf->lock);
409
410

	/*
411
412
	 * conf->bssid can be NULL if coming from the internal
	 * beacon update routine.
413
	 */
414
415
	if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
		update_bssid = 1;
416
		memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
417
	}
418
419

	spin_unlock(&intf->lock);
420

421
422
423
424
425
426
	/*
	 * 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.
	 */
427
428
	rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
			      update_bssid ? conf->bssid : NULL);
429

430
	/*
431
	 * Update the beacon.
432
	 */
433
434
	if (conf->changed & IEEE80211_IFCC_BEACON)
		status = rt2x00queue_update_beacon(rt2x00dev, vif);
435
436
437
438
439

	return status;
}
EXPORT_SYMBOL_GPL(rt2x00mac_config_interface);

Ivo van Doorn's avatar
Ivo van Doorn committed
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
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);
479
	else
480
		queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work);
Ivo van Doorn's avatar
Ivo van Doorn committed
481
482
483
}
EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter);

484
485
486
487
488
489
#ifdef CONFIG_RT2X00_LIB_CRYPTO
int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
		      const u8 *local_address, const u8 *address,
		      struct ieee80211_key_conf *key)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
490
	struct ieee80211_sta *sta;
491
492
493
494
495
	int (*set_key) (struct rt2x00_dev *rt2x00dev,
			struct rt2x00lib_crypto *crypto,
			struct ieee80211_key_conf *key);
	struct rt2x00lib_crypto crypto;

496
497
498
	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
		return 0;
	else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
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
530
531
532
533
534
535
536
537
538
539
		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
		crypto.bssidx =
		    local_address[5] & (rt2x00dev->ops->max_ap_intf - 1);

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

	crypto.cmd = cmd;
	crypto.address = address;

	if (crypto.cipher == CIPHER_TKIP) {
		if (key->keylen > NL80211_TKIP_DATA_OFFSET_ENCR_KEY)
			memcpy(&crypto.key,
			       &key->key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY],
			       sizeof(crypto.key));

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

		if (key->keylen > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY)
			memcpy(&crypto.rx_mic,
			       &key->key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY],
			       sizeof(crypto.rx_mic));
	} else
		memcpy(&crypto.key, &key->key[0], key->keylen);

540
541
542
543
544
545
546
547
548
549
550
	/*
	 * Discover the Association ID from mac80211.
	 * Some drivers need this information when updating the
	 * hardware key (either adding or removing).
	 */
	rcu_read_lock();
	sta = ieee80211_find_sta(hw, address);
	if (sta)
		crypto.aid = sta->aid;
	rcu_read_unlock();

551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
	/*
	 * 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).
	 */
567
568
	if (cmd == SET_KEY)
		key->hw_key_idx = 0;
569
570
571
572
573
574
575
576
577
578
579
580
581
582

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

583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
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;

605
	for (i = 0; i < rt2x00dev->ops->tx_queues; i++) {
606
607
608
		stats[i].len = rt2x00dev->tx[i].length;
		stats[i].limit = rt2x00dev->tx[i].limit;
		stats[i].count = rt2x00dev->tx[i].count;
609
	}
610
611
612
613
614

	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);

615
616
617
618
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
				struct ieee80211_vif *vif,
				struct ieee80211_bss_conf *bss_conf,
				u32 changes)
619
620
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
621
	struct rt2x00_intf *intf = vif_to_intf(vif);
Ivo van Doorn's avatar
Ivo van Doorn committed
622
	unsigned int delayed = 0;
623
624

	/*
625
626
627
628
	 * 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.
629
	 */
630
631
	if (changes & BSS_CHANGED_ASSOC) {
		rt2x00dev->link.count = 0;
632

633
634
635
636
		if (bss_conf->assoc)
			rt2x00dev->intf_associated++;
		else
			rt2x00dev->intf_associated--;
637
638
639
640
641
642

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

645
	/*
646
647
	 * When the erp information has changed, we should perform
	 * additional configuration steps. For all other changes we are done.
648
	 */
649
	if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
Ivo van Doorn's avatar
Ivo van Doorn committed
650
651
652
653
654
		if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
			rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
		else
			delayed |= DELAYED_CONFIG_ERP;
	}
655

656
	spin_lock(&intf->lock);
Ivo van Doorn's avatar
Ivo van Doorn committed
657
658
	if (delayed) {
		intf->delayed_flags |= delayed;
659
		schedule_work(&rt2x00dev->intf_work);
Ivo van Doorn's avatar
Ivo van Doorn committed
660
	}
661
	spin_unlock(&intf->lock);
662
}
663
EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
664

Johannes Berg's avatar
Johannes Berg committed
665
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
666
667
668
		      const struct ieee80211_tx_queue_params *params)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
669
	struct data_queue *queue;
670

671
672
	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
	if (unlikely(!queue))
673
674
675
676
677
678
		return -EINVAL;

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

684
	if (params->cw_max > 0)
685
		queue->cw_max = fls(params->cw_max);
686
	else
687
		queue->cw_max = 10; /* cw_min: 2^10 = 1024. */
688

689
	queue->aifs = params->aifs;
690
	queue->txop = params->txop;
691
692

	INFO(rt2x00dev,
693
694
	     "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);
695
696
697
698

	return 0;
}
EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx);