2 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
3 * Copyright (c) 2004-2005 Atheros Communications, Inc.
4 * Copyright (c) 2006 Devicescape Software, Inc.
5 * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
6 * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
7 * Copyright (c) 2010 Bruno Randolf <br1@einfach.org>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
19 * redistribution must be conditioned upon including a substantially
20 * similar Disclaimer requirement for further binary redistribution.
21 * 3. Neither the names of the above-listed copyright holders nor the names
22 * of any contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
25 * Alternatively, this software may be distributed under the terms of the
26 * GNU General Public License ("GPL") version 2 as published by the Free
27 * Software Foundation.
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
33 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
34 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
35 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
38 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
40 * THE POSSIBILITY OF SUCH DAMAGES.
44 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
46 #include <net/mac80211.h>
47 #include <asm/unaligned.h>
53 /********************\
54 * Mac80211 functions *
55 \********************/
58 ath5k_tx(struct ieee80211_hw
*hw
, struct ieee80211_tx_control
*control
,
61 struct ath5k_hw
*ah
= hw
->priv
;
62 u16 qnum
= skb_get_queue_mapping(skb
);
64 if (WARN_ON(qnum
>= ah
->ah_capabilities
.cap_queues
.q_tx_num
)) {
65 ieee80211_free_txskb(hw
, skb
);
69 ath5k_tx_queue(hw
, skb
, &ah
->txqs
[qnum
], control
);
74 ath5k_add_interface(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
)
76 struct ath5k_hw
*ah
= hw
->priv
;
78 struct ath5k_vif
*avf
= (void *)vif
->drv_priv
;
80 mutex_lock(&ah
->lock
);
82 if ((vif
->type
== NL80211_IFTYPE_AP
||
83 vif
->type
== NL80211_IFTYPE_ADHOC
)
84 && (ah
->num_ap_vifs
+ ah
->num_adhoc_vifs
) >= ATH_BCBUF
) {
89 /* Don't allow other interfaces if one ad-hoc is configured.
90 * TODO: Fix the problems with ad-hoc and multiple other interfaces.
91 * We would need to operate the HW in ad-hoc mode to allow TSF updates
92 * for the IBSS, but this breaks with additional AP or STA interfaces
94 if (ah
->num_adhoc_vifs
||
95 (ah
->nvifs
&& vif
->type
== NL80211_IFTYPE_ADHOC
)) {
96 ATH5K_ERR(ah
, "Only one single ad-hoc interface is allowed.\n");
102 case NL80211_IFTYPE_AP
:
103 case NL80211_IFTYPE_STATION
:
104 case NL80211_IFTYPE_ADHOC
:
105 case NL80211_IFTYPE_MESH_POINT
:
106 avf
->opmode
= vif
->type
;
114 ATH5K_DBG(ah
, ATH5K_DEBUG_MODE
, "add interface mode %d\n", avf
->opmode
);
116 /* Assign the vap/adhoc to a beacon xmit slot. */
117 if ((avf
->opmode
== NL80211_IFTYPE_AP
) ||
118 (avf
->opmode
== NL80211_IFTYPE_ADHOC
) ||
119 (avf
->opmode
== NL80211_IFTYPE_MESH_POINT
)) {
122 WARN_ON(list_empty(&ah
->bcbuf
));
123 avf
->bbuf
= list_first_entry(&ah
->bcbuf
, struct ath5k_buf
,
125 list_del(&avf
->bbuf
->list
);
128 for (slot
= 0; slot
< ATH_BCBUF
; slot
++) {
129 if (!ah
->bslot
[slot
]) {
134 BUG_ON(ah
->bslot
[avf
->bslot
] != NULL
);
135 ah
->bslot
[avf
->bslot
] = vif
;
136 if (avf
->opmode
== NL80211_IFTYPE_AP
)
138 else if (avf
->opmode
== NL80211_IFTYPE_ADHOC
)
139 ah
->num_adhoc_vifs
++;
140 else if (avf
->opmode
== NL80211_IFTYPE_MESH_POINT
)
144 /* Any MAC address is fine, all others are included through the
147 ath5k_hw_set_lladdr(ah
, vif
->addr
);
149 ath5k_update_bssid_mask_and_opmode(ah
, vif
);
152 mutex_unlock(&ah
->lock
);
158 ath5k_remove_interface(struct ieee80211_hw
*hw
,
159 struct ieee80211_vif
*vif
)
161 struct ath5k_hw
*ah
= hw
->priv
;
162 struct ath5k_vif
*avf
= (void *)vif
->drv_priv
;
165 mutex_lock(&ah
->lock
);
169 ath5k_txbuf_free_skb(ah
, avf
->bbuf
);
170 list_add_tail(&avf
->bbuf
->list
, &ah
->bcbuf
);
171 for (i
= 0; i
< ATH_BCBUF
; i
++) {
172 if (ah
->bslot
[i
] == vif
) {
179 if (avf
->opmode
== NL80211_IFTYPE_AP
)
181 else if (avf
->opmode
== NL80211_IFTYPE_ADHOC
)
182 ah
->num_adhoc_vifs
--;
183 else if (avf
->opmode
== NL80211_IFTYPE_MESH_POINT
)
186 ath5k_update_bssid_mask_and_opmode(ah
, NULL
);
187 mutex_unlock(&ah
->lock
);
192 * TODO: Phy disable/diversity etc
195 ath5k_config(struct ieee80211_hw
*hw
, u32 changed
)
197 struct ath5k_hw
*ah
= hw
->priv
;
198 struct ieee80211_conf
*conf
= &hw
->conf
;
202 mutex_lock(&ah
->lock
);
204 if (changed
& IEEE80211_CONF_CHANGE_CHANNEL
) {
205 ret
= ath5k_chan_set(ah
, &conf
->chandef
);
210 if ((changed
& IEEE80211_CONF_CHANGE_POWER
) &&
211 (ah
->ah_txpower
.txp_requested
!= conf
->power_level
)) {
212 ah
->ah_txpower
.txp_requested
= conf
->power_level
;
215 ath5k_hw_set_txpower_limit(ah
, (conf
->power_level
* 2));
218 if (changed
& IEEE80211_CONF_CHANGE_RETRY_LIMITS
) {
219 ah
->ah_retry_long
= conf
->long_frame_max_tx_count
;
220 ah
->ah_retry_short
= conf
->short_frame_max_tx_count
;
222 for (i
= 0; i
< ah
->ah_capabilities
.cap_queues
.q_tx_num
; i
++)
223 ath5k_hw_set_tx_retry_limits(ah
, i
);
227 * 1) Move this on config_interface and handle each case
228 * separately eg. when we have only one STA vif, use
229 * AR5K_ANTMODE_SINGLE_AP
231 * 2) Allow the user to change antenna mode eg. when only
232 * one antenna is present
234 * 3) Allow the user to set default/tx antenna when possible
236 * 4) Default mode should handle 90% of the cases, together
237 * with fixed a/b and single AP modes we should be able to
238 * handle 99%. Sectored modes are extreme cases and i still
239 * haven't found a usage for them. If we decide to support them,
240 * then we must allow the user to set how many tx antennas we
243 ath5k_hw_set_antenna_mode(ah
, ah
->ah_ant_mode
);
246 mutex_unlock(&ah
->lock
);
252 ath5k_bss_info_changed(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
253 struct ieee80211_bss_conf
*bss_conf
, u32 changes
)
255 struct ath5k_vif
*avf
= (void *)vif
->drv_priv
;
256 struct ath5k_hw
*ah
= hw
->priv
;
257 struct ath_common
*common
= ath5k_hw_common(ah
);
259 mutex_lock(&ah
->lock
);
261 if (changes
& BSS_CHANGED_BSSID
) {
262 /* Cache for later use during resets */
263 memcpy(common
->curbssid
, bss_conf
->bssid
, ETH_ALEN
);
265 ath5k_hw_set_bssid(ah
);
269 if (changes
& BSS_CHANGED_BEACON_INT
)
270 ah
->bintval
= bss_conf
->beacon_int
;
272 if (changes
& BSS_CHANGED_ERP_SLOT
) {
275 ah
->ah_short_slot
= bss_conf
->use_short_slot
;
276 slot_time
= ath5k_hw_get_default_slottime(ah
) +
277 3 * ah
->ah_coverage_class
;
278 ath5k_hw_set_ifs_intervals(ah
, slot_time
);
281 if (changes
& BSS_CHANGED_ASSOC
) {
282 avf
->assoc
= bss_conf
->assoc
;
284 ah
->assoc
= bss_conf
->assoc
;
286 ah
->assoc
= ath5k_any_vif_assoc(ah
);
288 if (ah
->opmode
== NL80211_IFTYPE_STATION
)
289 ath5k_set_beacon_filter(hw
, ah
->assoc
);
290 ath5k_hw_set_ledstate(ah
, ah
->assoc
?
291 AR5K_LED_ASSOC
: AR5K_LED_INIT
);
292 if (bss_conf
->assoc
) {
293 ATH5K_DBG(ah
, ATH5K_DEBUG_ANY
,
294 "Bss Info ASSOC %d, bssid: %pM\n",
295 bss_conf
->aid
, common
->curbssid
);
296 common
->curaid
= bss_conf
->aid
;
297 ath5k_hw_set_bssid(ah
);
298 /* Once ANI is available you would start it here */
302 if (changes
& BSS_CHANGED_BEACON
) {
303 spin_lock_bh(&ah
->block
);
304 ath5k_beacon_update(hw
, vif
);
305 spin_unlock_bh(&ah
->block
);
308 if (changes
& BSS_CHANGED_BEACON_ENABLED
)
309 ah
->enable_beacon
= bss_conf
->enable_beacon
;
311 if (changes
& (BSS_CHANGED_BEACON
| BSS_CHANGED_BEACON_ENABLED
|
312 BSS_CHANGED_BEACON_INT
))
313 ath5k_beacon_config(ah
);
315 mutex_unlock(&ah
->lock
);
320 ath5k_prepare_multicast(struct ieee80211_hw
*hw
,
321 struct netdev_hw_addr_list
*mc_list
)
325 struct netdev_hw_addr
*ha
;
330 netdev_hw_addr_list_for_each(ha
, mc_list
) {
331 /* calculate XOR of eight 6-bit values */
332 val
= get_unaligned_le32(ha
->addr
+ 0);
333 pos
= (val
>> 18) ^ (val
>> 12) ^ (val
>> 6) ^ val
;
334 val
= get_unaligned_le32(ha
->addr
+ 3);
335 pos
^= (val
>> 18) ^ (val
>> 12) ^ (val
>> 6) ^ val
;
337 mfilt
[pos
/ 32] |= (1 << (pos
% 32));
338 /* XXX: we might be able to just do this instead,
339 * but not sure, needs testing, if we do use this we'd
340 * need to inform below not to reset the mcast */
341 /* ath5k_hw_set_mcast_filterindex(ah,
345 return ((u64
)(mfilt
[1]) << 32) | mfilt
[0];
350 * o always accept unicast, broadcast, and multicast traffic
351 * o multicast traffic for all BSSIDs will be enabled if mac80211
353 * o maintain current state of phy ofdm or phy cck error reception.
354 * If the hardware detects any of these type of errors then
355 * ath5k_hw_get_rx_filter() will pass to us the respective
356 * hardware filters to be able to receive these type of frames.
357 * o probe request frames are accepted only when operating in
358 * hostap, adhoc, or monitor modes
359 * o enable promiscuous mode according to the interface state
361 * - when operating in adhoc mode so the 802.11 layer creates
362 * node table entries for peers,
363 * - when operating in station mode for collecting rssi data when
364 * the station is otherwise quiet, or
368 ath5k_configure_filter(struct ieee80211_hw
*hw
, unsigned int changed_flags
,
369 unsigned int *new_flags
, u64 multicast
)
371 #define SUPPORTED_FIF_FLAGS \
372 (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
373 FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
374 FIF_BCN_PRBRESP_PROMISC)
376 struct ath5k_hw
*ah
= hw
->priv
;
378 struct ath5k_vif_iter_data iter_data
; /* to count STA interfaces */
380 mutex_lock(&ah
->lock
);
382 mfilt
[0] = multicast
;
383 mfilt
[1] = multicast
>> 32;
385 /* Only deal with supported flags */
386 changed_flags
&= SUPPORTED_FIF_FLAGS
;
387 *new_flags
&= SUPPORTED_FIF_FLAGS
;
389 /* If HW detects any phy or radar errors, leave those filters on.
390 * Also, always enable Unicast, Broadcasts and Multicast
391 * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
392 rfilt
= (ath5k_hw_get_rx_filter(ah
) & (AR5K_RX_FILTER_PHYERR
)) |
393 (AR5K_RX_FILTER_UCAST
| AR5K_RX_FILTER_BCAST
|
394 AR5K_RX_FILTER_MCAST
);
396 if (changed_flags
& (FIF_PROMISC_IN_BSS
| FIF_OTHER_BSS
)) {
397 if (*new_flags
& FIF_PROMISC_IN_BSS
)
398 __set_bit(ATH_STAT_PROMISC
, ah
->status
);
400 __clear_bit(ATH_STAT_PROMISC
, ah
->status
);
403 if (test_bit(ATH_STAT_PROMISC
, ah
->status
))
404 rfilt
|= AR5K_RX_FILTER_PROM
;
406 /* Note, AR5K_RX_FILTER_MCAST is already enabled */
407 if (*new_flags
& FIF_ALLMULTI
) {
412 /* This is the best we can do */
413 if (*new_flags
& (FIF_FCSFAIL
| FIF_PLCPFAIL
))
414 rfilt
|= AR5K_RX_FILTER_PHYERR
;
416 /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
417 * and probes for any BSSID */
418 if ((*new_flags
& FIF_BCN_PRBRESP_PROMISC
) || (ah
->nvifs
> 1))
419 rfilt
|= AR5K_RX_FILTER_BEACON
;
421 /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
422 * set we should only pass on control frames for this
423 * station. This needs testing. I believe right now this
424 * enables *all* control frames, which is OK.. but
425 * but we should see if we can improve on granularity */
426 if (*new_flags
& FIF_CONTROL
)
427 rfilt
|= AR5K_RX_FILTER_CONTROL
;
429 /* Additional settings per mode -- this is per ath5k */
431 /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
433 switch (ah
->opmode
) {
434 case NL80211_IFTYPE_MESH_POINT
:
435 rfilt
|= AR5K_RX_FILTER_CONTROL
|
436 AR5K_RX_FILTER_BEACON
|
437 AR5K_RX_FILTER_PROBEREQ
|
440 case NL80211_IFTYPE_AP
:
441 case NL80211_IFTYPE_ADHOC
:
442 rfilt
|= AR5K_RX_FILTER_PROBEREQ
|
443 AR5K_RX_FILTER_BEACON
;
445 case NL80211_IFTYPE_STATION
:
447 rfilt
|= AR5K_RX_FILTER_BEACON
;
452 iter_data
.hw_macaddr
= NULL
;
453 iter_data
.n_stas
= 0;
454 iter_data
.need_set_hw_addr
= false;
455 ieee80211_iterate_active_interfaces_atomic(
456 ah
->hw
, IEEE80211_IFACE_ITER_RESUME_ALL
,
457 ath5k_vif_iter
, &iter_data
);
459 /* Set up RX Filter */
460 if (iter_data
.n_stas
> 1) {
461 /* If you have multiple STA interfaces connected to
462 * different APs, ARPs are not received (most of the time?)
463 * Enabling PROMISC appears to fix that problem.
465 rfilt
|= AR5K_RX_FILTER_PROM
;
469 ath5k_hw_set_rx_filter(ah
, rfilt
);
471 /* Set multicast bits */
472 ath5k_hw_set_mcast_filter(ah
, mfilt
[0], mfilt
[1]);
473 /* Set the cached hw filter flags, this will later actually
475 ah
->filter_flags
= rfilt
;
477 mutex_unlock(&ah
->lock
);
482 ath5k_set_key(struct ieee80211_hw
*hw
, enum set_key_cmd cmd
,
483 struct ieee80211_vif
*vif
, struct ieee80211_sta
*sta
,
484 struct ieee80211_key_conf
*key
)
486 struct ath5k_hw
*ah
= hw
->priv
;
487 struct ath_common
*common
= ath5k_hw_common(ah
);
490 if (ath5k_modparam_nohwcrypt
)
493 if (key
->flags
& IEEE80211_KEY_FLAG_RX_MGMT
)
496 if (vif
->type
== NL80211_IFTYPE_ADHOC
&&
497 (key
->cipher
== WLAN_CIPHER_SUITE_TKIP
||
498 key
->cipher
== WLAN_CIPHER_SUITE_CCMP
) &&
499 !(key
->flags
& IEEE80211_KEY_FLAG_PAIRWISE
)) {
500 /* don't program group keys when using IBSS_RSN */
504 switch (key
->cipher
) {
505 case WLAN_CIPHER_SUITE_WEP40
:
506 case WLAN_CIPHER_SUITE_WEP104
:
507 case WLAN_CIPHER_SUITE_TKIP
:
509 case WLAN_CIPHER_SUITE_CCMP
:
510 if (common
->crypt_caps
& ATH_CRYPT_CAP_CIPHER_AESCCM
)
518 mutex_lock(&ah
->lock
);
522 ret
= ath_key_config(common
, vif
, sta
, key
);
524 key
->hw_key_idx
= ret
;
525 /* push IV and Michael MIC generation to stack */
526 key
->flags
|= IEEE80211_KEY_FLAG_GENERATE_IV
;
527 if (key
->cipher
== WLAN_CIPHER_SUITE_TKIP
)
528 key
->flags
|= IEEE80211_KEY_FLAG_GENERATE_MMIC
;
529 if (key
->cipher
== WLAN_CIPHER_SUITE_CCMP
)
530 key
->flags
|= IEEE80211_KEY_FLAG_SW_MGMT_TX
;
535 ath_key_delete(common
, key
);
542 mutex_unlock(&ah
->lock
);
548 ath5k_sw_scan_start(struct ieee80211_hw
*hw
)
550 struct ath5k_hw
*ah
= hw
->priv
;
552 ath5k_hw_set_ledstate(ah
, AR5K_LED_SCAN
);
557 ath5k_sw_scan_complete(struct ieee80211_hw
*hw
)
559 struct ath5k_hw
*ah
= hw
->priv
;
560 ath5k_hw_set_ledstate(ah
, ah
->assoc
?
561 AR5K_LED_ASSOC
: AR5K_LED_INIT
);
566 ath5k_get_stats(struct ieee80211_hw
*hw
,
567 struct ieee80211_low_level_stats
*stats
)
569 struct ath5k_hw
*ah
= hw
->priv
;
572 ath5k_hw_update_mib_counters(ah
);
574 stats
->dot11ACKFailureCount
= ah
->stats
.ack_fail
;
575 stats
->dot11RTSFailureCount
= ah
->stats
.rts_fail
;
576 stats
->dot11RTSSuccessCount
= ah
->stats
.rts_ok
;
577 stats
->dot11FCSErrorCount
= ah
->stats
.fcs_error
;
584 ath5k_conf_tx(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
, u16 queue
,
585 const struct ieee80211_tx_queue_params
*params
)
587 struct ath5k_hw
*ah
= hw
->priv
;
588 struct ath5k_txq_info qi
;
591 if (queue
>= ah
->ah_capabilities
.cap_queues
.q_tx_num
)
594 mutex_lock(&ah
->lock
);
596 ath5k_hw_get_tx_queueprops(ah
, queue
, &qi
);
598 qi
.tqi_aifs
= params
->aifs
;
599 qi
.tqi_cw_min
= params
->cw_min
;
600 qi
.tqi_cw_max
= params
->cw_max
;
601 qi
.tqi_burst_time
= params
->txop
* 32;
603 ATH5K_DBG(ah
, ATH5K_DEBUG_ANY
,
604 "Configure tx [queue %d], "
605 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
606 queue
, params
->aifs
, params
->cw_min
,
607 params
->cw_max
, params
->txop
);
609 if (ath5k_hw_set_tx_queueprops(ah
, queue
, &qi
)) {
611 "Unable to update hardware queue %u!\n", queue
);
614 ath5k_hw_reset_tx_queue(ah
, queue
);
616 mutex_unlock(&ah
->lock
);
623 ath5k_get_tsf(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
)
625 struct ath5k_hw
*ah
= hw
->priv
;
627 return ath5k_hw_get_tsf64(ah
);
632 ath5k_set_tsf(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
, u64 tsf
)
634 struct ath5k_hw
*ah
= hw
->priv
;
636 ath5k_hw_set_tsf64(ah
, tsf
);
641 ath5k_reset_tsf(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
)
643 struct ath5k_hw
*ah
= hw
->priv
;
646 * in IBSS mode we need to update the beacon timers too.
647 * this will also reset the TSF if we call it with 0
649 if (ah
->opmode
== NL80211_IFTYPE_ADHOC
)
650 ath5k_beacon_update_timers(ah
, 0);
652 ath5k_hw_reset_tsf(ah
);
657 ath5k_get_survey(struct ieee80211_hw
*hw
, int idx
, struct survey_info
*survey
)
659 struct ath5k_hw
*ah
= hw
->priv
;
660 struct ieee80211_conf
*conf
= &hw
->conf
;
661 struct ath_common
*common
= ath5k_hw_common(ah
);
662 struct ath_cycle_counters
*cc
= &common
->cc_survey
;
663 unsigned int div
= common
->clockrate
* 1000;
668 spin_lock_bh(&common
->cc_lock
);
669 ath_hw_cycle_counters_update(common
);
670 if (cc
->cycles
> 0) {
671 ah
->survey
.channel_time
+= cc
->cycles
/ div
;
672 ah
->survey
.channel_time_busy
+= cc
->rx_busy
/ div
;
673 ah
->survey
.channel_time_rx
+= cc
->rx_frame
/ div
;
674 ah
->survey
.channel_time_tx
+= cc
->tx_frame
/ div
;
676 memset(cc
, 0, sizeof(*cc
));
677 spin_unlock_bh(&common
->cc_lock
);
679 memcpy(survey
, &ah
->survey
, sizeof(*survey
));
681 survey
->channel
= conf
->chandef
.chan
;
682 survey
->noise
= ah
->ah_noise_floor
;
683 survey
->filled
= SURVEY_INFO_NOISE_DBM
|
684 SURVEY_INFO_CHANNEL_TIME
|
685 SURVEY_INFO_CHANNEL_TIME_BUSY
|
686 SURVEY_INFO_CHANNEL_TIME_RX
|
687 SURVEY_INFO_CHANNEL_TIME_TX
;
694 * ath5k_set_coverage_class - Set IEEE 802.11 coverage class
696 * @hw: struct ieee80211_hw pointer
697 * @coverage_class: IEEE 802.11 coverage class number
699 * Mac80211 callback. Sets slot time, ACK timeout and CTS timeout for given
700 * coverage class. The values are persistent, they are restored after device
704 ath5k_set_coverage_class(struct ieee80211_hw
*hw
, u8 coverage_class
)
706 struct ath5k_hw
*ah
= hw
->priv
;
708 mutex_lock(&ah
->lock
);
709 ath5k_hw_set_coverage_class(ah
, coverage_class
);
710 mutex_unlock(&ah
->lock
);
715 ath5k_set_antenna(struct ieee80211_hw
*hw
, u32 tx_ant
, u32 rx_ant
)
717 struct ath5k_hw
*ah
= hw
->priv
;
719 if (tx_ant
== 1 && rx_ant
== 1)
720 ath5k_hw_set_antenna_mode(ah
, AR5K_ANTMODE_FIXED_A
);
721 else if (tx_ant
== 2 && rx_ant
== 2)
722 ath5k_hw_set_antenna_mode(ah
, AR5K_ANTMODE_FIXED_B
);
723 else if ((tx_ant
& 3) == 3 && (rx_ant
& 3) == 3)
724 ath5k_hw_set_antenna_mode(ah
, AR5K_ANTMODE_DEFAULT
);
732 ath5k_get_antenna(struct ieee80211_hw
*hw
, u32
*tx_ant
, u32
*rx_ant
)
734 struct ath5k_hw
*ah
= hw
->priv
;
736 switch (ah
->ah_ant_mode
) {
737 case AR5K_ANTMODE_FIXED_A
:
738 *tx_ant
= 1; *rx_ant
= 1; break;
739 case AR5K_ANTMODE_FIXED_B
:
740 *tx_ant
= 2; *rx_ant
= 2; break;
741 case AR5K_ANTMODE_DEFAULT
:
742 *tx_ant
= 3; *rx_ant
= 3; break;
748 static void ath5k_get_ringparam(struct ieee80211_hw
*hw
,
749 u32
*tx
, u32
*tx_max
, u32
*rx
, u32
*rx_max
)
751 struct ath5k_hw
*ah
= hw
->priv
;
753 *tx
= ah
->txqs
[AR5K_TX_QUEUE_ID_DATA_MIN
].txq_max
;
755 *tx_max
= ATH5K_TXQ_LEN_MAX
;
756 *rx
= *rx_max
= ATH_RXBUF
;
760 static int ath5k_set_ringparam(struct ieee80211_hw
*hw
, u32 tx
, u32 rx
)
762 struct ath5k_hw
*ah
= hw
->priv
;
765 /* only support setting tx ring size for now */
769 /* restrict tx ring size min/max */
770 if (!tx
|| tx
> ATH5K_TXQ_LEN_MAX
)
773 for (qnum
= 0; qnum
< ARRAY_SIZE(ah
->txqs
); qnum
++) {
774 if (!ah
->txqs
[qnum
].setup
)
776 if (ah
->txqs
[qnum
].qnum
< AR5K_TX_QUEUE_ID_DATA_MIN
||
777 ah
->txqs
[qnum
].qnum
> AR5K_TX_QUEUE_ID_DATA_MAX
)
780 ah
->txqs
[qnum
].txq_max
= tx
;
781 if (ah
->txqs
[qnum
].txq_len
>= ah
->txqs
[qnum
].txq_max
)
782 ieee80211_stop_queue(hw
, ah
->txqs
[qnum
].qnum
);
789 const struct ieee80211_ops ath5k_hw_ops
= {
791 .start
= ath5k_start
,
793 .add_interface
= ath5k_add_interface
,
794 /* .change_interface = not implemented */
795 .remove_interface
= ath5k_remove_interface
,
796 .config
= ath5k_config
,
797 .bss_info_changed
= ath5k_bss_info_changed
,
798 .prepare_multicast
= ath5k_prepare_multicast
,
799 .configure_filter
= ath5k_configure_filter
,
800 /* .set_tim = not implemented */
801 .set_key
= ath5k_set_key
,
802 /* .update_tkip_key = not implemented */
803 /* .hw_scan = not implemented */
804 .sw_scan_start
= ath5k_sw_scan_start
,
805 .sw_scan_complete
= ath5k_sw_scan_complete
,
806 .get_stats
= ath5k_get_stats
,
807 /* .get_tkip_seq = not implemented */
808 /* .set_frag_threshold = not implemented */
809 /* .set_rts_threshold = not implemented */
810 /* .sta_add = not implemented */
811 /* .sta_remove = not implemented */
812 /* .sta_notify = not implemented */
813 .conf_tx
= ath5k_conf_tx
,
814 .get_tsf
= ath5k_get_tsf
,
815 .set_tsf
= ath5k_set_tsf
,
816 .reset_tsf
= ath5k_reset_tsf
,
817 /* .tx_last_beacon = not implemented */
818 /* .ampdu_action = not needed */
819 .get_survey
= ath5k_get_survey
,
820 .set_coverage_class
= ath5k_set_coverage_class
,
821 /* .rfkill_poll = not implemented */
822 /* .flush = not implemented */
823 /* .channel_switch = not implemented */
824 /* .napi_poll = not implemented */
825 .set_antenna
= ath5k_set_antenna
,
826 .get_antenna
= ath5k_get_antenna
,
827 .set_ringparam
= ath5k_set_ringparam
,
828 .get_ringparam
= ath5k_get_ringparam
,