ath5k: Cleanups v2 + add kerneldoc on all hw functions

No functional changes

Add kernel doc for all ath5k_hw_* functions and strcucts. Also do some cleanup,
rename ath5k_hw_init_beacon to ath5k_hw_init_beacon_timers, remove an unused
variable from ath5k_hw_pcu_init and a few obsolete macros, mostly related to XR.

Signed-off-by: Nick Kossifidis <mickflemm@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Nick Kossifidis 2011-11-25 20:40:25 +02:00 committed by John W. Linville
parent 1846ac3dbe
commit c47faa364c
16 changed files with 1945 additions and 726 deletions

View File

@ -27,15 +27,21 @@
* or reducing sensitivity as necessary. * or reducing sensitivity as necessary.
* *
* The parameters are: * The parameters are:
*
* - "noise immunity" * - "noise immunity"
*
* - "spur immunity" * - "spur immunity"
*
* - "firstep level" * - "firstep level"
*
* - "OFDM weak signal detection" * - "OFDM weak signal detection"
*
* - "CCK weak signal detection" * - "CCK weak signal detection"
* *
* Basically we look at the amount of ODFM and CCK timing errors we get and then * Basically we look at the amount of ODFM and CCK timing errors we get and then
* raise or lower immunity accordingly by setting one or more of these * raise or lower immunity accordingly by setting one or more of these
* parameters. * parameters.
*
* Newer chipsets have PHY error counters in hardware which will generate a MIB * Newer chipsets have PHY error counters in hardware which will generate a MIB
* interrupt when they overflow. Older hardware has too enable PHY error frames * interrupt when they overflow. Older hardware has too enable PHY error frames
* by setting a RX flag and then count every single PHY error. When a specified * by setting a RX flag and then count every single PHY error. When a specified
@ -45,11 +51,13 @@
*/ */
/*** ANI parameter control ***/ /***********************\
* ANI parameter control *
\***********************/
/** /**
* ath5k_ani_set_noise_immunity_level() - Set noise immunity level * ath5k_ani_set_noise_immunity_level() - Set noise immunity level
* * @ah: The &struct ath5k_hw
* @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL * @level: level between 0 and @ATH5K_ANI_MAX_NOISE_IMM_LVL
*/ */
void void
@ -91,12 +99,11 @@ ath5k_ani_set_noise_immunity_level(struct ath5k_hw *ah, int level)
ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
} }
/** /**
* ath5k_ani_set_spur_immunity_level() - Set spur immunity level * ath5k_ani_set_spur_immunity_level() - Set spur immunity level
* * @ah: The &struct ath5k_hw
* @level: level between 0 and @max_spur_level (the maximum level is dependent * @level: level between 0 and @max_spur_level (the maximum level is dependent
* on the chip revision). * on the chip revision).
*/ */
void void
ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level) ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
@ -117,10 +124,9 @@ ath5k_ani_set_spur_immunity_level(struct ath5k_hw *ah, int level)
ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
} }
/** /**
* ath5k_ani_set_firstep_level() - Set "firstep" level * ath5k_ani_set_firstep_level() - Set "firstep" level
* * @ah: The &struct ath5k_hw
* @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL * @level: level between 0 and @ATH5K_ANI_MAX_FIRSTEP_LVL
*/ */
void void
@ -140,11 +146,9 @@ ath5k_ani_set_firstep_level(struct ath5k_hw *ah, int level)
ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level); ATH5K_DBG_UNLIMIT(ah, ATH5K_DEBUG_ANI, "new level %d", level);
} }
/** /**
* ath5k_ani_set_ofdm_weak_signal_detection() - Control OFDM weak signal * ath5k_ani_set_ofdm_weak_signal_detection() - Set OFDM weak signal detection
* detection * @ah: The &struct ath5k_hw
*
* @on: turn on or off * @on: turn on or off
*/ */
void void
@ -182,10 +186,9 @@ ath5k_ani_set_ofdm_weak_signal_detection(struct ath5k_hw *ah, bool on)
on ? "on" : "off"); on ? "on" : "off");
} }
/** /**
* ath5k_ani_set_cck_weak_signal_detection() - control CCK weak signal detection * ath5k_ani_set_cck_weak_signal_detection() - Set CCK weak signal detection
* * @ah: The &struct ath5k_hw
* @on: turn on or off * @on: turn on or off
*/ */
void void
@ -200,13 +203,16 @@ ath5k_ani_set_cck_weak_signal_detection(struct ath5k_hw *ah, bool on)
} }
/*** ANI algorithm ***/ /***************\
* ANI algorithm *
\***************/
/** /**
* ath5k_ani_raise_immunity() - Increase noise immunity * ath5k_ani_raise_immunity() - Increase noise immunity
* * @ah: The &struct ath5k_hw
* @as: The &struct ath5k_ani_state
* @ofdm_trigger: If this is true we are called because of too many OFDM errors, * @ofdm_trigger: If this is true we are called because of too many OFDM errors,
* the algorithm will tune more parameters then. * the algorithm will tune more parameters then.
* *
* Try to raise noise immunity (=decrease sensitivity) in several steps * Try to raise noise immunity (=decrease sensitivity) in several steps
* depending on the average RSSI of the beacons we received. * depending on the average RSSI of the beacons we received.
@ -290,9 +296,10 @@ ath5k_ani_raise_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as,
*/ */
} }
/** /**
* ath5k_ani_lower_immunity() - Decrease noise immunity * ath5k_ani_lower_immunity() - Decrease noise immunity
* @ah: The &struct ath5k_hw
* @as: The &struct ath5k_ani_state
* *
* Try to lower noise immunity (=increase sensitivity) in several steps * Try to lower noise immunity (=increase sensitivity) in several steps
* depending on the average RSSI of the beacons we received. * depending on the average RSSI of the beacons we received.
@ -352,9 +359,10 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as)
} }
} }
/** /**
* ath5k_hw_ani_get_listen_time() - Update counters and return listening time * ath5k_hw_ani_get_listen_time() - Update counters and return listening time
* @ah: The &struct ath5k_hw
* @as: The &struct ath5k_ani_state
* *
* Return an approximation of the time spent "listening" in milliseconds (ms) * Return an approximation of the time spent "listening" in milliseconds (ms)
* since the last call of this function. * since the last call of this function.
@ -379,9 +387,10 @@ ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as)
return listen; return listen;
} }
/** /**
* ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters * ath5k_ani_save_and_clear_phy_errors() - Clear and save PHY error counters
* @ah: The &struct ath5k_hw
* @as: The &struct ath5k_ani_state
* *
* Clear the PHY error counters as soon as possible, since this might be called * Clear the PHY error counters as soon as possible, since this might be called
* from a MIB interrupt and we want to make sure we don't get interrupted again. * from a MIB interrupt and we want to make sure we don't get interrupted again.
@ -429,9 +438,10 @@ ath5k_ani_save_and_clear_phy_errors(struct ath5k_hw *ah,
return 1; return 1;
} }
/** /**
* ath5k_ani_period_restart() - Restart ANI period * ath5k_ani_period_restart() - Restart ANI period
* @ah: The &struct ath5k_hw
* @as: The &struct ath5k_ani_state
* *
* Just reset counters, so they are clear for the next "ani period". * Just reset counters, so they are clear for the next "ani period".
*/ */
@ -448,9 +458,9 @@ ath5k_ani_period_restart(struct ath5k_hw *ah, struct ath5k_ani_state *as)
as->listen_time = 0; as->listen_time = 0;
} }
/** /**
* ath5k_ani_calibration() - The main ANI calibration function * ath5k_ani_calibration() - The main ANI calibration function
* @ah: The &struct ath5k_hw
* *
* We count OFDM and CCK errors relative to the time where we did not send or * We count OFDM and CCK errors relative to the time where we did not send or
* receive ("listen" time) and raise or lower immunity accordingly. * receive ("listen" time) and raise or lower immunity accordingly.
@ -509,10 +519,13 @@ ath5k_ani_calibration(struct ath5k_hw *ah)
} }
/*** INTERRUPT HANDLER ***/ /*******************\
* Interrupt handler *
\*******************/
/** /**
* ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters * ath5k_ani_mib_intr() - Interrupt handler for ANI MIB counters
* @ah: The &struct ath5k_hw
* *
* Just read & reset the registers quickly, so they don't generate more * Just read & reset the registers quickly, so they don't generate more
* interrupts, save the counters and schedule the tasklet to decide whether * interrupts, save the counters and schedule the tasklet to decide whether
@ -549,9 +562,11 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah)
tasklet_schedule(&ah->ani_tasklet); tasklet_schedule(&ah->ani_tasklet);
} }
/** /**
* ath5k_ani_phy_error_report() - Used by older HW to report PHY errors * ath5k_ani_phy_error_report - Used by older HW to report PHY errors
*
* @ah: The &struct ath5k_hw
* @phyerr: One of enum ath5k_phy_error_code
* *
* This is used by hardware without PHY error counters to report PHY errors * This is used by hardware without PHY error counters to report PHY errors
* on a frame-by-frame basis, instead of the interrupt. * on a frame-by-frame basis, instead of the interrupt.
@ -574,10 +589,13 @@ ath5k_ani_phy_error_report(struct ath5k_hw *ah,
} }
/*** INIT ***/ /****************\
* Initialization *
\****************/
/** /**
* ath5k_enable_phy_err_counters() - Enable PHY error counters * ath5k_enable_phy_err_counters() - Enable PHY error counters
* @ah: The &struct ath5k_hw
* *
* Enable PHY error counters for OFDM and CCK timing errors. * Enable PHY error counters for OFDM and CCK timing errors.
*/ */
@ -596,9 +614,9 @@ ath5k_enable_phy_err_counters(struct ath5k_hw *ah)
ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT);
} }
/** /**
* ath5k_disable_phy_err_counters() - Disable PHY error counters * ath5k_disable_phy_err_counters() - Disable PHY error counters
* @ah: The &struct ath5k_hw
* *
* Disable PHY error counters for OFDM and CCK timing errors. * Disable PHY error counters for OFDM and CCK timing errors.
*/ */
@ -615,10 +633,10 @@ ath5k_disable_phy_err_counters(struct ath5k_hw *ah)
ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT); ath5k_hw_reg_write(ah, 0, AR5K_CCK_FIL_CNT);
} }
/** /**
* ath5k_ani_init() - Initialize ANI * ath5k_ani_init() - Initialize ANI
* @mode: Which mode to use (auto, manual high, manual low, off) * @ah: The &struct ath5k_hw
* @mode: One of enum ath5k_ani_mode
* *
* Initialize ANI according to mode. * Initialize ANI according to mode.
*/ */
@ -695,10 +713,18 @@ ath5k_ani_init(struct ath5k_hw *ah, enum ath5k_ani_mode mode)
} }
/*** DEBUG ***/ /**************\
* Debug output *
\**************/
#ifdef CONFIG_ATH5K_DEBUG #ifdef CONFIG_ATH5K_DEBUG
/**
* ath5k_ani_print_counters() - Print ANI counters
* @ah: The &struct ath5k_hw
*
* Used for debugging ANI
*/
void void
ath5k_ani_print_counters(struct ath5k_hw *ah) ath5k_ani_print_counters(struct ath5k_hw *ah)
{ {

View File

@ -40,13 +40,13 @@ enum ath5k_phy_error_code;
* enum ath5k_ani_mode - mode for ANI / noise sensitivity * enum ath5k_ani_mode - mode for ANI / noise sensitivity
* *
* @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI * @ATH5K_ANI_MODE_OFF: Turn ANI off. This can be useful to just stop the ANI
* algorithm after it has been on auto mode. * algorithm after it has been on auto mode.
* ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low, * @ATH5K_ANI_MODE_MANUAL_LOW: Manually set all immunity parameters to low,
* maximizing sensitivity. ANI will not run. * maximizing sensitivity. ANI will not run.
* ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high, * @ATH5K_ANI_MODE_MANUAL_HIGH: Manually set all immunity parameters to high,
* minimizing sensitivity. ANI will not run. * minimizing sensitivity. ANI will not run.
* ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the * @ATH5K_ANI_MODE_AUTO: Automatically control immunity parameters based on the
* amount of OFDM and CCK frame errors (default). * amount of OFDM and CCK frame errors (default).
*/ */
enum ath5k_ani_mode { enum ath5k_ani_mode {
ATH5K_ANI_MODE_OFF = 0, ATH5K_ANI_MODE_OFF = 0,
@ -58,8 +58,22 @@ enum ath5k_ani_mode {
/** /**
* struct ath5k_ani_state - ANI state and associated counters * struct ath5k_ani_state - ANI state and associated counters
* * @ani_mode: One of enum ath5k_ani_mode
* @max_spur_level: the maximum spur level is chip dependent * @noise_imm_level: Noise immunity level
* @spur_level: Spur immunity level
* @firstep_level: FIRstep level
* @ofdm_weak_sig: OFDM weak signal detection state (on/off)
* @cck_weak_sig: CCK weak signal detection state (on/off)
* @max_spur_level: Max spur immunity level (chip specific)
* @listen_time: Listen time
* @ofdm_errors: OFDM timing error count
* @cck_errors: CCK timing error count
* @last_cc: The &struct ath_cycle_counters (for stats)
* @last_listen: Listen time from previous run (for stats)
* @last_ofdm_errors: OFDM timing error count from previous run (for tats)
* @last_cck_errors: CCK timing error count from previous run (for stats)
* @sum_ofdm_errors: Sum of OFDM timing errors (for stats)
* @sum_cck_errors: Sum of all CCK timing errors (for stats)
*/ */
struct ath5k_ani_state { struct ath5k_ani_state {
enum ath5k_ani_mode ani_mode; enum ath5k_ani_mode ani_mode;

View File

@ -261,16 +261,34 @@
#define AR5K_AGC_SETTLING_TURBO 37 #define AR5K_AGC_SETTLING_TURBO 37
/* GENERIC CHIPSET DEFINITIONS */
/* MAC Chips */ /*****************************\
* GENERIC CHIPSET DEFINITIONS *
\*****************************/
/**
* enum ath5k_version - MAC Chips
* @AR5K_AR5210: AR5210 (Crete)
* @AR5K_AR5211: AR5211 (Oahu/Maui)
* @AR5K_AR5212: AR5212 (Venice) and newer
*/
enum ath5k_version { enum ath5k_version {
AR5K_AR5210 = 0, AR5K_AR5210 = 0,
AR5K_AR5211 = 1, AR5K_AR5211 = 1,
AR5K_AR5212 = 2, AR5K_AR5212 = 2,
}; };
/* PHY Chips */ /**
* enum ath5k_radio - PHY Chips
* @AR5K_RF5110: RF5110 (Fez)
* @AR5K_RF5111: RF5111 (Sombrero)
* @AR5K_RF5112: RF2112/5112(A) (Derby/Derby2)
* @AR5K_RF2413: RF2413/2414 (Griffin/Griffin-Lite)
* @AR5K_RF5413: RF5413/5414/5424 (Eagle/Condor)
* @AR5K_RF2316: RF2315/2316 (Cobra SoC)
* @AR5K_RF2317: RF2317 (Spider SoC)
* @AR5K_RF2425: RF2425/2417 (Swan/Nalla)
*/
enum ath5k_radio { enum ath5k_radio {
AR5K_RF5110 = 0, AR5K_RF5110 = 0,
AR5K_RF5111 = 1, AR5K_RF5111 = 1,
@ -302,11 +320,11 @@ enum ath5k_radio {
#define AR5K_SREV_AR5213A 0x59 /* Hainan */ #define AR5K_SREV_AR5213A 0x59 /* Hainan */
#define AR5K_SREV_AR2413 0x78 /* Griffin lite */ #define AR5K_SREV_AR2413 0x78 /* Griffin lite */
#define AR5K_SREV_AR2414 0x70 /* Griffin */ #define AR5K_SREV_AR2414 0x70 /* Griffin */
#define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */ #define AR5K_SREV_AR2315_R6 0x86 /* AP51-Light */
#define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */ #define AR5K_SREV_AR2315_R7 0x87 /* AP51-Full */
#define AR5K_SREV_AR5424 0x90 /* Condor */ #define AR5K_SREV_AR5424 0x90 /* Condor */
#define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */ #define AR5K_SREV_AR2317_R1 0x90 /* AP61-Light */
#define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */ #define AR5K_SREV_AR2317_R2 0x91 /* AP61-Full */
#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ #define AR5K_SREV_AR5413 0xa4 /* Eagle lite */
#define AR5K_SREV_AR5414 0xa0 /* Eagle */ #define AR5K_SREV_AR5414 0xa0 /* Eagle */
#define AR5K_SREV_AR2415 0xb0 /* Talon */ #define AR5K_SREV_AR2415 0xb0 /* Talon */
@ -343,32 +361,40 @@ enum ath5k_radio {
/* TODO add support to mac80211 for vendor-specific rates and modes */ /* TODO add support to mac80211 for vendor-specific rates and modes */
/* /**
* DOC: Atheros XR
*
* Some of this information is based on Documentation from: * Some of this information is based on Documentation from:
* *
* http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG * http://madwifi-project.org/wiki/ChipsetFeatures/SuperAG
* *
* Modulation for Atheros' eXtended Range - range enhancing extension that is * Atheros' eXtended Range - range enhancing extension is a modulation scheme
* supposed to double the distance an Atheros client device can keep a * that is supposed to double the link distance between an Atheros XR-enabled
* connection with an Atheros access point. This is achieved by increasing * client device with an Atheros XR-enabled access point. This is achieved
* the receiver sensitivity up to, -105dBm, which is about 20dB above what * by increasing the receiver sensitivity up to, -105dBm, which is about 20dB
* the 802.11 specifications demand. In addition, new (proprietary) data rates * above what the 802.11 specifications demand. In addition, new (proprietary)
* are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. * data rates are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
* *
* Please note that can you either use XR or TURBO but you cannot use both, * Please note that can you either use XR or TURBO but you cannot use both,
* they are exclusive. * they are exclusive.
* *
* Also note that we do not plan to support XR mode at least for now. You can
* get a mode similar to XR by using 5MHz bwmode.
*/ */
#define MODULATION_XR 0x00000200
/*
* Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a /**
* throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s * DOC: Atheros SuperAG
* signaling rate achieved through the bonding of two 54Mbit/s 802.11g *
* channels. To use this feature your Access Point must also support it. * In addition to XR we have another modulation scheme called TURBO mode
* that is supposed to provide a throughput transmission speed up to 40Mbit/s
* -60Mbit/s at a 108Mbit/s signaling rate achieved through the bonding of two
* 54Mbit/s 802.11g channels. To use this feature both ends must support it.
* There is also a distinction between "static" and "dynamic" turbo modes: * There is also a distinction between "static" and "dynamic" turbo modes:
* *
* - Static: is the dumb version: devices set to this mode stick to it until * - Static: is the dumb version: devices set to this mode stick to it until
* the mode is turned off. * the mode is turned off.
*
* - Dynamic: is the intelligent version, the network decides itself if it * - Dynamic: is the intelligent version, the network decides itself if it
* is ok to use turbo. As soon as traffic is detected on adjacent channels * is ok to use turbo. As soon as traffic is detected on adjacent channels
* (which would get used in turbo mode), or when a non-turbo station joins * (which would get used in turbo mode), or when a non-turbo station joins
@ -382,24 +408,39 @@ enum ath5k_radio {
* *
* http://www.pcworld.com/article/id,113428-page,1/article.html * http://www.pcworld.com/article/id,113428-page,1/article.html
* *
* The channel bonding seems to be driver specific though. In addition to * The channel bonding seems to be driver specific though.
* deciding what channels will be used, these "Turbo" modes are accomplished *
* by also enabling the following features: * In addition to TURBO modes we also have the following features for even
* greater speed-up:
* *
* - Bursting: allows multiple frames to be sent at once, rather than pausing * - Bursting: allows multiple frames to be sent at once, rather than pausing
* after each frame. Bursting is a standards-compliant feature that can be * after each frame. Bursting is a standards-compliant feature that can be
* used with any Access Point. * used with any Access Point.
*
* - Fast frames: increases the amount of information that can be sent per * - Fast frames: increases the amount of information that can be sent per
* frame, also resulting in a reduction of transmission overhead. It is a * frame, also resulting in a reduction of transmission overhead. It is a
* proprietary feature that needs to be supported by the Access Point. * proprietary feature that needs to be supported by the Access Point.
*
* - Compression: data frames are compressed in real time using a Lempel Ziv * - Compression: data frames are compressed in real time using a Lempel Ziv
* algorithm. This is done transparently. Once this feature is enabled, * algorithm. This is done transparently. Once this feature is enabled,
* compression and decompression takes place inside the chipset, without * compression and decompression takes place inside the chipset, without
* putting additional load on the host CPU. * putting additional load on the host CPU.
* *
* As with XR we also don't plan to support SuperAG features for now. You can
* get a mode similar to TURBO by using 40MHz bwmode.
*/ */
#define MODULATION_TURBO 0x00000080
/**
* enum ath5k_driver_mode - PHY operation mode
* @AR5K_MODE_11A: 802.11a
* @AR5K_MODE_11B: 802.11b
* @AR5K_MODE_11G: 801.11g
* @AR5K_MODE_MAX: Used for boundary checks
*
* Do not change the order here, we use these as
* array indices and it also maps EEPROM structures.
*/
enum ath5k_driver_mode { enum ath5k_driver_mode {
AR5K_MODE_11A = 0, AR5K_MODE_11A = 0,
AR5K_MODE_11B = 1, AR5K_MODE_11B = 1,
@ -407,30 +448,64 @@ enum ath5k_driver_mode {
AR5K_MODE_MAX = 3 AR5K_MODE_MAX = 3
}; };
/**
* enum ath5k_ant_mode - Antenna operation mode
* @AR5K_ANTMODE_DEFAULT: Default antenna setup
* @AR5K_ANTMODE_FIXED_A: Only antenna A is present
* @AR5K_ANTMODE_FIXED_B: Only antenna B is present
* @AR5K_ANTMODE_SINGLE_AP: STA locked on a single ap
* @AR5K_ANTMODE_SECTOR_AP: AP with tx antenna set on tx desc
* @AR5K_ANTMODE_SECTOR_STA: STA with tx antenna set on tx desc
* @AR5K_ANTMODE_DEBUG: Debug mode -A -> Rx, B-> Tx-
* @AR5K_ANTMODE_MAX: Used for boundary checks
*
* For more infos on antenna control check out phy.c
*/
enum ath5k_ant_mode { enum ath5k_ant_mode {
AR5K_ANTMODE_DEFAULT = 0, /* default antenna setup */ AR5K_ANTMODE_DEFAULT = 0,
AR5K_ANTMODE_FIXED_A = 1, /* only antenna A is present */ AR5K_ANTMODE_FIXED_A = 1,
AR5K_ANTMODE_FIXED_B = 2, /* only antenna B is present */ AR5K_ANTMODE_FIXED_B = 2,
AR5K_ANTMODE_SINGLE_AP = 3, /* sta locked on a single ap */ AR5K_ANTMODE_SINGLE_AP = 3,
AR5K_ANTMODE_SECTOR_AP = 4, /* AP with tx antenna set on tx desc */ AR5K_ANTMODE_SECTOR_AP = 4,
AR5K_ANTMODE_SECTOR_STA = 5, /* STA with tx antenna set on tx desc */ AR5K_ANTMODE_SECTOR_STA = 5,
AR5K_ANTMODE_DEBUG = 6, /* Debug mode -A -> Rx, B-> Tx- */ AR5K_ANTMODE_DEBUG = 6,
AR5K_ANTMODE_MAX, AR5K_ANTMODE_MAX,
}; };
/**
* enum ath5k_bw_mode - Bandwidth operation mode
* @AR5K_BWMODE_DEFAULT: 20MHz, default operation
* @AR5K_BWMODE_5MHZ: Quarter rate
* @AR5K_BWMODE_10MHZ: Half rate
* @AR5K_BWMODE_40MHZ: Turbo
*/
enum ath5k_bw_mode { enum ath5k_bw_mode {
AR5K_BWMODE_DEFAULT = 0, /* 20MHz, default operation */ AR5K_BWMODE_DEFAULT = 0,
AR5K_BWMODE_5MHZ = 1, /* Quarter rate */ AR5K_BWMODE_5MHZ = 1,
AR5K_BWMODE_10MHZ = 2, /* Half rate */ AR5K_BWMODE_10MHZ = 2,
AR5K_BWMODE_40MHZ = 3 /* Turbo */ AR5K_BWMODE_40MHZ = 3
}; };
/****************\ /****************\
TX DEFINITIONS TX DEFINITIONS
\****************/ \****************/
/* /**
* TX Status descriptor * struct ath5k_tx_status - TX Status descriptor
* @ts_seqnum: Sequence number
* @ts_tstamp: Timestamp
* @ts_status: Status code
* @ts_final_idx: Final transmission series index
* @ts_final_retry: Final retry count
* @ts_rssi: RSSI for received ACK
* @ts_shortretry: Short retry count
* @ts_virtcol: Virtual collision count
* @ts_antenna: Antenna used
*
* TX status descriptor gets filled by the hw
* on each transmission attempt.
*/ */
struct ath5k_tx_status { struct ath5k_tx_status {
u16 ts_seqnum; u16 ts_seqnum;
@ -453,7 +528,6 @@ struct ath5k_tx_status {
* enum ath5k_tx_queue - Queue types used to classify tx queues. * enum ath5k_tx_queue - Queue types used to classify tx queues.
* @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue
* @AR5K_TX_QUEUE_DATA: A normal data queue * @AR5K_TX_QUEUE_DATA: A normal data queue
* @AR5K_TX_QUEUE_XR_DATA: An XR-data queue
* @AR5K_TX_QUEUE_BEACON: The beacon queue * @AR5K_TX_QUEUE_BEACON: The beacon queue
* @AR5K_TX_QUEUE_CAB: The after-beacon queue * @AR5K_TX_QUEUE_CAB: The after-beacon queue
* @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue
@ -461,7 +535,6 @@ struct ath5k_tx_status {
enum ath5k_tx_queue { enum ath5k_tx_queue {
AR5K_TX_QUEUE_INACTIVE = 0, AR5K_TX_QUEUE_INACTIVE = 0,
AR5K_TX_QUEUE_DATA, AR5K_TX_QUEUE_DATA,
AR5K_TX_QUEUE_XR_DATA,
AR5K_TX_QUEUE_BEACON, AR5K_TX_QUEUE_BEACON,
AR5K_TX_QUEUE_CAB, AR5K_TX_QUEUE_CAB,
AR5K_TX_QUEUE_UAPSD, AR5K_TX_QUEUE_UAPSD,
@ -470,36 +543,48 @@ enum ath5k_tx_queue {
#define AR5K_NUM_TX_QUEUES 10 #define AR5K_NUM_TX_QUEUES 10
#define AR5K_NUM_TX_QUEUES_NOQCU 2 #define AR5K_NUM_TX_QUEUES_NOQCU 2
/* /**
* Queue syb-types to classify normal data queues. * enum ath5k_tx_queue_subtype - Queue sub-types to classify normal data queues
* @AR5K_WME_AC_BK: Background traffic
* @AR5K_WME_AC_BE: Best-effort (normal) traffic
* @AR5K_WME_AC_VI: Video traffic
* @AR5K_WME_AC_VO: Voice traffic
*
* These are the 4 Access Categories as defined in * These are the 4 Access Categories as defined in
* WME spec. 0 is the lowest priority and 4 is the * WME spec. 0 is the lowest priority and 4 is the
* highest. Normal data that hasn't been classified * highest. Normal data that hasn't been classified
* goes to the Best Effort AC. * goes to the Best Effort AC.
*/ */
enum ath5k_tx_queue_subtype { enum ath5k_tx_queue_subtype {
AR5K_WME_AC_BK = 0, /*Background traffic*/ AR5K_WME_AC_BK = 0,
AR5K_WME_AC_BE, /*Best-effort (normal) traffic*/ AR5K_WME_AC_BE,
AR5K_WME_AC_VI, /*Video traffic*/ AR5K_WME_AC_VI,
AR5K_WME_AC_VO, /*Voice traffic*/ AR5K_WME_AC_VO,
}; };
/* /**
* Queue ID numbers as returned by the hw functions, each number * enum ath5k_tx_queue_id - Queue ID numbers as returned by the hw functions
* represents a hw queue. If hw does not support hw queues * @AR5K_TX_QUEUE_ID_NOQCU_DATA: Data queue on AR5210 (no QCU available)
* @AR5K_TX_QUEUE_ID_NOQCU_BEACON: Beacon queue on AR5210 (no QCU available)
* @AR5K_TX_QUEUE_ID_DATA_MIN: Data queue min index
* @AR5K_TX_QUEUE_ID_DATA_MAX: Data queue max index
* @AR5K_TX_QUEUE_ID_CAB: Content after beacon queue
* @AR5K_TX_QUEUE_ID_BEACON: Beacon queue
* @AR5K_TX_QUEUE_ID_UAPSD: Urgent Automatic Power Save Delivery,
* @AR5K_TX_QUEUE_ID_XR_DATA: XR Data queue
*
* Each number represents a hw queue. If hw does not support hw queues
* (eg 5210) all data goes in one queue. These match * (eg 5210) all data goes in one queue. These match
* d80211 definitions (net80211/MadWiFi don't use them). * mac80211 definitions.
*/ */
enum ath5k_tx_queue_id { enum ath5k_tx_queue_id {
AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, AR5K_TX_QUEUE_ID_NOQCU_DATA = 0,
AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1,
AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ AR5K_TX_QUEUE_ID_DATA_MIN = 0,
AR5K_TX_QUEUE_ID_DATA_MAX = 3, /*IEEE80211_TX_QUEUE_DATA3*/ AR5K_TX_QUEUE_ID_DATA_MAX = 3,
AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ AR5K_TX_QUEUE_ID_CAB = 6,
AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ AR5K_TX_QUEUE_ID_BEACON = 7,
AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/
AR5K_TX_QUEUE_ID_UAPSD = 8, AR5K_TX_QUEUE_ID_UAPSD = 8,
AR5K_TX_QUEUE_ID_XR_DATA = 9,
}; };
/* /*
@ -520,46 +605,70 @@ enum ath5k_tx_queue_id {
#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */ #define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */
#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ #define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
/* /**
* Data transmit queue state. One of these exists for each * struct ath5k_txq - Transmit queue state
* hardware transmit queue. Packets sent to us from above * @qnum: Hardware q number
* are assigned to queues based on their priority. Not all * @link: Link ptr in last TX desc
* devices support a complete set of hardware transmit queues. * @q: Transmit queue (&struct list_head)
* For those devices the array sc_ac2q will map multiple * @lock: Lock on q and link
* priorities to fewer hardware queues (typically all to one * @setup: Is the queue configured
* hardware queue). * @txq_len:Number of queued buffers
* @txq_max: Max allowed num of queued buffers
* @txq_poll_mark: Used to check if queue got stuck
* @txq_stuck: Queue stuck counter
*
* One of these exists for each hardware transmit queue.
* Packets sent to us from above are assigned to queues based
* on their priority. Not all devices support a complete set
* of hardware transmit queues. For those devices the array
* sc_ac2q will map multiple priorities to fewer hardware queues
* (typically all to one hardware queue).
*/ */
struct ath5k_txq { struct ath5k_txq {
unsigned int qnum; /* hardware q number */ unsigned int qnum;
u32 *link; /* link ptr in last TX desc */ u32 *link;
struct list_head q; /* transmit queue */ struct list_head q;
spinlock_t lock; /* lock on q and link */ spinlock_t lock;
bool setup; bool setup;
int txq_len; /* number of queued buffers */ int txq_len;
int txq_max; /* max allowed num of queued buffers */ int txq_max;
bool txq_poll_mark; bool txq_poll_mark;
unsigned int txq_stuck; /* informational counter */ unsigned int txq_stuck;
}; };
/* /**
* A struct to hold tx queue's parameters * struct ath5k_txq_info - A struct to hold TX queue's parameters
* @tqi_type: One of enum ath5k_tx_queue
* @tqi_subtype: One of enum ath5k_tx_queue_subtype
* @tqi_flags: TX queue flags (see above)
* @tqi_aifs: Arbitrated Inter-frame Space
* @tqi_cw_min: Minimum Contention Window
* @tqi_cw_max: Maximum Contention Window
* @tqi_cbr_period: Constant bit rate period
* @tqi_ready_time: Time queue waits after an event when RDYTIME is enabled
*/ */
struct ath5k_txq_info { struct ath5k_txq_info {
enum ath5k_tx_queue tqi_type; enum ath5k_tx_queue tqi_type;
enum ath5k_tx_queue_subtype tqi_subtype; enum ath5k_tx_queue_subtype tqi_subtype;
u16 tqi_flags; /* Tx queue flags (see above) */ u16 tqi_flags;
u8 tqi_aifs; /* Arbitrated Interframe Space */ u8 tqi_aifs;
u16 tqi_cw_min; /* Minimum Contention Window */ u16 tqi_cw_min;
u16 tqi_cw_max; /* Maximum Contention Window */ u16 tqi_cw_max;
u32 tqi_cbr_period; /* Constant bit rate period */ u32 tqi_cbr_period;
u32 tqi_cbr_overflow_limit; u32 tqi_cbr_overflow_limit;
u32 tqi_burst_time; u32 tqi_burst_time;
u32 tqi_ready_time; /* Time queue waits after an event */ u32 tqi_ready_time;
}; };
/* /**
* Transmit packet types. * enum ath5k_pkt_type - Transmit packet types
* used on tx control descriptor * @AR5K_PKT_TYPE_NORMAL: Normal data
* @AR5K_PKT_TYPE_ATIM: ATIM
* @AR5K_PKT_TYPE_PSPOLL: PS-Poll
* @AR5K_PKT_TYPE_BEACON: Beacon
* @AR5K_PKT_TYPE_PROBE_RESP: Probe response
* @AR5K_PKT_TYPE_PIFS: PIFS
* Used on tx control descriptor
*/ */
enum ath5k_pkt_type { enum ath5k_pkt_type {
AR5K_PKT_TYPE_NORMAL = 0, AR5K_PKT_TYPE_NORMAL = 0,
@ -582,27 +691,23 @@ enum ath5k_pkt_type {
(ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \
) )
/*
* DMA size definitions (2^(n+2))
*/
enum ath5k_dmasize {
AR5K_DMASIZE_4B = 0,
AR5K_DMASIZE_8B,
AR5K_DMASIZE_16B,
AR5K_DMASIZE_32B,
AR5K_DMASIZE_64B,
AR5K_DMASIZE_128B,
AR5K_DMASIZE_256B,
AR5K_DMASIZE_512B
};
/****************\ /****************\
RX DEFINITIONS RX DEFINITIONS
\****************/ \****************/
/* /**
* RX Status descriptor * struct ath5k_rx_status - RX Status descriptor
* @rs_datalen: Data length
* @rs_tstamp: Timestamp
* @rs_status: Status code
* @rs_phyerr: PHY error mask
* @rs_rssi: RSSI in 0.5dbm units
* @rs_keyix: Index to the key used for decrypting
* @rs_rate: Rate used to decode the frame
* @rs_antenna: Antenna used to receive the frame
* @rs_more: Indicates this is a frame fragment (Fast frames)
*/ */
struct ath5k_rx_status { struct ath5k_rx_status {
u16 rs_datalen; u16 rs_datalen;
@ -644,10 +749,18 @@ struct ath5k_rx_status {
#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
/*******************************\ /*******************************\
GAIN OPTIMIZATION DEFINITIONS GAIN OPTIMIZATION DEFINITIONS
\*******************************/ \*******************************/
/**
* enum ath5k_rfgain - RF Gain optimization engine state
* @AR5K_RFGAIN_INACTIVE: Engine disabled
* @AR5K_RFGAIN_ACTIVE: Probe active
* @AR5K_RFGAIN_READ_REQUESTED: Probe requested
* @AR5K_RFGAIN_NEED_CHANGE: Gain_F needs change
*/
enum ath5k_rfgain { enum ath5k_rfgain {
AR5K_RFGAIN_INACTIVE = 0, AR5K_RFGAIN_INACTIVE = 0,
AR5K_RFGAIN_ACTIVE, AR5K_RFGAIN_ACTIVE,
@ -655,6 +768,16 @@ enum ath5k_rfgain {
AR5K_RFGAIN_NEED_CHANGE, AR5K_RFGAIN_NEED_CHANGE,
}; };
/**
* struct ath5k_gain - RF Gain optimization engine state data
* @g_step_idx: Current step index
* @g_current: Current gain
* @g_target: Target gain
* @g_low: Low gain boundary
* @g_high: High gain boundary
* @g_f_corr: Gain_F correction
* @g_state: One of enum ath5k_rfgain
*/
struct ath5k_gain { struct ath5k_gain {
u8 g_step_idx; u8 g_step_idx;
u8 g_current; u8 g_current;
@ -665,6 +788,8 @@ struct ath5k_gain {
u8 g_state; u8 g_state;
}; };
/********************\ /********************\
COMMON DEFINITIONS COMMON DEFINITIONS
\********************/ \********************/
@ -673,9 +798,14 @@ struct ath5k_gain {
#define AR5K_SLOT_TIME_20 880 #define AR5K_SLOT_TIME_20 880
#define AR5K_SLOT_TIME_MAX 0xffff #define AR5K_SLOT_TIME_MAX 0xffff
/* /**
* The following structure is used to map 2GHz channels to * struct ath5k_athchan_2ghz - 2GHz to 5GHZ map for RF5111
* 5GHz Atheros channels. * @a2_flags: Channel flags (internal)
* @a2_athchan: HW channel number (internal)
*
* This structure is used to map 2GHz channels to
* 5GHz Atheros channels on 2111 frequency converter
* that comes together with RF5111
* TODO: Clean up * TODO: Clean up
*/ */
struct ath5k_athchan_2ghz { struct ath5k_athchan_2ghz {
@ -683,36 +813,80 @@ struct ath5k_athchan_2ghz {
u16 a2_athchan; u16 a2_athchan;
}; };
/**
* enum ath5k_dmasize - DMA size definitions (2^(n+2))
* @AR5K_DMASIZE_4B: 4Bytes
* @AR5K_DMASIZE_8B: 8Bytes
* @AR5K_DMASIZE_16B: 16Bytes
* @AR5K_DMASIZE_32B: 32Bytes
* @AR5K_DMASIZE_64B: 64Bytes (Default)
* @AR5K_DMASIZE_128B: 128Bytes
* @AR5K_DMASIZE_256B: 256Bytes
* @AR5K_DMASIZE_512B: 512Bytes
*
* These are used to set DMA burst size on hw
*
* Note: Some platforms can't handle more than 4Bytes
* be careful on embedded boards.
*/
enum ath5k_dmasize {
AR5K_DMASIZE_4B = 0,
AR5K_DMASIZE_8B,
AR5K_DMASIZE_16B,
AR5K_DMASIZE_32B,
AR5K_DMASIZE_64B,
AR5K_DMASIZE_128B,
AR5K_DMASIZE_256B,
AR5K_DMASIZE_512B
};
/******************\ /******************\
RATE DEFINITIONS RATE DEFINITIONS
\******************/ \******************/
/** /**
* DOC: Rate codes
*
* Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32. * Seems the ar5xxx hardware supports up to 32 rates, indexed by 1-32.
* *
* The rate code is used to get the RX rate or set the TX rate on the * The rate code is used to get the RX rate or set the TX rate on the
* hardware descriptors. It is also used for internal modulation control * hardware descriptors. It is also used for internal modulation control
* and settings. * and settings.
* *
* This is the hardware rate map we are aware of: * This is the hardware rate map we are aware of (html unfriendly):
* *
* rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 * Rate code Rate (Kbps)
* rate_kbps 3000 1000 ? ? ? 2000 500 48000 * --------- -----------
* 0x01 3000 (XR)
* 0x02 1000 (XR)
* 0x03 250 (XR)
* 0x04 - 05 -Reserved-
* 0x06 2000 (XR)
* 0x07 500 (XR)
* 0x08 48000 (OFDM)
* 0x09 24000 (OFDM)
* 0x0A 12000 (OFDM)
* 0x0B 6000 (OFDM)
* 0x0C 54000 (OFDM)
* 0x0D 36000 (OFDM)
* 0x0E 18000 (OFDM)
* 0x0F 9000 (OFDM)
* 0x10 - 17 -Reserved-
* 0x18 11000L (CCK)
* 0x19 5500L (CCK)
* 0x1A 2000L (CCK)
* 0x1B 1000L (CCK)
* 0x1C 11000S (CCK)
* 0x1D 5500S (CCK)
* 0x1E 2000S (CCK)
* 0x1F -Reserved-
* *
* rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 * "S" indicates CCK rates with short preamble and "L" with long preamble.
* rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
*
* rate_code 17 18 19 20 21 22 23 24
* rate_kbps ? ? ? ? ? ? ? 11000
*
* rate_code 25 26 27 28 29 30 31 32
* rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ?
*
* "S" indicates CCK rates with short preamble.
* *
* AR5211 has different rate codes for CCK (802.11B) rates. It only uses the * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the
* lowest 4 bits, so they are the same as below with a 0xF mask. * lowest 4 bits, so they are the same as above with a 0xF mask.
* (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M). * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M).
* We handle this in ath5k_setup_bands(). * We handle this in ath5k_setup_bands().
*/ */
@ -732,13 +906,9 @@ struct ath5k_athchan_2ghz {
#define ATH5K_RATE_CODE_36M 0x0D #define ATH5K_RATE_CODE_36M 0x0D
#define ATH5K_RATE_CODE_48M 0x08 #define ATH5K_RATE_CODE_48M 0x08
#define ATH5K_RATE_CODE_54M 0x0C #define ATH5K_RATE_CODE_54M 0x0C
/* XR */
#define ATH5K_RATE_CODE_XR_500K 0x07
#define ATH5K_RATE_CODE_XR_1M 0x02
#define ATH5K_RATE_CODE_XR_2M 0x06
#define ATH5K_RATE_CODE_XR_3M 0x01
/* adding this flag to rate_code enables short preamble */ /* Adding this flag to rate_code on B rates
* enables short preamble */
#define AR5K_SET_SHORT_PREAMBLE 0x04 #define AR5K_SET_SHORT_PREAMBLE 0x04
/* /*
@ -768,49 +938,65 @@ extern int ath5k_modparam_nohwcrypt;
/** /**
* enum ath5k_int - Hardware interrupt masks helpers * enum ath5k_int - Hardware interrupt masks helpers
* @AR5K_INT_RXOK: Frame successfully received
* @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor
* @AR5K_INT_RXERR: Frame reception failed
* @AR5K_INT_RXNOFRM: No frame received within a specified time period
* @AR5K_INT_RXEOL: Reached "End Of List", means we need more RX descriptors
* @AR5K_INT_RXORN: Indicates we got RX FIFO overrun. Note that Rx overrun is
* not always fatal, on some chips we can continue operation
* without resetting the card, that's why %AR5K_INT_FATAL is not
* common for all chips.
* @AR5K_INT_RX_ALL: Mask to identify all RX related interrupts
*
* @AR5K_INT_TXOK: Frame transmission success
* @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor
* @AR5K_INT_TXERR: Frame transmission failure
* @AR5K_INT_TXEOL: Received End Of List for VEOL (Virtual End Of List). The
* Queue Control Unit (QCU) signals an EOL interrupt only if a
* descriptor's LinkPtr is NULL. For more details, refer to:
* "http://www.freepatentsonline.com/20030225739.html"
* @AR5K_INT_TXNOFRM: No frame was transmitted within a specified time period
* @AR5K_INT_TXURN: Indicates we got TX FIFO underrun. In such case we should
* increase the TX trigger threshold.
* @AR5K_INT_TX_ALL: Mask to identify all TX related interrupts
* *
* @AR5K_INT_RX: mask to identify received frame interrupts, of type
* AR5K_ISR_RXOK or AR5K_ISR_RXERR
* @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
* @AR5K_INT_RXNOFRM: No frame received (?)
* @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
* Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
* LinkPtr is NULL. For more details, refer to:
* http://www.freepatentsonline.com/20030225739.html
* @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
* Note that Rx overrun is not always fatal, on some chips we can continue
* operation without resetting the card, that's why int_fatal is not
* common for all chips.
* @AR5K_INT_TX: mask to identify received frame interrupts, of type
* AR5K_ISR_TXOK or AR5K_ISR_TXERR
* @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
* @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
* We currently do increments on interrupt by
* (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
* @AR5K_INT_MIB: Indicates the either Management Information Base counters or * @AR5K_INT_MIB: Indicates the either Management Information Base counters or
* one of the PHY error counters reached the maximum value and should be * one of the PHY error counters reached the maximum value and
* read and cleared. * should be read and cleared.
* @AR5K_INT_SWI: Software triggered interrupt.
* @AR5K_INT_RXPHY: RX PHY Error * @AR5K_INT_RXPHY: RX PHY Error
* @AR5K_INT_RXKCM: RX Key cache miss * @AR5K_INT_RXKCM: RX Key cache miss
* @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
* beacon that must be handled in software. The alternative is if you * beacon that must be handled in software. The alternative is if
* have VEOL support, in that case you let the hardware deal with things. * you have VEOL support, in that case you let the hardware deal
* with things.
* @AR5K_INT_BRSSI: Beacon received with an RSSI value below our threshold
* @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
* beacons from the AP have associated with, we should probably try to * beacons from the AP have associated with, we should probably
* reassociate. When in IBSS mode this might mean we have not received * try to reassociate. When in IBSS mode this might mean we have
* any beacons from any local stations. Note that every station in an * not received any beacons from any local stations. Note that
* IBSS schedules to send beacons at the Target Beacon Transmission Time * every station in an IBSS schedules to send beacons at the
* (TBTT) with a random backoff. * Target Beacon Transmission Time (TBTT) with a random backoff.
* @AR5K_INT_BNR: Beacon Not Ready interrupt - ?? * @AR5K_INT_BNR: Beacon queue got triggered (DMA beacon alert) while empty.
* @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now * @AR5K_INT_TIM: Beacon with local station's TIM bit set
* until properly handled * @AR5K_INT_DTIM: Beacon with DTIM bit and zero DTIM count received
* @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA * @AR5K_INT_DTIM_SYNC: DTIM sync lost
* errors. These types of errors we can enable seem to be of type * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill switches connected to
* AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. * our GPIO pins.
* @AR5K_INT_BCN_TIMEOUT: Beacon timeout, we waited after TBTT but got noting
* @AR5K_INT_CAB_TIMEOUT: We waited for CAB traffic after the beacon but got
* nothing or an incomplete CAB frame sequence.
* @AR5K_INT_QCBRORN: A queue got it's CBR counter expired
* @AR5K_INT_QCBRURN: A queue got triggered wile empty
* @AR5K_INT_QTRIG: A queue got triggered
*
* @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by bus/DMA
* errors. Indicates we need to reset the card.
* @AR5K_INT_GLOBAL: Used to clear and set the IER * @AR5K_INT_GLOBAL: Used to clear and set the IER
* @AR5K_INT_NOCARD: signals the card has been removed * @AR5K_INT_NOCARD: Signals the card has been removed
* @AR5K_INT_COMMON: common interrupts shared among MACs with the same * @AR5K_INT_COMMON: Common interrupts shared among MACs with the same
* bit value * bit value
* *
* These are mapped to take advantage of some common bits * These are mapped to take advantage of some common bits
* between the MACs, to be able to set intr properties * between the MACs, to be able to set intr properties
@ -846,10 +1032,9 @@ enum ath5k_int {
AR5K_INT_GPIO = 0x01000000, AR5K_INT_GPIO = 0x01000000,
AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */ AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */
AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */ AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */
AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */ AR5K_INT_QCBRORN = 0x08000000, /* Non common */
AR5K_INT_QCBRORN = 0x10000000, /* Non common */ AR5K_INT_QCBRURN = 0x10000000, /* Non common */
AR5K_INT_QCBRURN = 0x20000000, /* Non common */ AR5K_INT_QTRIG = 0x20000000, /* Non common */
AR5K_INT_QTRIG = 0x40000000, /* Non common */
AR5K_INT_GLOBAL = 0x80000000, AR5K_INT_GLOBAL = 0x80000000,
AR5K_INT_TX_ALL = AR5K_INT_TXOK AR5K_INT_TX_ALL = AR5K_INT_TXOK
@ -891,7 +1076,13 @@ enum ath5k_int {
AR5K_INT_NOCARD = 0xffffffff AR5K_INT_NOCARD = 0xffffffff
}; };
/* mask which calibration is active at the moment */ /**
* enum ath5k_calibration_mask - Mask which calibration is active at the moment
* @AR5K_CALIBRATION_FULL: Full calibration (AGC + SHORT)
* @AR5K_CALIBRATION_SHORT: Short calibration (NF + I/Q)
* @AR5K_CALIBRATION_NF: Noise Floor calibration
* @AR5K_CALIBRATION_ANI: Adaptive Noise Immunity
*/
enum ath5k_calibration_mask { enum ath5k_calibration_mask {
AR5K_CALIBRATION_FULL = 0x01, AR5K_CALIBRATION_FULL = 0x01,
AR5K_CALIBRATION_SHORT = 0x02, AR5K_CALIBRATION_SHORT = 0x02,
@ -899,8 +1090,18 @@ enum ath5k_calibration_mask {
AR5K_CALIBRATION_ANI = 0x08, AR5K_CALIBRATION_ANI = 0x08,
}; };
/* /**
* Power management * enum ath5k_power_mode - Power management modes
* @AR5K_PM_UNDEFINED: Undefined
* @AR5K_PM_AUTO: Allow card to sleep if possible
* @AR5K_PM_AWAKE: Force card to wake up
* @AR5K_PM_FULL_SLEEP: Force card to full sleep (DANGEROUS)
* @AR5K_PM_NETWORK_SLEEP: Allow to sleep for a specified duration
*
* Currently only PM_AWAKE is used, FULL_SLEEP and NETWORK_SLEEP/AUTO
* are also known to have problems on some cards. This is not a big
* problem though because we can have almost the same effect as
* FULL_SLEEP by putting card on warm reset (it's almost powered down).
*/ */
enum ath5k_power_mode { enum ath5k_power_mode {
AR5K_PM_UNDEFINED = 0, AR5K_PM_UNDEFINED = 0,
@ -1344,11 +1545,11 @@ void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah);
u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64);
void ath5k_hw_reset_tsf(struct ath5k_hw *ah); void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); void ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon,
u32 interval);
bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval);
/* Init function */ /* Init function */
void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode);
u8 mode);
/* Queue Control Unit, DFS Control Unit Functions */ /* Queue Control Unit, DFS Control Unit Functions */
int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,

View File

@ -27,8 +27,7 @@
#include "debug.h" #include "debug.h"
/** /**
* ath5k_hw_post - Power On Self Test helper function * ath5k_hw_post() - Power On Self Test helper function
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*/ */
static int ath5k_hw_post(struct ath5k_hw *ah) static int ath5k_hw_post(struct ath5k_hw *ah)
@ -92,8 +91,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
} }
/** /**
* ath5k_hw_init - Check if hw is supported and init the needed structs * ath5k_hw_init() - Check if hw is supported and init the needed structs
*
* @ah: The &struct ath5k_hw associated with the device * @ah: The &struct ath5k_hw associated with the device
* *
* Check if the device is supported, perform a POST and initialize the needed * Check if the device is supported, perform a POST and initialize the needed
@ -349,8 +347,7 @@ err:
} }
/** /**
* ath5k_hw_deinit - Free the ath5k_hw struct * ath5k_hw_deinit() - Free the &struct ath5k_hw
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*/ */
void ath5k_hw_deinit(struct ath5k_hw *ah) void ath5k_hw_deinit(struct ath5k_hw *ah)

View File

@ -183,7 +183,6 @@ static const struct ieee80211_rate ath5k_rates[] = {
{ .bitrate = 540, { .bitrate = 540,
.hw_value = ATH5K_RATE_CODE_54M, .hw_value = ATH5K_RATE_CODE_54M,
.flags = 0 }, .flags = 0 },
/* XR missing */
}; };
static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
@ -2005,7 +2004,7 @@ ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf)
ah->nexttbtt = nexttbtt; ah->nexttbtt = nexttbtt;
intval |= AR5K_BEACON_ENA; intval |= AR5K_BEACON_ENA;
ath5k_hw_init_beacon(ah, nexttbtt, intval); ath5k_hw_init_beacon_timers(ah, nexttbtt, intval);
/* /*
* debugging output last in order to preserve the time critical aspect * debugging output last in order to preserve the time critical aspect

View File

@ -26,20 +26,61 @@
#include "debug.h" #include "debug.h"
/**
* 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.
*/
/************************\ /************************\
* TX Control descriptors * * TX Control descriptors *
\************************/ \************************/
/* /**
* Initialize the 2-word tx control descriptor on 5210/5211 * 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.5dB 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
*/ */
static int static int
ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah,
unsigned int pkt_len, unsigned int hdr_len, int padsize, struct ath5k_desc *desc,
enum ath5k_pkt_type type, unsigned int pkt_len, unsigned int hdr_len,
unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, int padsize,
unsigned int key_index, unsigned int antenna_mode, unsigned int flags, enum ath5k_pkt_type type,
unsigned int rtscts_rate, unsigned int rtscts_duration) 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)
{ {
u32 frame_type; u32 frame_type;
struct ath5k_hw_2w_tx_ctl *tx_ctl; struct ath5k_hw_2w_tx_ctl *tx_ctl;
@ -172,17 +213,40 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
return 0; return 0;
} }
/* /**
* Initialize the 4-word tx control descriptor on 5212 * 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.5dB 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
*/ */
static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, static int
struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
int padsize, struct ath5k_desc *desc,
enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, unsigned int pkt_len, unsigned int hdr_len,
unsigned int tx_tries0, unsigned int key_index, int padsize,
unsigned int antenna_mode, unsigned int flags, enum ath5k_pkt_type type,
unsigned int rtscts_rate, unsigned int tx_power,
unsigned int rtscts_duration) 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)
{ {
struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_4w_tx_ctl *tx_ctl;
unsigned int frame_len; unsigned int frame_len;
@ -292,13 +356,29 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
return 0; return 0;
} }
/* /**
* Initialize a 4-word multi rate retry tx control descriptor on 5212 * 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
*/ */
int int
ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah,
unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, struct ath5k_desc *desc,
u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) u_int tx_rate1, u_int tx_tries1,
u_int tx_rate2, u_int tx_tries2,
u_int tx_rate3, u_int tx_tries3)
{ {
struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_4w_tx_ctl *tx_ctl;
@ -350,11 +430,16 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
* TX Status descriptors * * TX Status descriptors *
\***********************/ \***********************/
/* /**
* Process the tx status descriptor on 5210/5211 * 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
*/ */
static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, static int
struct ath5k_desc *desc, struct ath5k_tx_status *ts) ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
struct ath5k_desc *desc,
struct ath5k_tx_status *ts)
{ {
struct ath5k_hw_2w_tx_ctl *tx_ctl; struct ath5k_hw_2w_tx_ctl *tx_ctl;
struct ath5k_hw_tx_status *tx_status; struct ath5k_hw_tx_status *tx_status;
@ -399,11 +484,16 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
return 0; return 0;
} }
/* /**
* Process a tx status descriptor on 5212 * 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
*/ */
static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, static int
struct ath5k_desc *desc, struct ath5k_tx_status *ts) ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
struct ath5k_desc *desc,
struct ath5k_tx_status *ts)
{ {
struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_4w_tx_ctl *tx_ctl;
struct ath5k_hw_tx_status *tx_status; struct ath5k_hw_tx_status *tx_status;
@ -460,11 +550,17 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
* RX Descriptors * * RX Descriptors *
\****************/ \****************/
/* /**
* Initialize an rx control descriptor * 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
*/ */
int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, int
u32 size, unsigned int flags) ath5k_hw_setup_rx_desc(struct ath5k_hw *ah,
struct ath5k_desc *desc,
u32 size, unsigned int flags)
{ {
struct ath5k_hw_rx_ctl *rx_ctl; struct ath5k_hw_rx_ctl *rx_ctl;
@ -491,11 +587,22 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
return 0; return 0;
} }
/* /**
* Process the rx status descriptor on 5210/5211 * 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.
*/ */
static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, static int
struct ath5k_desc *desc, struct ath5k_rx_status *rs) ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
struct ath5k_desc *desc,
struct ath5k_rx_status *rs)
{ {
struct ath5k_hw_rx_status *rx_status; struct ath5k_hw_rx_status *rx_status;
@ -574,12 +681,22 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah,
return 0; return 0;
} }
/* /**
* Process the rx status descriptor on 5212 * 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.
*/ */
static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, static int
struct ath5k_desc *desc, ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
struct ath5k_rx_status *rs) struct ath5k_desc *desc,
struct ath5k_rx_status *rs)
{ {
struct ath5k_hw_rx_status *rx_status; struct ath5k_hw_rx_status *rx_status;
u32 rxstat0, rxstat1; u32 rxstat0, rxstat1;
@ -646,10 +763,16 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
* Attach * * Attach *
\********/ \********/
/* /**
* Init function pointers inside ath5k_hw struct * 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.
*/ */
int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) int
ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
{ {
if (ah->ah_version == AR5K_AR5212) { if (ah->ah_version == AR5K_AR5212) {
ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;

View File

@ -20,25 +20,30 @@
* RX/TX descriptor structures * RX/TX descriptor structures
*/ */
/* /**
* Common hardware RX control descriptor * struct ath5k_hw_rx_ctl - Common hardware RX control descriptor
* @rx_control_0: RX control word 0
* @rx_control_1: RX control word 1
*/ */
struct ath5k_hw_rx_ctl { struct ath5k_hw_rx_ctl {
u32 rx_control_0; /* RX control word 0 */ u32 rx_control_0;
u32 rx_control_1; /* RX control word 1 */ u32 rx_control_1;
} __packed __aligned(4); } __packed __aligned(4);
/* RX control word 1 fields/flags */ /* RX control word 1 fields/flags */
#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */ #define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */
#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */ #define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 /* RX interrupt request */
/* /**
* Common hardware RX status descriptor * struct ath5k_hw_rx_status - Common hardware RX status descriptor
* @rx_status_0: RX status word 0
* @rx_status_1: RX status word 1
*
* 5210, 5211 and 5212 differ only in the fields and flags defined below * 5210, 5211 and 5212 differ only in the fields and flags defined below
*/ */
struct ath5k_hw_rx_status { struct ath5k_hw_rx_status {
u32 rx_status_0; /* RX status word 0 */ u32 rx_status_0;
u32 rx_status_1; /* RX status word 1 */ u32 rx_status_1;
} __packed __aligned(4); } __packed __aligned(4);
/* 5210/5211 */ /* 5210/5211 */
@ -98,17 +103,36 @@ struct ath5k_hw_rx_status {
/** /**
* enum ath5k_phy_error_code - PHY Error codes * enum ath5k_phy_error_code - PHY Error codes
* @AR5K_RX_PHY_ERROR_UNDERRUN: Transmit underrun, [5210] No error
* @AR5K_RX_PHY_ERROR_TIMING: Timing error
* @AR5K_RX_PHY_ERROR_PARITY: Illegal parity
* @AR5K_RX_PHY_ERROR_RATE: Illegal rate
* @AR5K_RX_PHY_ERROR_LENGTH: Illegal length
* @AR5K_RX_PHY_ERROR_RADAR: Radar detect, [5210] 64 QAM rate
* @AR5K_RX_PHY_ERROR_SERVICE: Illegal service
* @AR5K_RX_PHY_ERROR_TOR: Transmit override receive
* @AR5K_RX_PHY_ERROR_OFDM_TIMING: OFDM Timing error [5212+]
* @AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY: OFDM Signal parity error [5212+]
* @AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL: OFDM Illegal rate [5212+]
* @AR5K_RX_PHY_ERROR_OFDM_LENGTH_ILLEGAL: OFDM Illegal length [5212+]
* @AR5K_RX_PHY_ERROR_OFDM_POWER_DROP: OFDM Power drop [5212+]
* @AR5K_RX_PHY_ERROR_OFDM_SERVICE: OFDM Service (?) [5212+]
* @AR5K_RX_PHY_ERROR_OFDM_RESTART: OFDM Restart (?) [5212+]
* @AR5K_RX_PHY_ERROR_CCK_TIMING: CCK Timing error [5212+]
* @AR5K_RX_PHY_ERROR_CCK_HEADER_CRC: Header CRC error [5212+]
* @AR5K_RX_PHY_ERROR_CCK_RATE_ILLEGAL: Illegal rate [5212+]
* @AR5K_RX_PHY_ERROR_CCK_SERVICE: CCK Service (?) [5212+]
* @AR5K_RX_PHY_ERROR_CCK_RESTART: CCK Restart (?) [5212+]
*/ */
enum ath5k_phy_error_code { enum ath5k_phy_error_code {
AR5K_RX_PHY_ERROR_UNDERRUN = 0, /* Transmit underrun, [5210] No error */ AR5K_RX_PHY_ERROR_UNDERRUN = 0,
AR5K_RX_PHY_ERROR_TIMING = 1, /* Timing error */ AR5K_RX_PHY_ERROR_TIMING = 1,
AR5K_RX_PHY_ERROR_PARITY = 2, /* Illegal parity */ AR5K_RX_PHY_ERROR_PARITY = 2,
AR5K_RX_PHY_ERROR_RATE = 3, /* Illegal rate */ AR5K_RX_PHY_ERROR_RATE = 3,
AR5K_RX_PHY_ERROR_LENGTH = 4, /* Illegal length */ AR5K_RX_PHY_ERROR_LENGTH = 4,
AR5K_RX_PHY_ERROR_RADAR = 5, /* Radar detect, [5210] 64 QAM rate */ AR5K_RX_PHY_ERROR_RADAR = 5,
AR5K_RX_PHY_ERROR_SERVICE = 6, /* Illegal service */ AR5K_RX_PHY_ERROR_SERVICE = 6,
AR5K_RX_PHY_ERROR_TOR = 7, /* Transmit override receive */ AR5K_RX_PHY_ERROR_TOR = 7,
/* these are specific to the 5212 */
AR5K_RX_PHY_ERROR_OFDM_TIMING = 17, AR5K_RX_PHY_ERROR_OFDM_TIMING = 17,
AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18, AR5K_RX_PHY_ERROR_OFDM_SIGNAL_PARITY = 18,
AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19, AR5K_RX_PHY_ERROR_OFDM_RATE_ILLEGAL = 19,
@ -123,12 +147,14 @@ enum ath5k_phy_error_code {
AR5K_RX_PHY_ERROR_CCK_RESTART = 31, AR5K_RX_PHY_ERROR_CCK_RESTART = 31,
}; };
/* /**
* 5210/5211 hardware 2-word TX control descriptor * struct ath5k_hw_2w_tx_ctl - 5210/5211 hardware 2-word TX control descriptor
* @tx_control_0: TX control word 0
* @tx_control_1: TX control word 1
*/ */
struct ath5k_hw_2w_tx_ctl { struct ath5k_hw_2w_tx_ctl {
u32 tx_control_0; /* TX control word 0 */ u32 tx_control_0;
u32 tx_control_1; /* TX control word 1 */ u32 tx_control_1;
} __packed __aligned(4); } __packed __aligned(4);
/* TX control word 0 fields/flags */ /* TX control word 0 fields/flags */
@ -177,14 +203,18 @@ struct ath5k_hw_2w_tx_ctl {
#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4 #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 4
#define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4 #define AR5K_AR5211_TX_DESC_FRAME_TYPE_PRESP 4
/* /**
* 5212 hardware 4-word TX control descriptor * struct ath5k_hw_4w_tx_ctl - 5212 hardware 4-word TX control descriptor
* @tx_control_0: TX control word 0
* @tx_control_1: TX control word 1
* @tx_control_2: TX control word 2
* @tx_control_3: TX control word 3
*/ */
struct ath5k_hw_4w_tx_ctl { struct ath5k_hw_4w_tx_ctl {
u32 tx_control_0; /* TX control word 0 */ u32 tx_control_0;
u32 tx_control_1; /* TX control word 1 */ u32 tx_control_1;
u32 tx_control_2; /* TX control word 2 */ u32 tx_control_2;
u32 tx_control_3; /* TX control word 3 */ u32 tx_control_3;
} __packed __aligned(4); } __packed __aligned(4);
/* TX control word 0 fields/flags */ /* TX control word 0 fields/flags */
@ -238,12 +268,14 @@ struct ath5k_hw_4w_tx_ctl {
#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */ #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 /* RTS or CTS rate */
#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 #define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20
/* /**
* Common TX status descriptor * struct ath5k_hw_tx_status - Common TX status descriptor
* @tx_status_0: TX status word 0
* @tx_status_1: TX status word 1
*/ */
struct ath5k_hw_tx_status { struct ath5k_hw_tx_status {
u32 tx_status_0; /* TX status word 0 */ u32 tx_status_0;
u32 tx_status_1; /* TX status word 1 */ u32 tx_status_1;
} __packed __aligned(4); } __packed __aligned(4);
/* TX status word 0 fields/flags */ /* TX status word 0 fields/flags */
@ -276,37 +308,47 @@ struct ath5k_hw_tx_status {
#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */ #define AR5K_DESC_TX_STATUS1_COMP_SUCCESS_5212 0x00800000 /* [5212] compression status */
#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */ #define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212 0x01000000 /* [5212] transmit antenna */
/* /**
* 5210/5211 hardware TX descriptor * struct ath5k_hw_5210_tx_desc - 5210/5211 hardware TX descriptor
* @tx_ctl: The &struct ath5k_hw_2w_tx_ctl
* @tx_stat: The &struct ath5k_hw_tx_status
*/ */
struct ath5k_hw_5210_tx_desc { struct ath5k_hw_5210_tx_desc {
struct ath5k_hw_2w_tx_ctl tx_ctl; struct ath5k_hw_2w_tx_ctl tx_ctl;
struct ath5k_hw_tx_status tx_stat; struct ath5k_hw_tx_status tx_stat;
} __packed __aligned(4); } __packed __aligned(4);
/* /**
* 5212 hardware TX descriptor * struct ath5k_hw_5212_tx_desc - 5212 hardware TX descriptor
* @tx_ctl: The &struct ath5k_hw_4w_tx_ctl
* @tx_stat: The &struct ath5k_hw_tx_status
*/ */
struct ath5k_hw_5212_tx_desc { struct ath5k_hw_5212_tx_desc {
struct ath5k_hw_4w_tx_ctl tx_ctl; struct ath5k_hw_4w_tx_ctl tx_ctl;
struct ath5k_hw_tx_status tx_stat; struct ath5k_hw_tx_status tx_stat;
} __packed __aligned(4); } __packed __aligned(4);
/* /**
* Common hardware RX descriptor * struct ath5k_hw_all_rx_desc - Common hardware RX descriptor
* @rx_ctl: The &struct ath5k_hw_rx_ctl
* @rx_stat: The &struct ath5k_hw_rx_status
*/ */
struct ath5k_hw_all_rx_desc { struct ath5k_hw_all_rx_desc {
struct ath5k_hw_rx_ctl rx_ctl; struct ath5k_hw_rx_ctl rx_ctl;
struct ath5k_hw_rx_status rx_stat; struct ath5k_hw_rx_status rx_stat;
} __packed __aligned(4); } __packed __aligned(4);
/* /**
* Atheros hardware DMA descriptor * struct ath5k_desc - Atheros hardware DMA descriptor
* @ds_link: Physical address of the next descriptor
* @ds_data: Physical address of data buffer (skb)
* @ud: Union containing hw_5xxx_tx_desc structs and hw_all_rx_desc
*
* This is read and written to by the hardware * This is read and written to by the hardware
*/ */
struct ath5k_desc { struct ath5k_desc {
u32 ds_link; /* physical address of the next descriptor */ u32 ds_link;
u32 ds_data; /* physical address of data buffer (skb) */ u32 ds_data;
union { union {
struct ath5k_hw_5210_tx_desc ds_tx5210; struct ath5k_hw_5210_tx_desc ds_tx5210;

View File

@ -20,16 +20,13 @@
* DMA and interrupt masking functions * * DMA and interrupt masking functions *
\*************************************/ \*************************************/
/* /**
* dma.c - DMA and interrupt masking functions * DOC: DMA and interrupt masking functions
* *
* Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
* handle queue setup for 5210 chipset (rest are handled on qcu.c). * handle queue setup for 5210 chipset (rest are handled on qcu.c).
* Also we setup interrupt mask register (IMR) and read the various interrupt * Also we setup interrupt mask register (IMR) and read the various interrupt
* status registers (ISR). * status registers (ISR).
*
* TODO: Handle SISR on 5211+ and introduce a function to return the queue
* number that resulted the interrupt.
*/ */
#include "ath5k.h" #include "ath5k.h"
@ -42,22 +39,22 @@
\*********/ \*********/
/** /**
* ath5k_hw_start_rx_dma - Start DMA receive * ath5k_hw_start_rx_dma() - Start DMA receive
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*/ */
void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) void
ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
{ {
ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
ath5k_hw_reg_read(ah, AR5K_CR); ath5k_hw_reg_read(ah, AR5K_CR);
} }
/** /**
* ath5k_hw_stop_rx_dma - Stop DMA receive * ath5k_hw_stop_rx_dma() - Stop DMA receive
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*/ */
static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) static int
ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
{ {
unsigned int i; unsigned int i;
@ -79,24 +76,24 @@ static int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
} }
/** /**
* ath5k_hw_get_rxdp - Get RX Descriptor's address * ath5k_hw_get_rxdp() - Get RX Descriptor's address
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*/ */
u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) u32
ath5k_hw_get_rxdp(struct ath5k_hw *ah)
{ {
return ath5k_hw_reg_read(ah, AR5K_RXDP); return ath5k_hw_reg_read(ah, AR5K_RXDP);
} }
/** /**
* ath5k_hw_set_rxdp - Set RX Descriptor's address * ath5k_hw_set_rxdp() - Set RX Descriptor's address
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @phys_addr: RX descriptor address * @phys_addr: RX descriptor address
* *
* Returns -EIO if rx is active * Returns -EIO if rx is active
*/ */
int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) int
ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
{ {
if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) { if (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) {
ATH5K_DBG(ah, ATH5K_DEBUG_DMA, ATH5K_DBG(ah, ATH5K_DEBUG_DMA,
@ -114,8 +111,7 @@ int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
\**********/ \**********/
/** /**
* ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue * ath5k_hw_start_tx_dma() - Start DMA transmit for a specific queue
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @queue: The hw queue number * @queue: The hw queue number
* *
@ -128,7 +124,8 @@ int ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
* NOTE: Must be called after setting up tx control descriptor for that * NOTE: Must be called after setting up tx control descriptor for that
* queue (see below). * queue (see below).
*/ */
int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) int
ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
{ {
u32 tx_queue; u32 tx_queue;
@ -177,17 +174,16 @@ int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
} }
/** /**
* ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue * ath5k_hw_stop_tx_dma() - Stop DMA transmit on a specific queue
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @queue: The hw queue number * @queue: The hw queue number
* *
* Stop DMA transmit on a specific hw queue and drain queue so we don't * Stop DMA transmit on a specific hw queue and drain queue so we don't
* have any pending frames. Returns -EBUSY if we still have pending frames, * have any pending frames. Returns -EBUSY if we still have pending frames,
* -EINVAL if queue number is out of range or inactive. * -EINVAL if queue number is out of range or inactive.
*
*/ */
static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) static int
ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
{ {
unsigned int i = 40; unsigned int i = 40;
u32 tx_queue, pending; u32 tx_queue, pending;
@ -320,14 +316,14 @@ static int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
} }
/** /**
* ath5k_hw_stop_beacon_queue - Stop beacon queue * ath5k_hw_stop_beacon_queue() - Stop beacon queue
* * @ah: The &struct ath5k_hw
* @ah The &struct ath5k_hw * @queue: The queue number
* @queue The queue number
* *
* Returns -EIO if queue didn't stop * Returns -EIO if queue didn't stop
*/ */
int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue) int
ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
{ {
int ret; int ret;
ret = ath5k_hw_stop_tx_dma(ah, queue); ret = ath5k_hw_stop_tx_dma(ah, queue);
@ -340,8 +336,7 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
} }
/** /**
* ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue * ath5k_hw_get_txdp() - Get TX Descriptor's address for a specific queue
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @queue: The hw queue number * @queue: The hw queue number
* *
@ -352,7 +347,8 @@ int ath5k_hw_stop_beacon_queue(struct ath5k_hw *ah, unsigned int queue)
* *
* XXX: Is TXDP read and clear ? * XXX: Is TXDP read and clear ?
*/ */
u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) u32
ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
{ {
u16 tx_reg; u16 tx_reg;
@ -382,10 +378,10 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
} }
/** /**
* ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue * ath5k_hw_set_txdp() - Set TX Descriptor's address for a specific queue
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @queue: The hw queue number * @queue: The hw queue number
* @phys_addr: The physical address
* *
* Set TX descriptor's address for a specific queue. For 5210 we ignore * Set TX descriptor's address for a specific queue. For 5210 we ignore
* the queue number and we use tx queue type since we only have 2 queues * the queue number and we use tx queue type since we only have 2 queues
@ -394,7 +390,8 @@ u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
* Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
* active. * active.
*/ */
int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) int
ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
{ {
u16 tx_reg; u16 tx_reg;
@ -435,8 +432,7 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
} }
/** /**
* ath5k_hw_update_tx_triglevel - Update tx trigger level * ath5k_hw_update_tx_triglevel() - Update tx trigger level
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @increase: Flag to force increase of trigger level * @increase: Flag to force increase of trigger level
* *
@ -444,14 +440,15 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
* buffer (aka FIFO threshold) that is used to indicate when PCU flushes * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
* the buffer and transmits its data. Lowering this results sending small * the buffer and transmits its data. Lowering this results sending small
* frames more quickly but can lead to tx underruns, raising it a lot can * frames more quickly but can lead to tx underruns, raising it a lot can
* result other problems (i think bmiss is related). Right now we start with * result other problems. Right now we start with the lowest possible
* the lowest possible (64Bytes) and if we get tx underrun we increase it using * (64Bytes) and if we get tx underrun we increase it using the increase
* the increase flag. Returns -EIO if we have reached maximum/minimum. * flag. Returns -EIO if we have reached maximum/minimum.
* *
* XXX: Link this with tx DMA size ? * XXX: Link this with tx DMA size ?
* XXX: Use it to save interrupts ? * XXX2: Use it to save interrupts ?
*/ */
int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) int
ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
{ {
u32 trigger_level, imr; u32 trigger_level, imr;
int ret = -EIO; int ret = -EIO;
@ -497,21 +494,20 @@ done:
\*******************/ \*******************/
/** /**
* ath5k_hw_is_intr_pending - Check if we have pending interrupts * ath5k_hw_is_intr_pending() - Check if we have pending interrupts
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Check if we have pending interrupts to process. Returns 1 if we * Check if we have pending interrupts to process. Returns 1 if we
* have pending interrupts and 0 if we haven't. * have pending interrupts and 0 if we haven't.
*/ */
bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) bool
ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
{ {
return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
} }
/** /**
* ath5k_hw_get_isr - Get interrupt status * ath5k_hw_get_isr() - Get interrupt status
*
* @ah: The @struct ath5k_hw * @ah: The @struct ath5k_hw
* @interrupt_mask: Driver's interrupt mask used to filter out * @interrupt_mask: Driver's interrupt mask used to filter out
* interrupts in sw. * interrupts in sw.
@ -525,7 +521,8 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
* NOTE: We do write-to-clear, so the active PISR/SISR bits at the time this * NOTE: We do write-to-clear, so the active PISR/SISR bits at the time this
* function gets called are cleared on return. * function gets called are cleared on return.
*/ */
int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) int
ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
{ {
u32 data = 0; u32 data = 0;
@ -696,15 +693,10 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
if (unlikely(pisr & (AR5K_ISR_HIUERR))) if (unlikely(pisr & (AR5K_ISR_HIUERR)))
*interrupt_mask |= AR5K_INT_FATAL; *interrupt_mask |= AR5K_INT_FATAL;
/*Beacon Not Ready*/ /*Beacon Not Ready*/
if (unlikely(pisr & (AR5K_ISR_BNR))) if (unlikely(pisr & (AR5K_ISR_BNR)))
*interrupt_mask |= AR5K_INT_BNR; *interrupt_mask |= AR5K_INT_BNR;
/* Doppler chirp received */
if (unlikely(pisr & (AR5K_ISR_RXDOPPLER)))
*interrupt_mask |= AR5K_INT_RX_DOPPLER;
/* A queue got CBR overrun */ /* A queue got CBR overrun */
if (unlikely(pisr & (AR5K_ISR_QCBRORN))) { if (unlikely(pisr & (AR5K_ISR_QCBRORN))) {
*interrupt_mask |= AR5K_INT_QCBRORN; *interrupt_mask |= AR5K_INT_QCBRORN;
@ -740,8 +732,7 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
} }
/** /**
* ath5k_hw_set_imr - Set interrupt mask * ath5k_hw_set_imr() - Set interrupt mask
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @new_mask: The new interrupt mask to be set * @new_mask: The new interrupt mask to be set
* *
@ -749,7 +740,8 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
* ath5k_int bits to hw-specific bits to remove abstraction and writing * ath5k_int bits to hw-specific bits to remove abstraction and writing
* Interrupt Mask Register. * Interrupt Mask Register.
*/ */
enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) enum ath5k_int
ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
{ {
enum ath5k_int old_mask, int_mask; enum ath5k_int old_mask, int_mask;
@ -802,10 +794,6 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
if (new_mask & AR5K_INT_BNR) if (new_mask & AR5K_INT_BNR)
int_mask |= AR5K_INT_BNR; int_mask |= AR5K_INT_BNR;
/* RX doppler chirp */
if (new_mask & AR5K_INT_RX_DOPPLER)
int_mask |= AR5K_IMR_RXDOPPLER;
/* Note: Per queue interrupt masks /* Note: Per queue interrupt masks
* are set via ath5k_hw_reset_tx_queue() (qcu.c) */ * are set via ath5k_hw_reset_tx_queue() (qcu.c) */
ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
@ -844,8 +832,7 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
\********************/ \********************/
/** /**
* ath5k_hw_dma_init - Initialize DMA unit * ath5k_hw_dma_init() - Initialize DMA unit
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Set DMA size and pre-enable interrupts * Set DMA size and pre-enable interrupts
@ -854,7 +841,8 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
* *
* XXX: Save/restore RXDP/TXDP registers ? * XXX: Save/restore RXDP/TXDP registers ?
*/ */
void ath5k_hw_dma_init(struct ath5k_hw *ah) void
ath5k_hw_dma_init(struct ath5k_hw *ah)
{ {
/* /*
* Set Rx/Tx DMA Configuration * Set Rx/Tx DMA Configuration
@ -883,8 +871,7 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah)
} }
/** /**
* ath5k_hw_dma_stop - stop DMA unit * ath5k_hw_dma_stop() - stop DMA unit
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Stop tx/rx DMA and interrupts. Returns * Stop tx/rx DMA and interrupts. Returns
@ -894,7 +881,8 @@ void ath5k_hw_dma_init(struct ath5k_hw *ah)
* stuck frames on tx queues, only a reset * stuck frames on tx queues, only a reset
* can fix that. * can fix that.
*/ */
int ath5k_hw_dma_stop(struct ath5k_hw *ah) int
ath5k_hw_dma_stop(struct ath5k_hw *ah)
{ {
int i, qmax, err; int i, qmax, err;
err = 0; err = 0;

View File

@ -24,10 +24,33 @@
#include "reg.h" #include "reg.h"
#include "debug.h" #include "debug.h"
/*
* Set led state /**
* DOC: GPIO/LED functions
*
* Here we control the 6 bidirectional GPIO pins provided by the hw.
* We can set a GPIO pin to be an input or an output pin on GPIO control
* register and then read or set its status from GPIO data input/output
* registers.
*
* We also control the two LED pins provided by the hw, LED_0 is our
* "power" LED and LED_1 is our "network activity" LED but many scenarios
* are available from hw. Vendors might also provide LEDs connected to the
* GPIO pins, we handle them through the LED subsystem on led.c
*/ */
void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
/**
* ath5k_hw_set_ledstate() - Set led state
* @ah: The &struct ath5k_hw
* @state: One of AR5K_LED_*
*
* Used to set the LED blinking state. This only
* works for the LED connected to the LED_0, LED_1 pins,
* not the GPIO based.
*/
void
ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
{ {
u32 led; u32 led;
/*5210 has different led mode handling*/ /*5210 has different led mode handling*/
@ -74,10 +97,13 @@ void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
} }
/* /**
* Set GPIO inputs * ath5k_hw_set_gpio_input() - Set GPIO inputs
* @ah: The &struct ath5k_hw
* @gpio: GPIO pin to set as input
*/ */
int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) int
ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
{ {
if (gpio >= AR5K_NUM_GPIO) if (gpio >= AR5K_NUM_GPIO)
return -EINVAL; return -EINVAL;
@ -89,10 +115,13 @@ int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
return 0; return 0;
} }
/* /**
* Set GPIO outputs * ath5k_hw_set_gpio_output() - Set GPIO outputs
* @ah: The &struct ath5k_hw
* @gpio: The GPIO pin to set as output
*/ */
int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) int
ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
{ {
if (gpio >= AR5K_NUM_GPIO) if (gpio >= AR5K_NUM_GPIO)
return -EINVAL; return -EINVAL;
@ -104,10 +133,13 @@ int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
return 0; return 0;
} }
/* /**
* Get GPIO state * ath5k_hw_get_gpio() - Get GPIO state
* @ah: The &struct ath5k_hw
* @gpio: The GPIO pin to read
*/ */
u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) u32
ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
{ {
if (gpio >= AR5K_NUM_GPIO) if (gpio >= AR5K_NUM_GPIO)
return 0xffffffff; return 0xffffffff;
@ -117,10 +149,14 @@ u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
0x1; 0x1;
} }
/* /**
* Set GPIO state * ath5k_hw_set_gpio() - Set GPIO state
* @ah: The &struct ath5k_hw
* @gpio: The GPIO pin to set
* @val: Value to set (boolean)
*/ */
int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) int
ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
{ {
u32 data; u32 data;
@ -138,10 +174,19 @@ int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
return 0; return 0;
} }
/* /**
* Initialize the GPIO interrupt (RFKill switch) * ath5k_hw_set_gpio_intr() - Initialize the GPIO interrupt (RFKill switch)
* @ah: The &struct ath5k_hw
* @gpio: The GPIO pin to use
* @interrupt_level: True to generate interrupt on active pin (high)
*
* This function is used to set up the GPIO interrupt for the hw RFKill switch.
* That switch is connected to a GPIO pin and it's number is stored on EEPROM.
* It can either open or close the circuit to indicate that we should disable
* RF/Wireless to save power (we also get that from EEPROM).
*/ */
void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, void
ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
u32 interrupt_level) u32 interrupt_level)
{ {
u32 data; u32 data;

View File

@ -23,24 +23,27 @@
#include "reg.h" #include "reg.h"
#include "debug.h" #include "debug.h"
/* /**
* Mode-independent initial register writes * struct ath5k_ini - Mode-independent initial register writes
* @ini_register: Register address
* @ini_value: Default value
* @ini_mode: 0 to write 1 to read (and clear)
*/ */
struct ath5k_ini { struct ath5k_ini {
u16 ini_register; u16 ini_register;
u32 ini_value; u32 ini_value;
enum { enum {
AR5K_INI_WRITE = 0, /* Default */ AR5K_INI_WRITE = 0, /* Default */
AR5K_INI_READ = 1, /* Cleared on read */ AR5K_INI_READ = 1,
} ini_mode; } ini_mode;
}; };
/* /**
* Mode specific initial register values * struct ath5k_ini_mode - Mode specific initial register values
* @mode_register: Register address
* @mode_value: Set of values for each enum ath5k_driver_mode
*/ */
struct ath5k_ini_mode { struct ath5k_ini_mode {
u16 mode_register; u16 mode_register;
u32 mode_value[3]; u32 mode_value[3];
@ -386,11 +389,10 @@ static const struct ath5k_ini ar5211_ini[] = {
/* Initial mode-specific settings for AR5211 /* Initial mode-specific settings for AR5211
* 5211 supports OFDM-only g (draft g) but we * 5211 supports OFDM-only g (draft g) but we
* need to test it ! * need to test it ! */
*/
static const struct ath5k_ini_mode ar5211_ini_mode[] = { static const struct ath5k_ini_mode ar5211_ini_mode[] = {
{ AR5K_TXCFG, { AR5K_TXCFG,
/* A/XR B G */ /* A B G */
{ 0x00000015, 0x0000001d, 0x00000015 } }, { 0x00000015, 0x0000001d, 0x00000015 } },
{ AR5K_QUEUE_DFS_LOCAL_IFS(0), { AR5K_QUEUE_DFS_LOCAL_IFS(0),
{ 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, { 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } },
@ -460,7 +462,7 @@ static const struct ath5k_ini_mode ar5211_ini_mode[] = {
{ 0x00000010, 0x00000010, 0x00000010 } }, { 0x00000010, 0x00000010, 0x00000010 } },
}; };
/* Initial register settings for AR5212 */ /* Initial register settings for AR5212 and newer chips */
static const struct ath5k_ini ar5212_ini_common_start[] = { static const struct ath5k_ini ar5212_ini_common_start[] = {
{ AR5K_RXDP, 0x00000000 }, { AR5K_RXDP, 0x00000000 },
{ AR5K_RXCFG, 0x00000005 }, { AR5K_RXCFG, 0x00000005 },
@ -724,7 +726,8 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
{ 0x00000000, 0x00000000, 0x00000108 } }, { 0x00000000, 0x00000000, 0x00000108 } },
}; };
/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ /* Initial mode-specific settings for AR5212 + RF5111
* (Written after ar5212_ini) */
static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
{ AR5K_TXCFG, { AR5K_TXCFG,
/* A/XR B G */ /* A/XR B G */
@ -757,6 +760,7 @@ static const struct ath5k_ini_mode rf5111_ini_mode_end[] = {
{ 0x1883800a, 0x1873800a, 0x1883800a } }, { 0x1883800a, 0x1873800a, 0x1883800a } },
}; };
/* Common for all modes */
static const struct ath5k_ini rf5111_ini_common_end[] = { static const struct ath5k_ini rf5111_ini_common_end[] = {
{ AR5K_DCU_FP, 0x00000000 }, { AR5K_DCU_FP, 0x00000000 },
{ AR5K_PHY_AGC, 0x00000000 }, { AR5K_PHY_AGC, 0x00000000 },
@ -774,7 +778,9 @@ static const struct ath5k_ini rf5111_ini_common_end[] = {
{ 0xa23c, 0x13c889af }, { 0xa23c, 0x13c889af },
}; };
/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
/* Initial mode-specific settings for AR5212 + RF5112
* (Written after ar5212_ini) */
static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
{ AR5K_TXCFG, { AR5K_TXCFG,
/* A/XR B G */ /* A/XR B G */
@ -825,7 +831,9 @@ static const struct ath5k_ini rf5112_ini_common_end[] = {
{ 0xa23c, 0x13c889af }, { 0xa23c, 0x13c889af },
}; };
/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
/* Initial mode-specific settings for RF5413/5414
* (Written after ar5212_ini) */
static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
{ AR5K_TXCFG, { AR5K_TXCFG,
/* A/XR B G */ /* A/XR B G */
@ -963,7 +971,8 @@ static const struct ath5k_ini rf5413_ini_common_end[] = {
{ 0xa384, 0xf3307ff0 }, { 0xa384, 0xf3307ff0 },
}; };
/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ /* Initial mode-specific settings for RF2413/2414
* (Written after ar5212_ini) */
/* XXX: a mode ? */ /* XXX: a mode ? */
static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { static const struct ath5k_ini_mode rf2413_ini_mode_end[] = {
{ AR5K_TXCFG, { AR5K_TXCFG,
@ -1085,7 +1094,8 @@ static const struct ath5k_ini rf2413_ini_common_end[] = {
{ 0xa384, 0xf3307ff0 }, { 0xa384, 0xf3307ff0 },
}; };
/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ /* Initial mode-specific settings for RF2425
* (Written after ar5212_ini) */
/* XXX: a mode ? */ /* XXX: a mode ? */
static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { static const struct ath5k_ini_mode rf2425_ini_mode_end[] = {
{ AR5K_TXCFG, { AR5K_TXCFG,
@ -1357,10 +1367,15 @@ static const struct ath5k_ini rf5112_ini_bbgain[] = {
}; };
/* /**
* Write initial register dump * ath5k_hw_ini_registers() - Write initial register dump common for all modes
* @ah: The &struct ath5k_hw
* @size: Dump size
* @ini_regs: The array of &struct ath5k_ini
* @skip_pcu: Skip PCU registers
*/ */
static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, static void
ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
const struct ath5k_ini *ini_regs, bool skip_pcu) const struct ath5k_ini *ini_regs, bool skip_pcu)
{ {
unsigned int i; unsigned int i;
@ -1388,7 +1403,15 @@ static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
} }
} }
static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, /**
* ath5k_hw_ini_mode_registers() - Write initial mode-specific register dump
* @ah: The &struct ath5k_hw
* @size: Dump size
* @ini_mode: The array of &struct ath5k_ini_mode
* @mode: One of enum ath5k_driver_mode
*/
static void
ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
unsigned int size, const struct ath5k_ini_mode *ini_mode, unsigned int size, const struct ath5k_ini_mode *ini_mode,
u8 mode) u8 mode)
{ {
@ -1402,7 +1425,17 @@ static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
} }
int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu) /**
* ath5k_hw_write_initvals() - Write initial chip-specific register dump
* @ah: The &struct ath5k_hw
* @mode: One of enum ath5k_driver_mode
* @skip_pcu: Skip PCU registers
*
* Write initial chip-specific register dump, to get the chipset on a
* clean and ready-to-work state after warm reset.
*/
int
ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool skip_pcu)
{ {
/* /*
* Write initial register settings * Write initial register settings

View File

@ -30,11 +30,47 @@
#include "reg.h" #include "reg.h"
#include "debug.h" #include "debug.h"
/* /**
* DOC: Protocol Control Unit (PCU) functions
*
* Protocol control unit is responsible to maintain various protocol
* properties before a frame is send and after a frame is received to/from
* baseband. To be more specific, PCU handles:
*
* - Buffering of RX and TX frames (after QCU/DCUs)
*
* - Encrypting and decrypting (using the built-in engine)
*
* - Generating ACKs, RTS/CTS frames
*
* - Maintaining TSF
*
* - FCS
*
* - Updating beacon data (with TSF etc)
*
* - Generating virtual CCA
*
* - RX/Multicast filtering
*
* - BSSID filtering
*
* - Various statistics
*
* -Different operating modes: AP, STA, IBSS
*
* Note: Most of these functions can be tweaked/bypassed so you can do
* them on sw above for debugging or research. For more infos check out PCU
* registers on reg.h.
*/
/**
* DOC: ACK rates
*
* AR5212+ can use higher rates for ack transmission * AR5212+ can use higher rates for ack transmission
* based on current tx rate instead of the base rate. * based on current tx rate instead of the base rate.
* It does this to better utilize channel usage. * It does this to better utilize channel usage.
* This is a mapping between G rates (that cover both * There is a mapping between G rates (that cover both
* CCK and OFDM) and ack rates that we use when setting * CCK and OFDM) and ack rates that we use when setting
* rate -> duration table. This mapping is hw-based so * rate -> duration table. This mapping is hw-based so
* don't change anything. * don't change anything.
@ -63,17 +99,18 @@ static const unsigned int ack_rates_high[] =
\*******************/ \*******************/
/** /**
* ath5k_hw_get_frame_duration - Get tx time of a frame * ath5k_hw_get_frame_duration() - Get tx time of a frame
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @len: Frame's length in bytes * @len: Frame's length in bytes
* @rate: The @struct ieee80211_rate * @rate: The @struct ieee80211_rate
* @shortpre: Indicate short preample
* *
* Calculate tx duration of a frame given it's rate and length * Calculate tx duration of a frame given it's rate and length
* It extends ieee80211_generic_frame_duration for non standard * It extends ieee80211_generic_frame_duration for non standard
* bwmodes. * bwmodes.
*/ */
int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, int
ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
int len, struct ieee80211_rate *rate, bool shortpre) int len, struct ieee80211_rate *rate, bool shortpre)
{ {
int sifs, preamble, plcp_bits, sym_time; int sifs, preamble, plcp_bits, sym_time;
@ -129,11 +166,11 @@ int ath5k_hw_get_frame_duration(struct ath5k_hw *ah,
} }
/** /**
* ath5k_hw_get_default_slottime - Get the default slot time for current mode * ath5k_hw_get_default_slottime() - Get the default slot time for current mode
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*/ */
unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah) unsigned int
ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
{ {
struct ieee80211_channel *channel = ah->ah_current_channel; struct ieee80211_channel *channel = ah->ah_current_channel;
unsigned int slot_time; unsigned int slot_time;
@ -160,11 +197,11 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
} }
/** /**
* ath5k_hw_get_default_sifs - Get the default SIFS for current mode * ath5k_hw_get_default_sifs() - Get the default SIFS for current mode
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
*/ */
unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah) unsigned int
ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
{ {
struct ieee80211_channel *channel = ah->ah_current_channel; struct ieee80211_channel *channel = ah->ah_current_channel;
unsigned int sifs; unsigned int sifs;
@ -191,17 +228,17 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
} }
/** /**
* ath5k_hw_update_mib_counters - Update MIB counters (mac layer statistics) * ath5k_hw_update_mib_counters() - Update MIB counters (mac layer statistics)
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Reads MIB counters from PCU and updates sw statistics. Is called after a * Reads MIB counters from PCU and updates sw statistics. Is called after a
* MIB interrupt, because one of these counters might have reached their maximum * MIB interrupt, because one of these counters might have reached their maximum
* and triggered the MIB interrupt, to let us read and clear the counter. * and triggered the MIB interrupt, to let us read and clear the counter.
* *
* Is called in interrupt context! * NOTE: Is called in interrupt context!
*/ */
void ath5k_hw_update_mib_counters(struct ath5k_hw *ah) void
ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
{ {
struct ath5k_statistics *stats = &ah->stats; struct ath5k_statistics *stats = &ah->stats;
@ -219,10 +256,8 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
\******************/ \******************/
/** /**
* ath5k_hw_write_rate_duration - fill rate code to duration table * ath5k_hw_write_rate_duration() - Fill rate code to duration table
* * @ah: The &struct ath5k_hw
* @ah: the &struct ath5k_hw
* @mode: one of enum ath5k_driver_mode
* *
* Write the rate code to duration table upon hw reset. This is a helper for * Write the rate code to duration table upon hw reset. This is a helper for
* ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on
@ -236,7 +271,8 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah)
* that include all OFDM and CCK rates. * that include all OFDM and CCK rates.
* *
*/ */
static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah) static inline void
ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
{ {
struct ieee80211_rate *rate; struct ieee80211_rate *rate;
unsigned int i; unsigned int i;
@ -280,12 +316,12 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah)
} }
/** /**
* ath5k_hw_set_ack_timeout - Set ACK timeout on PCU * ath5k_hw_set_ack_timeout() - Set ACK timeout on PCU
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @timeout: Timeout in usec * @timeout: Timeout in usec
*/ */
static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) static int
ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
{ {
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK))
<= timeout) <= timeout)
@ -298,12 +334,12 @@ static int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
} }
/** /**
* ath5k_hw_set_cts_timeout - Set CTS timeout on PCU * ath5k_hw_set_cts_timeout() - Set CTS timeout on PCU
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @timeout: Timeout in usec * @timeout: Timeout in usec
*/ */
static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) static int
ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
{ {
if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS))
<= timeout) <= timeout)
@ -321,14 +357,14 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
\*******************/ \*******************/
/** /**
* ath5k_hw_set_lladdr - Set station id * ath5k_hw_set_lladdr() - Set station id
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @mac: The card's mac address * @mac: The card's mac address (array of octets)
* *
* Set station id on hw using the provided mac address * Set station id on hw using the provided mac address
*/ */
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) int
ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
{ {
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
u32 low_id, high_id; u32 low_id, high_id;
@ -349,14 +385,14 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
} }
/** /**
* ath5k_hw_set_bssid - Set current BSSID on hw * ath5k_hw_set_bssid() - Set current BSSID on hw
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Sets the current BSSID and BSSID mask we have from the * Sets the current BSSID and BSSID mask we have from the
* common struct into the hardware * common struct into the hardware
*/ */
void ath5k_hw_set_bssid(struct ath5k_hw *ah) void
ath5k_hw_set_bssid(struct ath5k_hw *ah)
{ {
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
u16 tim_offset = 0; u16 tim_offset = 0;
@ -389,7 +425,23 @@ void ath5k_hw_set_bssid(struct ath5k_hw *ah)
ath5k_hw_enable_pspoll(ah, NULL, 0); ath5k_hw_enable_pspoll(ah, NULL, 0);
} }
void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) /**
* ath5k_hw_set_bssid_mask() - Filter out bssids we listen
* @ah: The &struct ath5k_hw
* @mask: The BSSID mask to set (array of octets)
*
* BSSID masking is a method used by AR5212 and newer hardware to inform PCU
* which bits of the interface's MAC address should be looked at when trying
* to decide which packets to ACK. In station mode and AP mode with a single
* BSS every bit matters since we lock to only one BSS. In AP mode with
* multiple BSSes (virtual interfaces) not every bit matters because hw must
* accept frames for all BSSes and so we tweak some bits of our mac address
* in order to have multiple BSSes.
*
* For more information check out ../hw.c of the common ath module.
*/
void
ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
{ {
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
@ -400,18 +452,21 @@ void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
ath_hw_setbssidmask(common); ath_hw_setbssidmask(common);
} }
/* /**
* Set multicast filter * ath5k_hw_set_mcast_filter() - Set multicast filter
* @ah: The &struct ath5k_hw
* @filter0: Lower 32bits of muticast filter
* @filter1: Higher 16bits of multicast filter
*/ */
void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) void
ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
{ {
ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
} }
/** /**
* ath5k_hw_get_rx_filter - Get current rx filter * ath5k_hw_get_rx_filter() - Get current rx filter
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Returns the RX filter by reading rx filter and * Returns the RX filter by reading rx filter and
@ -420,7 +475,8 @@ void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
* and pass to the driver. For a list of frame types * and pass to the driver. For a list of frame types
* check out reg.h. * check out reg.h.
*/ */
u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) u32
ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
{ {
u32 data, filter = 0; u32 data, filter = 0;
@ -440,8 +496,7 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
} }
/** /**
* ath5k_hw_set_rx_filter - Set rx filter * ath5k_hw_set_rx_filter() - Set rx filter
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @filter: RX filter mask (see reg.h) * @filter: RX filter mask (see reg.h)
* *
@ -449,7 +504,8 @@ u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
* register on 5212 and newer chips so that we have proper PHY * register on 5212 and newer chips so that we have proper PHY
* error reporting. * error reporting.
*/ */
void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) void
ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
{ {
u32 data = 0; u32 data = 0;
@ -493,13 +549,13 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
#define ATH5K_MAX_TSF_READ 10 #define ATH5K_MAX_TSF_READ 10
/** /**
* ath5k_hw_get_tsf64 - Get the full 64bit TSF * ath5k_hw_get_tsf64() - Get the full 64bit TSF
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Returns the current TSF * Returns the current TSF
*/ */
u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) u64
ath5k_hw_get_tsf64(struct ath5k_hw *ah)
{ {
u32 tsf_lower, tsf_upper1, tsf_upper2; u32 tsf_lower, tsf_upper1, tsf_upper2;
int i; int i;
@ -536,28 +592,30 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
return ((u64)tsf_upper1 << 32) | tsf_lower; return ((u64)tsf_upper1 << 32) | tsf_lower;
} }
#undef ATH5K_MAX_TSF_READ
/** /**
* ath5k_hw_set_tsf64 - Set a new 64bit TSF * ath5k_hw_set_tsf64() - Set a new 64bit TSF
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @tsf64: The new 64bit TSF * @tsf64: The new 64bit TSF
* *
* Sets the new TSF * Sets the new TSF
*/ */
void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) void
ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64)
{ {
ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32);
ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32);
} }
/** /**
* ath5k_hw_reset_tsf - Force a TSF reset * ath5k_hw_reset_tsf() - Force a TSF reset
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Forces a TSF reset on PCU * Forces a TSF reset on PCU
*/ */
void ath5k_hw_reset_tsf(struct ath5k_hw *ah) void
ath5k_hw_reset_tsf(struct ath5k_hw *ah)
{ {
u32 val; u32 val;
@ -573,10 +631,17 @@ void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
ath5k_hw_reg_write(ah, val, AR5K_BEACON); ath5k_hw_reg_write(ah, val, AR5K_BEACON);
} }
/* /**
* Initialize beacon timers * ath5k_hw_init_beacon_timers() - Initialize beacon timers
* @ah: The &struct ath5k_hw
* @next_beacon: Next TBTT
* @interval: Current beacon interval
*
* This function is used to initialize beacon timers based on current
* operation mode and settings.
*/ */
void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) void
ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
{ {
u32 timer1, timer2, timer3; u32 timer1, timer2, timer3;
@ -655,8 +720,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
} }
/** /**
* ath5k_check_timer_win - Check if timer B is timer A + window * ath5k_check_timer_win() - Check if timer B is timer A + window
*
* @a: timer a (before b) * @a: timer a (before b)
* @b: timer b (after a) * @b: timer b (after a)
* @window: difference between a and b * @window: difference between a and b
@ -686,12 +750,11 @@ ath5k_check_timer_win(int a, int b, int window, int intval)
} }
/** /**
* ath5k_hw_check_beacon_timers - Check if the beacon timers are correct * ath5k_hw_check_beacon_timers() - Check if the beacon timers are correct
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @intval: beacon interval * @intval: beacon interval
* *
* This is a workaround for IBSS mode: * This is a workaround for IBSS mode
* *
* The need for this function arises from the fact that we have 4 separate * The need for this function arises from the fact that we have 4 separate
* HW timer registers (TIMER0 - TIMER3), which are closely related to the * HW timer registers (TIMER0 - TIMER3), which are closely related to the
@ -746,14 +809,14 @@ ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval)
} }
/** /**
* ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class * ath5k_hw_set_coverage_class() - Set IEEE 802.11 coverage class
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @coverage_class: IEEE 802.11 coverage class number * @coverage_class: IEEE 802.11 coverage class number
* *
* Sets IFS intervals and ACK/CTS timeouts for given coverage class. * Sets IFS intervals and ACK/CTS timeouts for given coverage class.
*/ */
void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) void
ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
{ {
/* As defined by IEEE 802.11-2007 17.3.8.6 */ /* As defined by IEEE 802.11-2007 17.3.8.6 */
int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class;
@ -772,8 +835,7 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
\***************************/ \***************************/
/** /**
* ath5k_hw_start_rx_pcu - Start RX engine * ath5k_hw_start_rx_pcu() - Start RX engine
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Starts RX engine on PCU so that hw can process RXed frames * Starts RX engine on PCU so that hw can process RXed frames
@ -781,32 +843,33 @@ void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class)
* *
* NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
*/ */
void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) void
ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
{ {
AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
} }
/** /**
* at5k_hw_stop_rx_pcu - Stop RX engine * at5k_hw_stop_rx_pcu() - Stop RX engine
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* *
* Stops RX engine on PCU * Stops RX engine on PCU
*/ */
void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) void
ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
{ {
AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
} }
/** /**
* ath5k_hw_set_opmode - Set PCU operating mode * ath5k_hw_set_opmode() - Set PCU operating mode
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @op_mode: &enum nl80211_iftype operating mode * @op_mode: One of enum nl80211_iftype
* *
* Configure PCU for the various operating modes (AP/STA etc) * Configure PCU for the various operating modes (AP/STA etc)
*/ */
int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) int
ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
{ {
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
u32 pcu_reg, beacon_reg, low_id, high_id; u32 pcu_reg, beacon_reg, low_id, high_id;
@ -873,8 +936,17 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
return 0; return 0;
} }
void ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /**
u8 mode) * ath5k_hw_pcu_init() - Initialize PCU
* @ah: The &struct ath5k_hw
* @op_mode: One of enum nl80211_iftype
* @mode: One of enum ath5k_driver_mode
*
* This function is used to initialize PCU by setting current
* operation mode and various other settings.
*/
void
ath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
{ {
/* Set bssid and bssid mask */ /* Set bssid and bssid mask */
ath5k_hw_set_bssid(ah); ath5k_hw_set_bssid(ah);

File diff suppressed because it is too large Load Diff

View File

@ -17,23 +17,47 @@
*/ */
/********************************************\ /********************************************\
Queue Control Unit, DFS Control Unit Functions Queue Control Unit, DCF Control Unit Functions
\********************************************/ \********************************************/
#include "ath5k.h" #include "ath5k.h"
#include "reg.h" #include "reg.h"
#include "debug.h" #include "debug.h"
/**
* DOC: Queue Control Unit (QCU)/DCF Control Unit (DCU) functions
*
* Here we setup parameters for the 12 available TX queues. Note that
* on the various registers we can usually only map the first 10 of them so
* basically we have 10 queues to play with. Each queue has a matching
* QCU that controls when the queue will get triggered and multiple QCUs
* can be mapped to a single DCU that controls the various DFS parameters
* for the various queues. In our setup we have a 1:1 mapping between QCUs
* and DCUs allowing us to have different DFS settings for each queue.
*
* When a frame goes into a TX queue, QCU decides when it'll trigger a
* transmission based on various criteria (such as how many data we have inside
* it's buffer or -if it's a beacon queue- if it's time to fire up the queue
* based on TSF etc), DCU adds backoff, IFSes etc and then a scheduler
* (arbitrator) decides the priority of each QCU based on it's configuration
* (e.g. beacons are always transmitted when they leave DCU bypassing all other
* frames from other queues waiting to be transmitted). After a frame leaves
* the DCU it goes to PCU for further processing and then to PHY for
* the actual transmission.
*/
/******************\ /******************\
* Helper functions * * Helper functions *
\******************/ \******************/
/* /**
* Get number of pending frames * ath5k_hw_num_tx_pending() - Get number of pending frames for a given queue
* for a specific queue [5211+] * @ah: The &struct ath5k_hw
* @queue: The hw queue number
*/ */
u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) u32
ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
{ {
u32 pending; u32 pending;
AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
@ -58,10 +82,13 @@ u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue)
return pending; return pending;
} }
/* /**
* Set a transmit queue inactive * ath5k_hw_release_tx_queue() - Set a transmit queue inactive
* @ah: The &struct ath5k_hw
* @queue: The hw queue number
*/ */
void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) void
ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
{ {
if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
return; return;
@ -72,10 +99,14 @@ void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
} }
/* /**
* ath5k_cw_validate() - Make sure the given cw is valid
* @cw_req: The contention window value to check
*
* Make sure cw is a power of 2 minus 1 and smaller than 1024 * Make sure cw is a power of 2 minus 1 and smaller than 1024
*/ */
static u16 ath5k_cw_validate(u16 cw_req) static u16
ath5k_cw_validate(u16 cw_req)
{ {
u32 cw = 1; u32 cw = 1;
cw_req = min(cw_req, (u16)1023); cw_req = min(cw_req, (u16)1023);
@ -86,20 +117,30 @@ static u16 ath5k_cw_validate(u16 cw_req)
return cw; return cw;
} }
/* /**
* Get properties for a transmit queue * ath5k_hw_get_tx_queueprops() - Get properties for a transmit queue
* @ah: The &struct ath5k_hw
* @queue: The hw queue number
* @queue_info: The &struct ath5k_txq_info to fill
*/ */
int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, int
ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
struct ath5k_txq_info *queue_info) struct ath5k_txq_info *queue_info)
{ {
memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
return 0; return 0;
} }
/* /**
* Set properties for a transmit queue * ath5k_hw_set_tx_queueprops() - Set properties for a transmit queue
* @ah: The &struct ath5k_hw
* @queue: The hw queue number
* @qinfo: The &struct ath5k_txq_info to use
*
* Returns 0 on success or -EIO if queue is inactive
*/ */
int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, int
ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
const struct ath5k_txq_info *qinfo) const struct ath5k_txq_info *qinfo)
{ {
struct ath5k_txq_info *qi; struct ath5k_txq_info *qi;
@ -139,10 +180,16 @@ int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue,
return 0; return 0;
} }
/* /**
* Initialize a transmit queue * ath5k_hw_setup_tx_queue() - Initialize a transmit queue
* @ah: The &struct ath5k_hw
* @queue_type: One of enum ath5k_tx_queue
* @queue_info: The &struct ath5k_txq_info to use
*
* Returns 0 on success, -EINVAL on invalid arguments
*/ */
int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, int
ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
struct ath5k_txq_info *queue_info) struct ath5k_txq_info *queue_info)
{ {
unsigned int queue; unsigned int queue;
@ -217,10 +264,16 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
* Single QCU/DCU initialization * * Single QCU/DCU initialization *
\*******************************/ \*******************************/
/* /**
* Set tx retry limits on DCU * ath5k_hw_set_tx_retry_limits() - Set tx retry limits on DCU
* @ah: The &struct ath5k_hw
* @queue: The hw queue number
*
* This function is used when initializing a queue, to set
* retry limits based on ah->ah_retry_* and the chipset used.
*/ */
void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah, void
ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
unsigned int queue) unsigned int queue)
{ {
/* Single data queue on AR5210 */ /* Single data queue on AR5210 */
@ -255,15 +308,15 @@ void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
} }
/** /**
* ath5k_hw_reset_tx_queue - Initialize a single hw queue * ath5k_hw_reset_tx_queue() - Initialize a single hw queue
* * @ah: The &struct ath5k_hw
* @ah The &struct ath5k_hw * @queue: The hw queue number
* @queue The hw queue number
* *
* Set DFS properties for the given transmit queue on DCU * Set DFS properties for the given transmit queue on DCU
* and configures all queue-specific parameters. * and configures all queue-specific parameters.
*/ */
int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) int
ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
{ {
struct ath5k_txq_info *tq = &ah->ah_txq[queue]; struct ath5k_txq_info *tq = &ah->ah_txq[queue];
@ -491,10 +544,9 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
\**************************/ \**************************/
/** /**
* ath5k_hw_set_ifs_intervals - Set global inter-frame spaces on DCU * ath5k_hw_set_ifs_intervals() - Set global inter-frame spaces on DCU
* * @ah: The &struct ath5k_hw
* @ah The &struct ath5k_hw * @slot_time: Slot time in us
* @slot_time Slot time in us
* *
* Sets the global IFS intervals on DCU (also works on AR5210) for * Sets the global IFS intervals on DCU (also works on AR5210) for
* the given slot time and the current bwmode. * the given slot time and the current bwmode.
@ -597,7 +649,15 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
} }
int ath5k_hw_init_queues(struct ath5k_hw *ah) /**
* ath5k_hw_init_queues() - Initialize tx queues
* @ah: The &struct ath5k_hw
*
* Initializes all tx queues based on information on
* ah->ah_txq* set by the driver
*/
int
ath5k_hw_init_queues(struct ath5k_hw *ah)
{ {
int i, ret; int i, ret;

View File

@ -19,9 +19,9 @@
* *
*/ */
/*****************************\ /****************************\
Reset functions and helpers Reset function and helpers
\*****************************/ \****************************/
#include <asm/unaligned.h> #include <asm/unaligned.h>
@ -33,14 +33,36 @@
#include "debug.h" #include "debug.h"
/**
* DOC: Reset function and helpers
*
* Here we implement the main reset routine, used to bring the card
* to a working state and ready to receive. We also handle routines
* that don't fit on other places such as clock, sleep and power control
*/
/******************\ /******************\
* Helper functions * * Helper functions *
\******************/ \******************/
/* /**
* Check if a register write has been completed * ath5k_hw_register_timeout() - Poll a register for a flag/field change
* @ah: The &struct ath5k_hw
* @reg: The register to read
* @flag: The flag/field to check on the register
* @val: The field value we expect (if we check a field)
* @is_set: Instead of checking if the flag got cleared, check if it got set
*
* Some registers contain flags that indicate that an operation is
* running. We use this function to poll these registers and check
* if these flags get cleared. We also use it to poll a register
* field (containing multiple flags) until it gets a specific value.
*
* Returns -EAGAIN if we exceeded AR5K_TUNE_REGISTER_TIMEOUT * 15us or 0
*/ */
int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, int
ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
bool is_set) bool is_set)
{ {
int i; int i;
@ -64,35 +86,48 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
\*************************/ \*************************/
/** /**
* ath5k_hw_htoclock - Translate usec to hw clock units * ath5k_hw_htoclock() - Translate usec to hw clock units
*
* @ah: The &struct ath5k_hw * @ah: The &struct ath5k_hw
* @usec: value in microseconds * @usec: value in microseconds
*
* Translate usecs to hw clock units based on the current
* hw clock rate.
*
* Returns number of clock units
*/ */
unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) unsigned int
ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec)
{ {
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
return usec * common->clockrate; return usec * common->clockrate;
} }
/** /**
* ath5k_hw_clocktoh - Translate hw clock units to usec * ath5k_hw_clocktoh() - Translate hw clock units to usec
* @ah: The &struct ath5k_hw
* @clock: value in hw clock units * @clock: value in hw clock units
*
* Translate hw clock units to usecs based on the current
* hw clock rate.
*
* Returns number of usecs
*/ */
unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) unsigned int
ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock)
{ {
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
return clock / common->clockrate; return clock / common->clockrate;
} }
/** /**
* ath5k_hw_init_core_clock - Initialize core clock * ath5k_hw_init_core_clock() - Initialize core clock
* @ah: The &struct ath5k_hw
* *
* @ah The &struct ath5k_hw * Initialize core clock parameters (usec, usec32, latencies etc),
* * based on current bwmode and chipset properties.
* Initialize core clock parameters (usec, usec32, latencies etc).
*/ */
static void ath5k_hw_init_core_clock(struct ath5k_hw *ah) static void
ath5k_hw_init_core_clock(struct ath5k_hw *ah)
{ {
struct ieee80211_channel *channel = ah->ah_current_channel; struct ieee80211_channel *channel = ah->ah_current_channel;
struct ath_common *common = ath5k_hw_common(ah); struct ath_common *common = ath5k_hw_common(ah);
@ -227,16 +262,21 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
} }
} }
/* /**
* ath5k_hw_set_sleep_clock() - Setup sleep clock operation
* @ah: The &struct ath5k_hw
* @enable: Enable sleep clock operation (false to disable)
*
* If there is an external 32KHz crystal available, use it * If there is an external 32KHz crystal available, use it
* as ref. clock instead of 32/40MHz clock and baseband clocks * as ref. clock instead of 32/40MHz clock and baseband clocks
* to save power during sleep or restore normal 32/40MHz * to save power during sleep or restore normal 32/40MHz
* operation. * operation.
* *
* XXX: When operating on 32KHz certain PHY registers (27 - 31, * NOTE: When operating on 32KHz certain PHY registers (27 - 31,
* 123 - 127) require delay on access. * 123 - 127) require delay on access.
*/ */
static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) static void
ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
{ {
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
u32 scal, spending, sclock; u32 scal, spending, sclock;
@ -340,10 +380,19 @@ static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable)
* Reset/Sleep control * * Reset/Sleep control *
\*********************/ \*********************/
/* /**
* Reset chipset * ath5k_hw_nic_reset() - Reset the various chipset units
* @ah: The &struct ath5k_hw
* @val: Mask to indicate what units to reset
*
* To reset the various chipset units we need to write
* the mask to AR5K_RESET_CTL and poll the register until
* all flags are cleared.
*
* Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout)
*/ */
static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) static int
ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
{ {
int ret; int ret;
u32 mask = val ? val : ~0U; u32 mask = val ? val : ~0U;
@ -382,12 +431,17 @@ static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
return ret; return ret;
} }
/* /**
* Reset AHB chipset * ath5k_hw_wisoc_reset() - Reset AHB chipset
* AR5K_RESET_CTL_PCU flag resets WMAC * @ah: The &struct ath5k_hw
* AR5K_RESET_CTL_BASEBAND flag resets WBB * @flags: Mask to indicate what units to reset
*
* Same as ath5k_hw_nic_reset but for AHB based devices
*
* Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout)
*/ */
static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) static int
ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
{ {
u32 mask = flags ? flags : ~0U; u32 mask = flags ? flags : ~0U;
u32 __iomem *reg; u32 __iomem *reg;
@ -439,11 +493,23 @@ static int ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags)
return 0; return 0;
} }
/**
/* * ath5k_hw_set_power_mode() - Set power mode
* Sleep control * @ah: The &struct ath5k_hw
* @mode: One of enum ath5k_power_mode
* @set_chip: Set to true to write sleep control register
* @sleep_duration: How much time the device is allowed to sleep
* when sleep logic is enabled (in 128 microsecond increments).
*
* This function is used to configure sleep policy and allowed
* sleep modes. For more information check out the sleep control
* register on reg.h and STA_ID1.
*
* Returns 0 on success, -EIO if chip didn't wake up or -EINVAL if an invalid
* mode is requested.
*/ */
static int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, static int
ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode,
bool set_chip, u16 sleep_duration) bool set_chip, u16 sleep_duration)
{ {
unsigned int i; unsigned int i;
@ -523,17 +589,20 @@ commit:
return 0; return 0;
} }
/* /**
* Put device on hold * ath5k_hw_on_hold() - Put device on hold
* @ah: The &struct ath5k_hw
* *
* Put MAC and Baseband on warm reset and * Put MAC and Baseband on warm reset and keep that state
* keep that state (don't clean sleep control * (don't clean sleep control register). After this MAC
* register). After this MAC and Baseband are * and Baseband are disabled and a full reset is needed
* disabled and a full reset is needed to come * to come back. This way we save as much power as possible
* back. This way we save as much power as possible
* without putting the card on full sleep. * without putting the card on full sleep.
*
* Returns 0 on success or -EIO on error
*/ */
int ath5k_hw_on_hold(struct ath5k_hw *ah) int
ath5k_hw_on_hold(struct ath5k_hw *ah)
{ {
struct pci_dev *pdev = ah->pdev; struct pci_dev *pdev = ah->pdev;
u32 bus_flags; u32 bus_flags;
@ -543,7 +612,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
return 0; return 0;
/* Make sure device is awake */ /* Make sure device is awake */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0);
if (ret) { if (ret) {
ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
return ret; return ret;
@ -575,7 +644,7 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
} }
/* ...wakeup again!*/ /* ...wakeup again!*/
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0);
if (ret) { if (ret) {
ATH5K_ERR(ah, "failed to put device on hold\n"); ATH5K_ERR(ah, "failed to put device on hold\n");
return ret; return ret;
@ -584,11 +653,18 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
return ret; return ret;
} }
/* /**
* ath5k_hw_nic_wakeup() - Force card out of sleep
* @ah: The &struct ath5k_hw
* @channel: The &struct ieee80211_channel
*
* Bring up MAC + PHY Chips and program PLL * Bring up MAC + PHY Chips and program PLL
* Channel is NULL for the initial wakeup. * NOTE: Channel is NULL for the initial wakeup.
*
* Returns 0 on success, -EIO on hw failure or -EINVAL for false channel infos
*/ */
int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) int
ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
{ {
struct pci_dev *pdev = ah->pdev; struct pci_dev *pdev = ah->pdev;
u32 turbo, mode, clock, bus_flags; u32 turbo, mode, clock, bus_flags;
@ -600,7 +676,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) {
/* Wakeup the device */ /* Wakeup the device */
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0);
if (ret) { if (ret) {
ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n");
return ret; return ret;
@ -637,7 +713,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
} }
/* ...wakeup again!...*/ /* ...wakeup again!...*/
ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0);
if (ret) { if (ret) {
ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); ATH5K_ERR(ah, "failed to resume the MAC Chip\n");
return ret; return ret;
@ -755,8 +831,19 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
* Post-initvals register modifications * * Post-initvals register modifications *
\**************************************/ \**************************************/
/* TODO: Half/Quarter rate */ /**
static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, * ath5k_hw_tweak_initval_settings() - Tweak initial settings
* @ah: The &struct ath5k_hw
* @channel: The &struct ieee80211_channel
*
* Some settings are not handled on initvals, e.g. bwmode
* settings, some phy settings, workarounds etc that in general
* don't fit anywhere else or are too small to introduce a separate
* function for each one. So we have this function to handle
* them all during reset and complete card's initialization.
*/
static void
ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
struct ieee80211_channel *channel) struct ieee80211_channel *channel)
{ {
if (ah->ah_version == AR5K_AR5212 && if (ah->ah_version == AR5K_AR5212 &&
@ -875,7 +962,16 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
} }
} }
static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, /**
* ath5k_hw_commit_eeprom_settings() - Commit settings from EEPROM
* @ah: The &struct ath5k_hw
* @channel: The &struct ieee80211_channel
*
* Use settings stored on EEPROM to properly initialize the card
* based on various infos and per-mode calibration data.
*/
static void
ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
struct ieee80211_channel *channel) struct ieee80211_channel *channel)
{ {
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
@ -1029,7 +1125,23 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
* Main reset function * * Main reset function *
\*********************/ \*********************/
int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, /**
* ath5k_hw_reset() - The main reset function
* @ah: The &struct ath5k_hw
* @op_mode: One of enum nl80211_iftype
* @channel: The &struct ieee80211_channel
* @fast: Enable fast channel switching
* @skip_pcu: Skip pcu initialization
*
* This is the function we call each time we want to (re)initialize the
* card and pass new settings to hw. We also call it when hw runs into
* trouble to make it come back to a working state.
*
* Returns 0 on success, -EINVAL on false op_mode or channel infos, or -EIO
* on failure.
*/
int
ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
struct ieee80211_channel *channel, bool fast, bool skip_pcu) struct ieee80211_channel *channel, bool fast, bool skip_pcu)
{ {
u32 s_seq[10], s_led[3], tsf_up, tsf_lo; u32 s_seq[10], s_led[3], tsf_up, tsf_lo;
@ -1242,7 +1354,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* /*
* Initialize PCU * Initialize PCU
*/ */
ath5k_hw_pcu_init(ah, op_mode, mode); ath5k_hw_pcu_init(ah, op_mode);
/* /*
* Initialize PHY * Initialize PHY

View File

@ -18,7 +18,9 @@
*/ */
/* /**
* DOC: RF Buffer registers
*
* There are some special registers on the RF chip * There are some special registers on the RF chip
* that control various operation settings related mostly to * that control various operation settings related mostly to
* the analog parts (channel, gain adjustment etc). * the analog parts (channel, gain adjustment etc).
@ -44,40 +46,63 @@
*/ */
/* /**
* struct ath5k_ini_rfbuffer - Initial RF Buffer settings
* @rfb_bank: RF Bank number
* @rfb_ctrl_register: RF Buffer control register
* @rfb_mode_data: RF Buffer data for each mode
*
* Struct to hold default mode specific RF * Struct to hold default mode specific RF
* register values (RF Banks) * register values (RF Banks) for each chip.
*/ */
struct ath5k_ini_rfbuffer { struct ath5k_ini_rfbuffer {
u8 rfb_bank; /* RF Bank number */ u8 rfb_bank;
u16 rfb_ctrl_register; /* RF Buffer control register */ u16 rfb_ctrl_register;
u32 rfb_mode_data[3]; /* RF Buffer data for each mode */ u32 rfb_mode_data[3];
}; };
/* /**
* struct ath5k_rfb_field - An RF Buffer field (register/value)
* @len: Field length
* @pos: Offset on the raw packet
* @col: Used for shifting
*
* Struct to hold RF Buffer field * Struct to hold RF Buffer field
* infos used to access certain RF * infos used to access certain RF
* analog registers * analog registers
*/ */
struct ath5k_rfb_field { struct ath5k_rfb_field {
u8 len; /* Field length */ u8 len;
u16 pos; /* Offset on the raw packet */ u16 pos;
u8 col; /* Column -used for shifting */ u8 col;
}; };
/* /**
* RF analog register definition * struct ath5k_rf_reg - RF analog register definition
* @bank: RF Buffer Bank number
* @index: Register's index on ath5k_rf_regx_idx
* @field: The &struct ath5k_rfb_field
*
* We use this struct to define the set of RF registers
* on each chip that we want to tweak. Some RF registers
* are common between different chip versions so this saves
* us space and complexity because we can refer to an rf
* register by it's index no matter what chip we work with
* as long as it has that register.
*/ */
struct ath5k_rf_reg { struct ath5k_rf_reg {
u8 bank; /* RF Buffer Bank number */ u8 bank;
u8 index; /* Register's index on rf_regs_idx */ u8 index;
struct ath5k_rfb_field field; /* RF Buffer field for this register */ struct ath5k_rfb_field field;
}; };
/* Map RF registers to indexes /**
* enum ath5k_rf_regs_idx - Map RF registers to indexes
*
* We do this to handle common bits and make our * We do this to handle common bits and make our
* life easier by using an index for each register * life easier by using an index for each register
* instead of a full rfb_field */ * instead of a full rfb_field
*/
enum ath5k_rf_regs_idx { enum ath5k_rf_regs_idx {
/* BANK 2 */ /* BANK 2 */
AR5K_RF_TURBO = 0, AR5K_RF_TURBO = 0,

View File

@ -18,13 +18,17 @@
* *
*/ */
/* /**
* struct ath5k_ini_rfgain - RF Gain table
* @rfg_register: RF Gain register address
* @rfg_value: Register value for 5 and 2GHz
*
* Mode-specific RF Gain table (64bytes) for RF5111/5112 * Mode-specific RF Gain table (64bytes) for RF5111/5112
* (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
* RF Gain values are included in AR5K_AR5210_INI) * RF Gain values are included in AR5K_AR5210_INI)
*/ */
struct ath5k_ini_rfgain { struct ath5k_ini_rfgain {
u16 rfg_register; /* RF Gain register address */ u16 rfg_register;
u32 rfg_value[2]; /* [freq (see below)] */ u32 rfg_value[2]; /* [freq (see below)] */
}; };
@ -455,18 +459,31 @@ static const struct ath5k_ini_rfgain rfgain_2425[] = {
#define AR5K_GAIN_CHECK_ADJUST(_g) \ #define AR5K_GAIN_CHECK_ADJUST(_g) \
((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
/**
* struct ath5k_gain_opt_step - An RF gain optimization step
* @gos_param: Set of parameters
* @gos_gain: Gain
*/
struct ath5k_gain_opt_step { struct ath5k_gain_opt_step {
s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
s8 gos_gain; s8 gos_gain;
}; };
/**
* struct ath5k_gain_opt - RF Gain optimization ladder
* @go_default: The default step
* @go_steps_count: How many optimization steps
* @go_step: Array of &struct ath5k_gain_opt_step
*/
struct ath5k_gain_opt { struct ath5k_gain_opt {
u8 go_default; u8 go_default;
u8 go_steps_count; u8 go_steps_count;
const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT];
}; };
/* /*
* RF5111
* Parameters on gos_param: * Parameters on gos_param:
* 1) Tx clip PHY register * 1) Tx clip PHY register
* 2) PWD 90 RF register * 2) PWD 90 RF register
@ -490,6 +507,7 @@ static const struct ath5k_gain_opt rfgain_opt_5111 = {
}; };
/* /*
* RF5112
* Parameters on gos_param: * Parameters on gos_param:
* 1) Mixgain ovr RF register * 1) Mixgain ovr RF register
* 2) PWD 138 RF register * 2) PWD 138 RF register