2008-08-29 22:45:39 +03:00
/*
* Copyright ( c ) 2004 - 2008 Reyk Floeter < reyk @ openbsd . org >
* Copyright ( c ) 2006 - 2008 Nick Kossifidis < mickflemm @ gmail . com >
* Copyright ( c ) 2007 - 2008 Pavel Roskin < proski @ gnu . org >
*
* Permission to use , copy , modify , and distribute this software for any
* purpose with or without fee is hereby granted , provided that the above
* copyright notice and this permission notice appear in all copies .
*
* THE SOFTWARE IS PROVIDED " AS IS " AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS . IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL , DIRECT , INDIRECT , OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
* ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
*
*/
/******************************\
Hardware Descriptor Functions
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-03-18 17:30:52 -07:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2008-08-29 22:45:39 +03:00
# include "ath5k.h"
# include "reg.h"
# include "debug.h"
2010-11-23 20:36:45 +02:00
2011-11-25 20:40:25 +02:00
/**
* DOC : Hardware descriptor functions
*
* Here we handle the processing of the low - level hw descriptors
* that hw reads and writes via DMA for each TX and RX attempt ( that means
* we can also have descriptors for failed TX / RX tries ) . We have two kind of
* descriptors for RX and TX , control descriptors tell the hw how to send or
* receive a packet where to read / write it from / to etc and status descriptors
* that contain information about how the packet was sent or received ( errors
* included ) .
*
* Descriptor format is not exactly the same for each MAC chip version so we
* have function pointers on & struct ath5k_hw we initialize at runtime based on
* the chip used .
*/
2010-11-23 20:36:45 +02:00
/************************\
* TX Control descriptors *
\ * * * * * * * * * * * * * * * * * * * * * * * */
2008-08-29 22:45:39 +03:00
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_setup_2word_tx_desc ( ) - Initialize a 2 - word tx control descriptor
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ pkt_len : Frame length in bytes
* @ hdr_len : Header length in bytes ( only used on AR5210 )
* @ padsize : Any padding we ' ve added to the frame length
* @ type : One of enum ath5k_pkt_type
* @ tx_power : Tx power in 0.5 dB steps
* @ tx_rate0 : HW idx for transmission rate
* @ tx_tries0 : Max number of retransmissions
* @ key_index : Index on key table to use for encryption
* @ antenna_mode : Which antenna to use ( 0 for auto )
* @ flags : One of AR5K_TXDESC_ * flags ( desc . h )
* @ rtscts_rate : HW idx for RTS / CTS transmission rate
* @ rtscts_duration : What to put on duration field on the header of RTS / CTS
*
* Internal function to initialize a 2 - Word TX control descriptor
* found on AR5210 and AR5211 MACs chips .
*
* Returns 0 on success or - EINVAL on false input
2008-08-29 22:45:39 +03:00
*/
static int
2011-11-25 20:40:25 +02:00
ath5k_hw_setup_2word_tx_desc ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
unsigned int pkt_len , unsigned int hdr_len ,
int padsize ,
enum ath5k_pkt_type type ,
unsigned int tx_power ,
unsigned int tx_rate0 , unsigned int tx_tries0 ,
unsigned int key_index ,
unsigned int antenna_mode ,
unsigned int flags ,
unsigned int rtscts_rate , unsigned int rtscts_duration )
2008-08-29 22:45:39 +03:00
{
u32 frame_type ;
struct ath5k_hw_2w_tx_ctl * tx_ctl ;
unsigned int frame_len ;
tx_ctl = & desc - > ud . ds_tx5210 . tx_ctl ;
/*
* Validate input
* - Zero retries don ' t make sense .
2011-03-30 22:57:33 -03:00
* - A zero rate will put the HW into a mode where it continuously sends
2008-08-29 22:45:39 +03:00
* noise on the channel , so it is important to avoid this .
*/
if ( unlikely ( tx_tries0 = = 0 ) ) {
2011-07-14 20:21:55 -04:00
ATH5K_ERR ( ah , " zero retries \n " ) ;
2008-08-29 22:45:39 +03:00
WARN_ON ( 1 ) ;
return - EINVAL ;
}
if ( unlikely ( tx_rate0 = = 0 ) ) {
2011-07-14 20:21:55 -04:00
ATH5K_ERR ( ah , " zero rate \n " ) ;
2008-08-29 22:45:39 +03:00
WARN_ON ( 1 ) ;
return - EINVAL ;
}
/* Clear descriptor */
memset ( & desc - > ud . ds_tx5210 , 0 , sizeof ( struct ath5k_hw_5210_tx_desc ) ) ;
/* Setup control descriptor */
/* Verify and set frame length */
/* remove padding we might have added before */
2010-02-27 23:05:26 +01:00
frame_len = pkt_len - padsize + FCS_LEN ;
2008-08-29 22:45:39 +03:00
if ( frame_len & ~ AR5K_2W_TX_DESC_CTL0_FRAME_LEN )
return - EINVAL ;
tx_ctl - > tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN ;
/* Verify and set buffer length */
/* NB: beacon's BufLen must be a multiple of 4 bytes */
if ( type = = AR5K_PKT_TYPE_BEACON )
pkt_len = roundup ( pkt_len , 4 ) ;
if ( pkt_len & ~ AR5K_2W_TX_DESC_CTL1_BUF_LEN )
return - EINVAL ;
tx_ctl - > tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN ;
/*
2010-06-16 19:12:28 +09:00
* Verify and set header length ( only 5210 )
2008-08-29 22:45:39 +03:00
*/
if ( ah - > ah_version = = AR5K_AR5210 ) {
2010-06-16 19:12:17 +09:00
if ( hdr_len & ~ AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210 )
2008-08-29 22:45:39 +03:00
return - EINVAL ;
tx_ctl - > tx_control_0 | =
2010-06-16 19:12:17 +09:00
AR5K_REG_SM ( hdr_len , AR5K_2W_TX_DESC_CTL0_HEADER_LEN_5210 ) ;
2008-08-29 22:45:39 +03:00
}
2010-02-27 23:05:26 +01:00
/*Differences between 5210-5211*/
2008-08-29 22:45:39 +03:00
if ( ah - > ah_version = = AR5K_AR5210 ) {
switch ( type ) {
case AR5K_PKT_TYPE_BEACON :
case AR5K_PKT_TYPE_PROBE_RESP :
frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY ;
2011-07-10 02:28:26 -07:00
break ;
2008-08-29 22:45:39 +03:00
case AR5K_PKT_TYPE_PIFS :
frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS ;
2011-07-10 02:28:26 -07:00
break ;
2008-08-29 22:45:39 +03:00
default :
2010-06-16 19:12:22 +09:00
frame_type = type ;
2011-07-10 02:28:26 -07:00
break ;
2008-08-29 22:45:39 +03:00
}
tx_ctl - > tx_control_0 | =
2010-06-16 19:12:17 +09:00
AR5K_REG_SM ( frame_type , AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_5210 ) |
2008-08-29 22:45:39 +03:00
AR5K_REG_SM ( tx_rate0 , AR5K_2W_TX_DESC_CTL0_XMIT_RATE ) ;
} else {
tx_ctl - > tx_control_0 | =
AR5K_REG_SM ( tx_rate0 , AR5K_2W_TX_DESC_CTL0_XMIT_RATE ) |
AR5K_REG_SM ( antenna_mode ,
AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT ) ;
tx_ctl - > tx_control_1 | =
2010-06-16 19:12:17 +09:00
AR5K_REG_SM ( type , AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_5211 ) ;
2008-08-29 22:45:39 +03:00
}
2010-06-16 19:12:28 +09:00
2008-08-29 22:45:39 +03:00
# define _TX_FLAGS(_c, _flag) \
if ( flags & AR5K_TXDESC_ # # _flag ) { \
tx_ctl - > tx_control_ # # _c | = \
AR5K_2W_TX_DESC_CTL # # _c # # _ # # _flag ; \
}
2010-06-16 19:12:28 +09:00
# define _TX_FLAGS_5211(_c, _flag) \
if ( flags & AR5K_TXDESC_ # # _flag ) { \
tx_ctl - > tx_control_ # # _c | = \
AR5K_2W_TX_DESC_CTL # # _c # # _ # # _flag # # _5211 ; \
}
2008-08-29 22:45:39 +03:00
_TX_FLAGS ( 0 , CLRDMASK ) ;
_TX_FLAGS ( 0 , INTREQ ) ;
_TX_FLAGS ( 0 , RTSENA ) ;
2010-06-16 19:12:28 +09:00
if ( ah - > ah_version = = AR5K_AR5211 ) {
_TX_FLAGS_5211 ( 0 , VEOL ) ;
_TX_FLAGS_5211 ( 1 , NOACK ) ;
}
2008-08-29 22:45:39 +03:00
# undef _TX_FLAGS
2010-06-16 19:12:28 +09:00
# undef _TX_FLAGS_5211
2008-08-29 22:45:39 +03:00
/*
* WEP crap
*/
if ( key_index ! = AR5K_TXKEYIX_INVALID ) {
tx_ctl - > tx_control_0 | =
AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID ;
tx_ctl - > tx_control_1 | =
AR5K_REG_SM ( key_index ,
2010-06-16 19:12:17 +09:00
AR5K_2W_TX_DESC_CTL1_ENC_KEY_IDX ) ;
2008-08-29 22:45:39 +03:00
}
/*
* RTS / CTS Duration [ 5210 ? ]
*/
if ( ( ah - > ah_version = = AR5K_AR5210 ) & &
( flags & ( AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA ) ) )
tx_ctl - > tx_control_1 | = rtscts_duration &
2010-06-16 19:12:17 +09:00
AR5K_2W_TX_DESC_CTL1_RTS_DURATION_5210 ;
2008-08-29 22:45:39 +03:00
return 0 ;
}
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_setup_4word_tx_desc ( ) - Initialize a 4 - word tx control descriptor
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ pkt_len : Frame length in bytes
* @ hdr_len : Header length in bytes ( only used on AR5210 )
* @ padsize : Any padding we ' ve added to the frame length
* @ type : One of enum ath5k_pkt_type
* @ tx_power : Tx power in 0.5 dB steps
* @ tx_rate0 : HW idx for transmission rate
* @ tx_tries0 : Max number of retransmissions
* @ key_index : Index on key table to use for encryption
* @ antenna_mode : Which antenna to use ( 0 for auto )
* @ flags : One of AR5K_TXDESC_ * flags ( desc . h )
* @ rtscts_rate : HW idx for RTS / CTS transmission rate
* @ rtscts_duration : What to put on duration field on the header of RTS / CTS
*
* Internal function to initialize a 4 - Word TX control descriptor
* found on AR5212 and later MACs chips .
*
* Returns 0 on success or - EINVAL on false input
2008-08-29 22:45:39 +03:00
*/
2011-11-25 20:40:25 +02:00
static int
ath5k_hw_setup_4word_tx_desc ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
unsigned int pkt_len , unsigned int hdr_len ,
int padsize ,
enum ath5k_pkt_type type ,
unsigned int tx_power ,
unsigned int tx_rate0 , unsigned int tx_tries0 ,
unsigned int key_index ,
unsigned int antenna_mode ,
unsigned int flags ,
unsigned int rtscts_rate , unsigned int rtscts_duration )
2008-08-29 22:45:39 +03:00
{
struct ath5k_hw_4w_tx_ctl * tx_ctl ;
unsigned int frame_len ;
2011-04-13 08:47:32 -04:00
/*
* Use local variables for these to reduce load / store access on
* uncached memory
*/
2011-04-10 18:32:13 +02:00
u32 txctl0 = 0 , txctl1 = 0 , txctl2 = 0 , txctl3 = 0 ;
2008-08-29 22:45:39 +03:00
tx_ctl = & desc - > ud . ds_tx5212 . tx_ctl ;
/*
* Validate input
* - Zero retries don ' t make sense .
2011-03-30 22:57:33 -03:00
* - A zero rate will put the HW into a mode where it continuously sends
2008-08-29 22:45:39 +03:00
* noise on the channel , so it is important to avoid this .
*/
if ( unlikely ( tx_tries0 = = 0 ) ) {
2011-07-14 20:21:55 -04:00
ATH5K_ERR ( ah , " zero retries \n " ) ;
2008-08-29 22:45:39 +03:00
WARN_ON ( 1 ) ;
return - EINVAL ;
}
if ( unlikely ( tx_rate0 = = 0 ) ) {
2011-07-14 20:21:55 -04:00
ATH5K_ERR ( ah , " zero rate \n " ) ;
2008-08-29 22:45:39 +03:00
WARN_ON ( 1 ) ;
return - EINVAL ;
}
2009-03-15 22:20:35 +02:00
tx_power + = ah - > ah_txpower . txp_offset ;
if ( tx_power > AR5K_TUNE_MAX_TXPOWER )
tx_power = AR5K_TUNE_MAX_TXPOWER ;
2011-04-13 08:47:32 -04:00
/* Clear descriptor status area */
2011-04-10 18:32:13 +02:00
memset ( & desc - > ud . ds_tx5212 . tx_stat , 0 ,
sizeof ( desc - > ud . ds_tx5212 . tx_stat ) ) ;
2008-08-29 22:45:39 +03:00
/* Setup control descriptor */
/* Verify and set frame length */
/* remove padding we might have added before */
2010-02-27 23:05:26 +01:00
frame_len = pkt_len - padsize + FCS_LEN ;
2008-08-29 22:45:39 +03:00
if ( frame_len & ~ AR5K_4W_TX_DESC_CTL0_FRAME_LEN )
return - EINVAL ;
2011-04-10 18:32:13 +02:00
txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN ;
2008-08-29 22:45:39 +03:00
/* Verify and set buffer length */
/* NB: beacon's BufLen must be a multiple of 4 bytes */
if ( type = = AR5K_PKT_TYPE_BEACON )
pkt_len = roundup ( pkt_len , 4 ) ;
if ( pkt_len & ~ AR5K_4W_TX_DESC_CTL1_BUF_LEN )
return - EINVAL ;
2011-04-10 18:32:13 +02:00
txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN ;
2008-08-29 22:45:39 +03:00
2011-04-10 18:32:13 +02:00
txctl0 | = AR5K_REG_SM ( tx_power , AR5K_4W_TX_DESC_CTL0_XMIT_POWER ) |
AR5K_REG_SM ( antenna_mode , AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT ) ;
txctl1 | = AR5K_REG_SM ( type , AR5K_4W_TX_DESC_CTL1_FRAME_TYPE ) ;
txctl2 = AR5K_REG_SM ( tx_tries0 , AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 ) ;
txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 ;
2008-08-29 22:45:39 +03:00
# define _TX_FLAGS(_c, _flag) \
if ( flags & AR5K_TXDESC_ # # _flag ) { \
2011-04-10 18:32:13 +02:00
txctl # # _c | = AR5K_4W_TX_DESC_CTL # # _c # # _ # # _flag ; \
2008-08-29 22:45:39 +03:00
}
_TX_FLAGS ( 0 , CLRDMASK ) ;
_TX_FLAGS ( 0 , VEOL ) ;
_TX_FLAGS ( 0 , INTREQ ) ;
_TX_FLAGS ( 0 , RTSENA ) ;
_TX_FLAGS ( 0 , CTSENA ) ;
_TX_FLAGS ( 1 , NOACK ) ;
# undef _TX_FLAGS
/*
* WEP crap
*/
if ( key_index ! = AR5K_TXKEYIX_INVALID ) {
2011-04-10 18:32:13 +02:00
txctl0 | = AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID ;
txctl1 | = AR5K_REG_SM ( key_index ,
2010-06-16 19:12:17 +09:00
AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX ) ;
2008-08-29 22:45:39 +03:00
}
/*
* RTS / CTS
*/
if ( flags & ( AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA ) ) {
if ( ( flags & AR5K_TXDESC_RTSENA ) & &
( flags & AR5K_TXDESC_CTSENA ) )
return - EINVAL ;
2011-04-10 18:32:13 +02:00
txctl2 | = rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION ;
txctl3 | = AR5K_REG_SM ( rtscts_rate ,
2008-08-29 22:45:39 +03:00
AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE ) ;
}
2011-04-10 18:32:13 +02:00
tx_ctl - > tx_control_0 = txctl0 ;
tx_ctl - > tx_control_1 = txctl1 ;
tx_ctl - > tx_control_2 = txctl2 ;
tx_ctl - > tx_control_3 = txctl3 ;
2008-08-29 22:45:39 +03:00
return 0 ;
}
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_setup_mrr_tx_desc ( ) - Initialize an MRR tx control descriptor
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ tx_rate1 : HW idx for rate used on transmission series 1
* @ tx_tries1 : Max number of retransmissions for transmission series 1
* @ tx_rate2 : HW idx for rate used on transmission series 2
* @ tx_tries2 : Max number of retransmissions for transmission series 2
* @ tx_rate3 : HW idx for rate used on transmission series 3
* @ tx_tries3 : Max number of retransmissions for transmission series 3
*
* Multi rate retry ( MRR ) tx control descriptors are available only on AR5212
* MACs , they are part of the normal 4 - word tx control descriptor ( see above )
* but we handle them through a separate function for better abstraction .
*
* Returns 0 on success or - EINVAL on invalid input
2008-08-29 22:45:39 +03:00
*/
2010-06-16 19:12:01 +09:00
int
2011-11-25 20:40:25 +02:00
ath5k_hw_setup_mrr_tx_desc ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
u_int tx_rate1 , u_int tx_tries1 ,
u_int tx_rate2 , u_int tx_tries2 ,
u_int tx_rate3 , u_int tx_tries3 )
2008-08-29 22:45:39 +03:00
{
struct ath5k_hw_4w_tx_ctl * tx_ctl ;
2010-06-16 19:12:01 +09:00
/* no mrr support for cards older than 5212 */
if ( ah - > ah_version < AR5K_AR5212 )
return 0 ;
2008-08-29 22:45:39 +03:00
/*
* Rates can be 0 as long as the retry count is 0 too .
* A zero rate and nonzero retry count will put the HW into a mode where
2011-03-30 22:57:33 -03:00
* it continuously sends noise on the channel , so it is important to
2008-08-29 22:45:39 +03:00
* avoid this .
*/
if ( unlikely ( ( tx_rate1 = = 0 & & tx_tries1 ! = 0 ) | |
( tx_rate2 = = 0 & & tx_tries2 ! = 0 ) | |
( tx_rate3 = = 0 & & tx_tries3 ! = 0 ) ) ) {
2011-07-14 20:21:55 -04:00
ATH5K_ERR ( ah , " zero rate \n " ) ;
2008-08-29 22:45:39 +03:00
WARN_ON ( 1 ) ;
return - EINVAL ;
}
if ( ah - > ah_version = = AR5K_AR5212 ) {
tx_ctl = & desc - > ud . ds_tx5212 . tx_ctl ;
# define _XTX_TRIES(_n) \
if ( tx_tries # # _n ) { \
tx_ctl - > tx_control_2 | = \
AR5K_REG_SM ( tx_tries # # _n , \
AR5K_4W_TX_DESC_CTL2_XMIT_TRIES # # _n ) ; \
tx_ctl - > tx_control_3 | = \
AR5K_REG_SM ( tx_rate # # _n , \
AR5K_4W_TX_DESC_CTL3_XMIT_RATE # # _n ) ; \
}
_XTX_TRIES ( 1 ) ;
_XTX_TRIES ( 2 ) ;
_XTX_TRIES ( 3 ) ;
# undef _XTX_TRIES
return 1 ;
}
return 0 ;
}
2010-11-23 20:36:45 +02:00
/***********************\
* TX Status descriptors *
\ * * * * * * * * * * * * * * * * * * * * * * */
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_proc_2word_tx_status ( ) - Process a tx status descriptor on 5210 / 1
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ ts : The & struct ath5k_tx_status
2008-08-29 22:45:39 +03:00
*/
2011-11-25 20:40:25 +02:00
static int
ath5k_hw_proc_2word_tx_status ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
struct ath5k_tx_status * ts )
2008-08-29 22:45:39 +03:00
{
struct ath5k_hw_tx_status * tx_status ;
tx_status = & desc - > ud . ds_tx5210 . tx_stat ;
/* No frame has been send or error */
if ( unlikely ( ( tx_status - > tx_status_1 & AR5K_DESC_TX_STATUS1_DONE ) = = 0 ) )
return - EINPROGRESS ;
/*
* Get descriptor status
*/
ts - > ts_tstamp = AR5K_REG_MS ( tx_status - > tx_status_0 ,
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP ) ;
ts - > ts_shortretry = AR5K_REG_MS ( tx_status - > tx_status_0 ,
AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT ) ;
2011-04-10 18:32:17 +02:00
ts - > ts_final_retry = AR5K_REG_MS ( tx_status - > tx_status_0 ,
2008-08-29 22:45:39 +03:00
AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT ) ;
/*TODO: ts->ts_virtcol + test*/
ts - > ts_seqnum = AR5K_REG_MS ( tx_status - > tx_status_1 ,
AR5K_DESC_TX_STATUS1_SEQ_NUM ) ;
ts - > ts_rssi = AR5K_REG_MS ( tx_status - > tx_status_1 ,
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH ) ;
ts - > ts_antenna = 1 ;
ts - > ts_status = 0 ;
2008-10-05 18:05:48 +02:00
ts - > ts_final_idx = 0 ;
2008-08-29 22:45:39 +03:00
if ( ! ( tx_status - > tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK ) ) {
if ( tx_status - > tx_status_0 &
AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES )
ts - > ts_status | = AR5K_TXERR_XRETRY ;
if ( tx_status - > tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN )
ts - > ts_status | = AR5K_TXERR_FIFO ;
if ( tx_status - > tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED )
ts - > ts_status | = AR5K_TXERR_FILT ;
}
return 0 ;
}
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_proc_4word_tx_status ( ) - Process a tx status descriptor on 5212
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ ts : The & struct ath5k_tx_status
2008-08-29 22:45:39 +03:00
*/
2011-11-25 20:40:25 +02:00
static int
ath5k_hw_proc_4word_tx_status ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
struct ath5k_tx_status * ts )
2008-08-29 22:45:39 +03:00
{
struct ath5k_hw_tx_status * tx_status ;
2011-04-10 18:32:17 +02:00
u32 txstat0 , txstat1 ;
2008-08-29 22:45:39 +03:00
tx_status = & desc - > ud . ds_tx5212 . tx_stat ;
2011-04-10 18:32:15 +02:00
txstat1 = ACCESS_ONCE ( tx_status - > tx_status_1 ) ;
2008-08-29 22:45:39 +03:00
/* No frame has been send or error */
2011-04-10 18:32:15 +02:00
if ( unlikely ( ! ( txstat1 & AR5K_DESC_TX_STATUS1_DONE ) ) )
2008-08-29 22:45:39 +03:00
return - EINPROGRESS ;
2011-04-10 18:32:15 +02:00
txstat0 = ACCESS_ONCE ( tx_status - > tx_status_0 ) ;
2008-08-29 22:45:39 +03:00
/*
* Get descriptor status
*/
2011-04-10 18:32:15 +02:00
ts - > ts_tstamp = AR5K_REG_MS ( txstat0 ,
2008-08-29 22:45:39 +03:00
AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP ) ;
2011-04-10 18:32:15 +02:00
ts - > ts_shortretry = AR5K_REG_MS ( txstat0 ,
2008-08-29 22:45:39 +03:00
AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT ) ;
2011-04-10 18:32:17 +02:00
ts - > ts_final_retry = AR5K_REG_MS ( txstat0 ,
2008-08-29 22:45:39 +03:00
AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT ) ;
2011-04-10 18:32:15 +02:00
ts - > ts_seqnum = AR5K_REG_MS ( txstat1 ,
2008-08-29 22:45:39 +03:00
AR5K_DESC_TX_STATUS1_SEQ_NUM ) ;
2011-04-10 18:32:15 +02:00
ts - > ts_rssi = AR5K_REG_MS ( txstat1 ,
2008-08-29 22:45:39 +03:00
AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH ) ;
2011-04-10 18:32:15 +02:00
ts - > ts_antenna = ( txstat1 &
2010-06-16 19:12:17 +09:00
AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 ) ? 2 : 1 ;
2008-08-29 22:45:39 +03:00
ts - > ts_status = 0 ;
2011-04-10 18:32:15 +02:00
ts - > ts_final_idx = AR5K_REG_MS ( txstat1 ,
2010-06-16 19:12:17 +09:00
AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212 ) ;
2008-10-05 18:05:48 +02:00
2008-08-29 22:45:39 +03:00
/* TX error */
2011-04-10 18:32:15 +02:00
if ( ! ( txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK ) ) {
if ( txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES )
2008-08-29 22:45:39 +03:00
ts - > ts_status | = AR5K_TXERR_XRETRY ;
2011-04-10 18:32:15 +02:00
if ( txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN )
2008-08-29 22:45:39 +03:00
ts - > ts_status | = AR5K_TXERR_FIFO ;
2011-04-10 18:32:15 +02:00
if ( txstat0 & AR5K_DESC_TX_STATUS0_FILTERED )
2008-08-29 22:45:39 +03:00
ts - > ts_status | = AR5K_TXERR_FILT ;
}
return 0 ;
}
2010-11-23 20:36:45 +02:00
/****************\
* RX Descriptors *
\ * * * * * * * * * * * * * * * */
2008-08-29 22:45:39 +03:00
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_setup_rx_desc ( ) - Initialize an rx control descriptor
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ size : RX buffer length in bytes
* @ flags : One of AR5K_RXDESC_ * flags
2008-08-29 22:45:39 +03:00
*/
2011-11-25 20:40:25 +02:00
int
ath5k_hw_setup_rx_desc ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
u32 size , unsigned int flags )
2008-08-29 22:45:39 +03:00
{
struct ath5k_hw_rx_ctl * rx_ctl ;
rx_ctl = & desc - > ud . ds_rx . rx_ctl ;
/*
* Clear the descriptor
* If we don ' t clean the status descriptor ,
* while scanning we get too many results ,
* most of them virtual , after some secs
* of scanning system hangs . M . F .
*/
memset ( & desc - > ud . ds_rx , 0 , sizeof ( struct ath5k_hw_all_rx_desc ) ) ;
2010-06-16 19:12:34 +09:00
if ( unlikely ( size & ~ AR5K_DESC_RX_CTL1_BUF_LEN ) )
return - EINVAL ;
2008-08-29 22:45:39 +03:00
/* Setup descriptor */
rx_ctl - > rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN ;
if ( flags & AR5K_RXDESC_INTREQ )
rx_ctl - > rx_control_1 | = AR5K_DESC_RX_CTL1_INTREQ ;
return 0 ;
}
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_proc_5210_rx_status ( ) - Process the rx status descriptor on 5210 / 1
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ rs : The & struct ath5k_rx_status
*
* Internal function used to process an RX status descriptor
* on AR5210 / 5211 MAC .
*
* Returns 0 on success or - EINPROGRESS in case we haven ' t received the who ; e
* frame yet .
2008-08-29 22:45:39 +03:00
*/
2011-11-25 20:40:25 +02:00
static int
ath5k_hw_proc_5210_rx_status ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
struct ath5k_rx_status * rs )
2008-08-29 22:45:39 +03:00
{
struct ath5k_hw_rx_status * rx_status ;
2010-06-16 19:12:12 +09:00
rx_status = & desc - > ud . ds_rx . rx_stat ;
2008-08-29 22:45:39 +03:00
/* No frame received / not ready */
if ( unlikely ( ! ( rx_status - > rx_status_1 &
2010-06-16 19:12:34 +09:00
AR5K_5210_RX_DESC_STATUS1_DONE ) ) )
2008-08-29 22:45:39 +03:00
return - EINPROGRESS ;
2010-06-16 19:12:34 +09:00
memset ( rs , 0 , sizeof ( struct ath5k_rx_status ) ) ;
2008-08-29 22:45:39 +03:00
/*
* Frame receive status
*/
rs - > rs_datalen = rx_status - > rx_status_0 &
AR5K_5210_RX_DESC_STATUS0_DATA_LEN ;
rs - > rs_rssi = AR5K_REG_MS ( rx_status - > rx_status_0 ,
AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL ) ;
rs - > rs_rate = AR5K_REG_MS ( rx_status - > rx_status_0 ,
AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE ) ;
2008-11-03 22:14:00 -05:00
rs - > rs_more = ! ! ( rx_status - > rx_status_0 &
AR5K_5210_RX_DESC_STATUS0_MORE ) ;
2010-06-16 19:12:34 +09:00
/* TODO: this timestamp is 13 bit, later on we assume 15 bit!
* also the HAL code for 5210 says the timestamp is bits [ 10. .22 ] of the
* TSF , and extends the timestamp here to 15 bit .
* we need to check on 5210. . .
*/
2008-08-29 22:45:39 +03:00
rs - > rs_tstamp = AR5K_REG_MS ( rx_status - > rx_status_1 ,
AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP ) ;
2010-06-16 19:12:28 +09:00
if ( ah - > ah_version = = AR5K_AR5211 )
rs - > rs_antenna = AR5K_REG_MS ( rx_status - > rx_status_0 ,
AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5211 ) ;
else
rs - > rs_antenna = ( rx_status - > rx_status_0 &
AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANT_5210 )
? 2 : 1 ;
2008-08-29 22:45:39 +03:00
/*
* Key table status
*/
if ( rx_status - > rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID )
rs - > rs_keyix = AR5K_REG_MS ( rx_status - > rx_status_1 ,
AR5K_5210_RX_DESC_STATUS1_KEY_INDEX ) ;
else
rs - > rs_keyix = AR5K_RXKEYIX_INVALID ;
/*
* Receive / descriptor errors
*/
if ( ! ( rx_status - > rx_status_1 &
2010-06-16 19:12:34 +09:00
AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK ) ) {
2008-08-29 22:45:39 +03:00
if ( rx_status - > rx_status_1 &
AR5K_5210_RX_DESC_STATUS1_CRC_ERROR )
rs - > rs_status | = AR5K_RXERR_CRC ;
2010-06-16 19:12:34 +09:00
/* only on 5210 */
if ( ( ah - > ah_version = = AR5K_AR5210 ) & &
( rx_status - > rx_status_1 &
AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN_5210 ) )
2008-08-29 22:45:39 +03:00
rs - > rs_status | = AR5K_RXERR_FIFO ;
if ( rx_status - > rx_status_1 &
AR5K_5210_RX_DESC_STATUS1_PHY_ERROR ) {
rs - > rs_status | = AR5K_RXERR_PHY ;
2010-06-16 19:12:34 +09:00
rs - > rs_phyerr = AR5K_REG_MS ( rx_status - > rx_status_1 ,
2008-08-29 22:45:39 +03:00
AR5K_5210_RX_DESC_STATUS1_PHY_ERROR ) ;
}
if ( rx_status - > rx_status_1 &
AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR )
rs - > rs_status | = AR5K_RXERR_DECRYPT ;
}
return 0 ;
}
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_proc_5212_rx_status ( ) - Process the rx status descriptor on 5212
* @ ah : The & struct ath5k_hw
* @ desc : The & struct ath5k_desc
* @ rs : The & struct ath5k_rx_status
*
* Internal function used to process an RX status descriptor
* on AR5212 and later MAC .
*
* Returns 0 on success or - EINPROGRESS in case we haven ' t received the who ; e
* frame yet .
2008-08-29 22:45:39 +03:00
*/
2011-11-25 20:40:25 +02:00
static int
ath5k_hw_proc_5212_rx_status ( struct ath5k_hw * ah ,
struct ath5k_desc * desc ,
struct ath5k_rx_status * rs )
2008-08-29 22:45:39 +03:00
{
struct ath5k_hw_rx_status * rx_status ;
2011-04-10 18:32:16 +02:00
u32 rxstat0 , rxstat1 ;
2008-08-29 22:45:39 +03:00
2010-06-16 19:12:12 +09:00
rx_status = & desc - > ud . ds_rx . rx_stat ;
2011-04-10 18:32:16 +02:00
rxstat1 = ACCESS_ONCE ( rx_status - > rx_status_1 ) ;
2008-08-29 22:45:39 +03:00
/* No frame received / not ready */
2011-04-10 18:32:16 +02:00
if ( unlikely ( ! ( rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE ) ) )
2008-08-29 22:45:39 +03:00
return - EINPROGRESS ;
2010-06-16 19:12:34 +09:00
memset ( rs , 0 , sizeof ( struct ath5k_rx_status ) ) ;
2011-04-10 18:32:16 +02:00
rxstat0 = ACCESS_ONCE ( rx_status - > rx_status_0 ) ;
2010-06-16 19:12:34 +09:00
2008-08-29 22:45:39 +03:00
/*
* Frame receive status
*/
2011-04-10 18:32:16 +02:00
rs - > rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN ;
rs - > rs_rssi = AR5K_REG_MS ( rxstat0 ,
2008-08-29 22:45:39 +03:00
AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL ) ;
2011-04-10 18:32:16 +02:00
rs - > rs_rate = AR5K_REG_MS ( rxstat0 ,
2008-08-29 22:45:39 +03:00
AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE ) ;
2011-04-10 18:32:16 +02:00
rs - > rs_antenna = AR5K_REG_MS ( rxstat0 ,
2008-11-03 22:14:00 -05:00
AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA ) ;
2011-04-10 18:32:16 +02:00
rs - > rs_more = ! ! ( rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE ) ;
rs - > rs_tstamp = AR5K_REG_MS ( rxstat1 ,
2008-08-29 22:45:39 +03:00
AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP ) ;
/*
* Key table status
*/
2011-04-10 18:32:16 +02:00
if ( rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID )
rs - > rs_keyix = AR5K_REG_MS ( rxstat1 ,
2010-06-16 19:12:07 +09:00
AR5K_5212_RX_DESC_STATUS1_KEY_INDEX ) ;
2008-08-29 22:45:39 +03:00
else
rs - > rs_keyix = AR5K_RXKEYIX_INVALID ;
/*
* Receive / descriptor errors
*/
2011-04-10 18:32:16 +02:00
if ( ! ( rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK ) ) {
if ( rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR )
2008-08-29 22:45:39 +03:00
rs - > rs_status | = AR5K_RXERR_CRC ;
2011-04-10 18:32:16 +02:00
if ( rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR ) {
2008-08-29 22:45:39 +03:00
rs - > rs_status | = AR5K_RXERR_PHY ;
2011-04-10 18:32:16 +02:00
rs - > rs_phyerr = AR5K_REG_MS ( rxstat1 ,
2010-06-16 19:12:12 +09:00
AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE ) ;
2010-06-16 19:12:39 +09:00
if ( ! ah - > ah_capabilities . cap_has_phyerr_counters )
ath5k_ani_phy_error_report ( ah , rs - > rs_phyerr ) ;
2008-08-29 22:45:39 +03:00
}
2011-04-10 18:32:16 +02:00
if ( rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR )
2008-08-29 22:45:39 +03:00
rs - > rs_status | = AR5K_RXERR_DECRYPT ;
2011-04-10 18:32:16 +02:00
if ( rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR )
2008-08-29 22:45:39 +03:00
rs - > rs_status | = AR5K_RXERR_MIC ;
}
return 0 ;
}
2010-11-23 20:36:45 +02:00
/********\
* Attach *
\ * * * * * * * */
2011-11-25 20:40:25 +02:00
/**
* ath5k_hw_init_desc_functions ( ) - Init function pointers inside ah
* @ ah : The & struct ath5k_hw
*
* Maps the internal descriptor functions to the function pointers on ah , used
* from above . This is used as an abstraction layer to handle the various chips
* the same way .
2008-08-29 22:45:39 +03:00
*/
2011-11-25 20:40:25 +02:00
int
ath5k_hw_init_desc_functions ( struct ath5k_hw * ah )
2008-08-29 22:45:39 +03:00
{
if ( ah - > ah_version = = AR5K_AR5212 ) {
ah - > ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc ;
ah - > ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status ;
2010-06-16 19:12:01 +09:00
ah - > ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status ;
} else if ( ah - > ah_version < = AR5K_AR5211 ) {
2008-08-29 22:45:39 +03:00
ah - > ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc ;
ah - > ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status ;
ah - > ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status ;
2010-06-16 19:12:01 +09:00
} else
return - ENOTSUPP ;
2008-08-29 22:45:39 +03:00
return 0 ;
}