Merge branch 'master' into for-davem

Conflicts:
	drivers/net/wireless/ath/ath9k/phy.c
	drivers/net/wireless/iwlwifi/iwl-6000.c
	drivers/net/wireless/iwlwifi/iwl-debugfs.c
This commit is contained in:
John W. Linville 2010-04-23 14:43:45 -04:00
commit 3b51cc996e
127 changed files with 19021 additions and 8935 deletions

View File

@ -210,90 +210,7 @@ config USB_NET_RNDIS_WLAN
If you choose to build a module, it'll be called rndis_wlan.
config RTL8180
tristate "Realtek 8180/8185 PCI support"
depends on MAC80211 && PCI && EXPERIMENTAL
select EEPROM_93CX6
---help---
This is a driver for RTL8180 and RTL8185 based cards.
These are PCI based chips found in cards such as:
(RTL8185 802.11g)
A-Link WL54PC
(RTL8180 802.11b)
Belkin F5D6020 v3
Belkin F5D6020 v3
Dlink DWL-610
Dlink DWL-510
Netgear MA521
Level-One WPC-0101
Acer Aspire 1357 LMi
VCTnet PC-11B1
Ovislink AirLive WL-1120PCM
Mentor WL-PCI
Linksys WPC11 v4
TrendNET TEW-288PI
D-Link DWL-520 Rev D
Repotec RP-WP7126
TP-Link TL-WN250/251
Zonet ZEW1000
Longshine LCS-8031-R
HomeLine HLW-PCC200
GigaFast WF721-AEX
Planet WL-3553
Encore ENLWI-PCI1-NT
TrendNET TEW-266PC
Gigabyte GN-WLMR101
Siemens-fujitsu Amilo D1840W
Edimax EW-7126
PheeNet WL-11PCIR
Tonze PC-2100T
Planet WL-8303
Dlink DWL-650 v M1
Edimax EW-7106
Q-Tec 770WC
Topcom Skyr@cer 4011b
Roper FreeLan 802.11b (edition 2004)
Wistron Neweb Corp CB-200B
Pentagram HorNET
QTec 775WC
TwinMOS Booming B Series
Micronet SP906BB
Sweex LC700010
Surecom EP-9428
Safecom SWLCR-1100
Thanks to Realtek for their support!
config RTL8187
tristate "Realtek 8187 and 8187B USB support"
depends on MAC80211 && USB
select EEPROM_93CX6
---help---
This is a driver for RTL8187 and RTL8187B based cards.
These are USB based chips found in devices such as:
Netgear WG111v2
Level 1 WNC-0301USB
Micronet SP907GK V5
Encore ENUWI-G2
Trendnet TEW-424UB
ASUS P5B Deluxe/P5K Premium motherboards
Toshiba Satellite Pro series of laptops
Asus Wireless Link
Linksys WUSB54GC-EU v2
(v1 = rt73usb; v3 is rt2070-based,
use staging/rt3070 or try rt2800usb)
Thanks to Realtek for their support!
# If possible, automatically enable LEDs for RTL8187.
config RTL8187_LEDS
bool
depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187)
default y
source "drivers/net/wireless/rtl818x/Kconfig"
config ADM8211
tristate "ADMtek ADM8211 support"

View File

@ -71,9 +71,21 @@ struct ath_regulatory {
struct reg_dmn_pair_mapping *regpair;
};
/**
* struct ath_ops - Register read/write operations
*
* @read: Register read
* @write: Register write
* @enable_write_buffer: Enable multiple register writes
* @disable_write_buffer: Disable multiple register writes
* @write_flush: Flush buffered register writes
*/
struct ath_ops {
unsigned int (*read)(void *, u32 reg_offset);
void (*write)(void *, u32 val, u32 reg_offset);
void (*write)(void *, u32 val, u32 reg_offset);
void (*enable_write_buffer)(void *);
void (*disable_write_buffer)(void *);
void (*write_flush) (void *);
};
struct ath_common;

View File

@ -242,6 +242,8 @@ static int ath5k_set_key(struct ieee80211_hw *hw,
struct ieee80211_key_conf *key);
static int ath5k_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
static int ath5k_get_survey(struct ieee80211_hw *hw,
int idx, struct survey_info *survey);
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
@ -267,6 +269,7 @@ static const struct ieee80211_ops ath5k_hw_ops = {
.configure_filter = ath5k_configure_filter,
.set_key = ath5k_set_key,
.get_stats = ath5k_get_stats,
.get_survey = ath5k_get_survey,
.conf_tx = NULL,
.get_tsf = ath5k_get_tsf,
.set_tsf = ath5k_set_tsf,
@ -3292,6 +3295,22 @@ ath5k_get_stats(struct ieee80211_hw *hw,
return 0;
}
static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
struct ath5k_softc *sc = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
if (idx != 0)
return -ENOENT;
survey->channel = conf->channel;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = sc->ah->ah_noise_floor;
return 0;
}
static u64
ath5k_get_tsf(struct ieee80211_hw *hw)
{

View File

@ -496,6 +496,8 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
* Beacon control *
\****************/
#define ATH5K_MAX_TSF_READ 10
/**
* ath5k_hw_get_tsf64 - Get the full 64bit TSF
*
@ -505,10 +507,35 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
*/
u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
{
u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
u32 tsf_lower, tsf_upper1, tsf_upper2;
int i;
/*
* While reading TSF upper and then lower part, the clock is still
* counting (or jumping in case of IBSS merge) so we might get
* inconsistent values. To avoid this, we read the upper part again
* and check it has not been changed. We make the hypothesis that a
* maximum of 3 changes can happens in a row (we use 10 as a safe
* value).
*
* Impact on performance is pretty small, since in most cases, only
* 3 register reads are needed.
*/
tsf_upper1 = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
for (i = 0; i < ATH5K_MAX_TSF_READ; i++) {
tsf_lower = ath5k_hw_reg_read(ah, AR5K_TSF_L32);
tsf_upper2 = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
if (tsf_upper2 == tsf_upper1)
break;
tsf_upper1 = tsf_upper2;
}
WARN_ON( i == ATH5K_MAX_TSF_READ );
ATH5K_TRACE(ah->ah_sc);
return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
return (((u64)tsf_upper1 << 32) | tsf_lower);
}
/**

View File

@ -13,16 +13,26 @@ ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
obj-$(CONFIG_ATH9K) += ath9k.o
ath9k_hw-y:= hw.o \
ath9k_hw-y:= \
ar9002_hw.o \
ar9003_hw.o \
hw.o \
ar9003_phy.o \
ar9002_phy.o \
ar5008_phy.o \
ar9002_calib.o \
ar9003_calib.o \
calib.o \
eeprom.o \
eeprom_def.o \
eeprom_4k.o \
eeprom_9287.o \
calib.o \
ani.o \
phy.o \
btcoex.o \
mac.o \
ar9002_mac.o \
ar9003_mac.o \
ar9003_eeprom.o
obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o

View File

@ -15,6 +15,7 @@
*/
#include "hw.h"
#include "hw-ops.h"
static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
struct ath9k_channel *chan)
@ -37,190 +38,6 @@ static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
return 0;
}
static bool ath9k_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
struct ar5416AniState *aniState = ah->curani;
struct ath_common *common = ath9k_hw_common(ah);
switch (cmd & ah->ani_function) {
case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
u32 level = param;
if (level >= ARRAY_SIZE(ah->totalSizeDesired)) {
ath_print(common, ATH_DBG_ANI,
"level out of range (%u > %u)\n",
level,
(unsigned)ARRAY_SIZE(ah->totalSizeDesired));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
AR_PHY_DESIRED_SZ_TOT_DES,
ah->totalSizeDesired[level]);
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
AR_PHY_AGC_CTL1_COARSE_LOW,
ah->coarse_low[level]);
REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
AR_PHY_AGC_CTL1_COARSE_HIGH,
ah->coarse_high[level]);
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRPWR,
ah->firpwr[level]);
if (level > aniState->noiseImmunityLevel)
ah->stats.ast_ani_niup++;
else if (level < aniState->noiseImmunityLevel)
ah->stats.ast_ani_nidown++;
aniState->noiseImmunityLevel = level;
break;
}
case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
const int m1ThreshLow[] = { 127, 50 };
const int m2ThreshLow[] = { 127, 40 };
const int m1Thresh[] = { 127, 0x4d };
const int m2Thresh[] = { 127, 0x40 };
const int m2CountThr[] = { 31, 16 };
const int m2CountThrLow[] = { 63, 48 };
u32 on = param ? 1 : 0;
REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
m1ThreshLow[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
m2ThreshLow[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR,
AR_PHY_SFCORR_M1_THRESH,
m1Thresh[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR,
AR_PHY_SFCORR_M2_THRESH,
m2Thresh[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR,
AR_PHY_SFCORR_M2COUNT_THR,
m2CountThr[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
m2CountThrLow[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
m1ThreshLow[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
m2ThreshLow[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
AR_PHY_SFCORR_EXT_M1_THRESH,
m1Thresh[on]);
REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
AR_PHY_SFCORR_EXT_M2_THRESH,
m2Thresh[on]);
if (on)
REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
else
REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
if (!on != aniState->ofdmWeakSigDetectOff) {
if (on)
ah->stats.ast_ani_ofdmon++;
else
ah->stats.ast_ani_ofdmoff++;
aniState->ofdmWeakSigDetectOff = !on;
}
break;
}
case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
const int weakSigThrCck[] = { 8, 6 };
u32 high = param ? 1 : 0;
REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
weakSigThrCck[high]);
if (high != aniState->cckWeakSigThreshold) {
if (high)
ah->stats.ast_ani_cckhigh++;
else
ah->stats.ast_ani_ccklow++;
aniState->cckWeakSigThreshold = high;
}
break;
}
case ATH9K_ANI_FIRSTEP_LEVEL:{
const int firstep[] = { 0, 4, 8 };
u32 level = param;
if (level >= ARRAY_SIZE(firstep)) {
ath_print(common, ATH_DBG_ANI,
"level out of range (%u > %u)\n",
level,
(unsigned) ARRAY_SIZE(firstep));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRSTEP,
firstep[level]);
if (level > aniState->firstepLevel)
ah->stats.ast_ani_stepup++;
else if (level < aniState->firstepLevel)
ah->stats.ast_ani_stepdown++;
aniState->firstepLevel = level;
break;
}
case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
const int cycpwrThr1[] =
{ 2, 4, 6, 8, 10, 12, 14, 16 };
u32 level = param;
if (level >= ARRAY_SIZE(cycpwrThr1)) {
ath_print(common, ATH_DBG_ANI,
"level out of range (%u > %u)\n",
level,
(unsigned) ARRAY_SIZE(cycpwrThr1));
return false;
}
REG_RMW_FIELD(ah, AR_PHY_TIMING5,
AR_PHY_TIMING5_CYCPWR_THR1,
cycpwrThr1[level]);
if (level > aniState->spurImmunityLevel)
ah->stats.ast_ani_spurup++;
else if (level < aniState->spurImmunityLevel)
ah->stats.ast_ani_spurdown++;
aniState->spurImmunityLevel = level;
break;
}
case ATH9K_ANI_PRESENT:
break;
default:
ath_print(common, ATH_DBG_ANI,
"invalid cmd %u\n", cmd);
return false;
}
ath_print(common, ATH_DBG_ANI, "ANI parameters:\n");
ath_print(common, ATH_DBG_ANI,
"noiseImmunityLevel=%d, spurImmunityLevel=%d, "
"ofdmWeakSigDetectOff=%d\n",
aniState->noiseImmunityLevel,
aniState->spurImmunityLevel,
!aniState->ofdmWeakSigDetectOff);
ath_print(common, ATH_DBG_ANI,
"cckWeakSigThreshold=%d, "
"firstepLevel=%d, listenTime=%d\n",
aniState->cckWeakSigThreshold,
aniState->firstepLevel,
aniState->listenTime);
ath_print(common, ATH_DBG_ANI,
"cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
aniState->cycleCount,
aniState->ofdmPhyErrCount,
aniState->cckPhyErrCount);
return true;
}
static void ath9k_hw_update_mibstats(struct ath_hw *ah,
struct ath9k_mib_stats *stats)
{
@ -262,11 +79,17 @@ static void ath9k_ani_restart(struct ath_hw *ah)
"Writing ofdmbase=%u cckbase=%u\n",
aniState->ofdmPhyErrBase,
aniState->cckPhyErrBase);
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
aniState->ofdmPhyErrCount = 0;
@ -540,8 +363,14 @@ void ath9k_ani_reset(struct ath_hw *ah)
ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
~ATH9K_RX_FILTER_PHYERR);
ath9k_ani_restart(ah);
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
}
void ath9k_hw_ani_monitor(struct ath_hw *ah,
@ -639,6 +468,8 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_FILT_OFDM, 0);
REG_WRITE(ah, AR_FILT_CCK, 0);
REG_WRITE(ah, AR_MIBC,
@ -646,6 +477,9 @@ void ath9k_enable_mib_counters(struct ath_hw *ah)
& 0x0f);
REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
}
/* Freeze the MIB counters, get the stats and then clear them */
@ -809,8 +643,14 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
ath_print(common, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
ah->ani[0].cckPhyErrBase);
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
ath9k_enable_mib_counters(ah);
ah->aniperiod = ATH9K_ANI_PERIOD;

View File

@ -0,0 +1,742 @@
/*
* Copyright (c) 2008-2009 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef INITVALS_AR5008_H
#define INITVALS_AR5008_H
static const u32 ar5416Modes[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
{ 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
{ 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
{ 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
{ 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
{ 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 },
{ 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a },
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
{ 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
{ 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x00009850, 0x6c48b4e0, 0x6d48b4e0, 0x6d48b0de, 0x6c48b0de, 0x6c48b0de },
{ 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
{ 0x0000985c, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e, 0x31395d5e },
{ 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 },
{ 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
{ 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
{ 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
{ 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 },
{ 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b },
{ 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
{ 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
{ 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
{ 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
{ 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 },
{ 0x000099bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 },
{ 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
{ 0x000099c8, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c, 0x6af6532c },
{ 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
{ 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
{ 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
{ 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
{ 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 },
{ 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
{ 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
{ 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
{ 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
{ 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
{ 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
{ 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
{ 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
{ 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
{ 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
{ 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
{ 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
{ 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
{ 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
};
static const u32 ar5416Common[][2] = {
{ 0x0000000c, 0x00000000 },
{ 0x00000030, 0x00020015 },
{ 0x00000034, 0x00000005 },
{ 0x00000040, 0x00000000 },
{ 0x00000044, 0x00000008 },
{ 0x00000048, 0x00000008 },
{ 0x0000004c, 0x00000010 },
{ 0x00000050, 0x00000000 },
{ 0x00000054, 0x0000001f },
{ 0x00000800, 0x00000000 },
{ 0x00000804, 0x00000000 },
{ 0x00000808, 0x00000000 },
{ 0x0000080c, 0x00000000 },
{ 0x00000810, 0x00000000 },
{ 0x00000814, 0x00000000 },
{ 0x00000818, 0x00000000 },
{ 0x0000081c, 0x00000000 },
{ 0x00000820, 0x00000000 },
{ 0x00000824, 0x00000000 },
{ 0x00001040, 0x002ffc0f },
{ 0x00001044, 0x002ffc0f },
{ 0x00001048, 0x002ffc0f },
{ 0x0000104c, 0x002ffc0f },
{ 0x00001050, 0x002ffc0f },
{ 0x00001054, 0x002ffc0f },
{ 0x00001058, 0x002ffc0f },
{ 0x0000105c, 0x002ffc0f },
{ 0x00001060, 0x002ffc0f },
{ 0x00001064, 0x002ffc0f },
{ 0x00001230, 0x00000000 },
{ 0x00001270, 0x00000000 },
{ 0x00001038, 0x00000000 },
{ 0x00001078, 0x00000000 },
{ 0x000010b8, 0x00000000 },
{ 0x000010f8, 0x00000000 },
{ 0x00001138, 0x00000000 },
{ 0x00001178, 0x00000000 },
{ 0x000011b8, 0x00000000 },
{ 0x000011f8, 0x00000000 },
{ 0x00001238, 0x00000000 },
{ 0x00001278, 0x00000000 },
{ 0x000012b8, 0x00000000 },
{ 0x000012f8, 0x00000000 },
{ 0x00001338, 0x00000000 },
{ 0x00001378, 0x00000000 },
{ 0x000013b8, 0x00000000 },
{ 0x000013f8, 0x00000000 },
{ 0x00001438, 0x00000000 },
{ 0x00001478, 0x00000000 },
{ 0x000014b8, 0x00000000 },
{ 0x000014f8, 0x00000000 },
{ 0x00001538, 0x00000000 },
{ 0x00001578, 0x00000000 },
{ 0x000015b8, 0x00000000 },
{ 0x000015f8, 0x00000000 },
{ 0x00001638, 0x00000000 },
{ 0x00001678, 0x00000000 },
{ 0x000016b8, 0x00000000 },
{ 0x000016f8, 0x00000000 },
{ 0x00001738, 0x00000000 },
{ 0x00001778, 0x00000000 },
{ 0x000017b8, 0x00000000 },
{ 0x000017f8, 0x00000000 },
{ 0x0000103c, 0x00000000 },
{ 0x0000107c, 0x00000000 },
{ 0x000010bc, 0x00000000 },
{ 0x000010fc, 0x00000000 },
{ 0x0000113c, 0x00000000 },
{ 0x0000117c, 0x00000000 },
{ 0x000011bc, 0x00000000 },
{ 0x000011fc, 0x00000000 },
{ 0x0000123c, 0x00000000 },
{ 0x0000127c, 0x00000000 },
{ 0x000012bc, 0x00000000 },
{ 0x000012fc, 0x00000000 },
{ 0x0000133c, 0x00000000 },
{ 0x0000137c, 0x00000000 },
{ 0x000013bc, 0x00000000 },
{ 0x000013fc, 0x00000000 },
{ 0x0000143c, 0x00000000 },
{ 0x0000147c, 0x00000000 },
{ 0x00004030, 0x00000002 },
{ 0x0000403c, 0x00000002 },
{ 0x00007010, 0x00000000 },
{ 0x00007038, 0x000004c2 },
{ 0x00008004, 0x00000000 },
{ 0x00008008, 0x00000000 },
{ 0x0000800c, 0x00000000 },
{ 0x00008018, 0x00000700 },
{ 0x00008020, 0x00000000 },
{ 0x00008038, 0x00000000 },
{ 0x0000803c, 0x00000000 },
{ 0x00008048, 0x40000000 },
{ 0x00008054, 0x00000000 },
{ 0x00008058, 0x00000000 },
{ 0x0000805c, 0x000fc78f },
{ 0x00008060, 0x0000000f },
{ 0x00008064, 0x00000000 },
{ 0x000080c0, 0x2a82301a },
{ 0x000080c4, 0x05dc01e0 },
{ 0x000080c8, 0x1f402710 },
{ 0x000080cc, 0x01f40000 },
{ 0x000080d0, 0x00001e00 },
{ 0x000080d4, 0x00000000 },
{ 0x000080d8, 0x00400000 },
{ 0x000080e0, 0xffffffff },
{ 0x000080e4, 0x0000ffff },
{ 0x000080e8, 0x003f3f3f },
{ 0x000080ec, 0x00000000 },
{ 0x000080f0, 0x00000000 },
{ 0x000080f4, 0x00000000 },
{ 0x000080f8, 0x00000000 },
{ 0x000080fc, 0x00020000 },
{ 0x00008100, 0x00020000 },
{ 0x00008104, 0x00000001 },
{ 0x00008108, 0x00000052 },
{ 0x0000810c, 0x00000000 },
{ 0x00008110, 0x00000168 },
{ 0x00008118, 0x000100aa },
{ 0x0000811c, 0x00003210 },
{ 0x00008124, 0x00000000 },
{ 0x00008128, 0x00000000 },
{ 0x0000812c, 0x00000000 },
{ 0x00008130, 0x00000000 },
{ 0x00008134, 0x00000000 },
{ 0x00008138, 0x00000000 },
{ 0x0000813c, 0x00000000 },
{ 0x00008144, 0xffffffff },
{ 0x00008168, 0x00000000 },
{ 0x0000816c, 0x00000000 },
{ 0x00008170, 0x32143320 },
{ 0x00008174, 0xfaa4fa50 },
{ 0x00008178, 0x00000100 },
{ 0x0000817c, 0x00000000 },
{ 0x000081c4, 0x00000000 },
{ 0x000081ec, 0x00000000 },
{ 0x000081f0, 0x00000000 },
{ 0x000081f4, 0x00000000 },
{ 0x000081f8, 0x00000000 },
{ 0x000081fc, 0x00000000 },
{ 0x00008200, 0x00000000 },
{ 0x00008204, 0x00000000 },
{ 0x00008208, 0x00000000 },
{ 0x0000820c, 0x00000000 },
{ 0x00008210, 0x00000000 },
{ 0x00008214, 0x00000000 },
{ 0x00008218, 0x00000000 },
{ 0x0000821c, 0x00000000 },
{ 0x00008220, 0x00000000 },
{ 0x00008224, 0x00000000 },
{ 0x00008228, 0x00000000 },
{ 0x0000822c, 0x00000000 },
{ 0x00008230, 0x00000000 },
{ 0x00008234, 0x00000000 },
{ 0x00008238, 0x00000000 },
{ 0x0000823c, 0x00000000 },
{ 0x00008240, 0x00100000 },
{ 0x00008244, 0x0010f400 },
{ 0x00008248, 0x00000100 },
{ 0x0000824c, 0x0001e800 },
{ 0x00008250, 0x00000000 },
{ 0x00008254, 0x00000000 },
{ 0x00008258, 0x00000000 },
{ 0x0000825c, 0x400000ff },
{ 0x00008260, 0x00080922 },
{ 0x00008264, 0xa8000010 },
{ 0x00008270, 0x00000000 },
{ 0x00008274, 0x40000000 },
{ 0x00008278, 0x003e4180 },
{ 0x0000827c, 0x00000000 },
{ 0x00008284, 0x0000002c },
{ 0x00008288, 0x0000002c },
{ 0x0000828c, 0x00000000 },
{ 0x00008294, 0x00000000 },
{ 0x00008298, 0x00000000 },
{ 0x00008300, 0x00000000 },
{ 0x00008304, 0x00000000 },
{ 0x00008308, 0x00000000 },
{ 0x0000830c, 0x00000000 },
{ 0x00008310, 0x00000000 },
{ 0x00008314, 0x00000000 },
{ 0x00008318, 0x00000000 },
{ 0x00008328, 0x00000000 },
{ 0x0000832c, 0x00000007 },
{ 0x00008330, 0x00000302 },
{ 0x00008334, 0x00000e00 },
{ 0x00008338, 0x00070000 },
{ 0x0000833c, 0x00000000 },
{ 0x00008340, 0x000107ff },
{ 0x00009808, 0x00000000 },
{ 0x0000980c, 0xad848e19 },
{ 0x00009810, 0x7d14e000 },
{ 0x00009814, 0x9c0a9f6b },
{ 0x0000981c, 0x00000000 },
{ 0x0000982c, 0x0000a000 },
{ 0x00009830, 0x00000000 },
{ 0x0000983c, 0x00200400 },
{ 0x00009840, 0x206a002e },
{ 0x0000984c, 0x1284233c },
{ 0x00009854, 0x00000859 },
{ 0x00009900, 0x00000000 },
{ 0x00009904, 0x00000000 },
{ 0x00009908, 0x00000000 },
{ 0x0000990c, 0x00000000 },
{ 0x0000991c, 0x10000fff },
{ 0x00009920, 0x05100000 },
{ 0x0000a920, 0x05100000 },
{ 0x0000b920, 0x05100000 },
{ 0x00009928, 0x00000001 },
{ 0x0000992c, 0x00000004 },
{ 0x00009934, 0x1e1f2022 },
{ 0x00009938, 0x0a0b0c0d },
{ 0x0000993c, 0x00000000 },
{ 0x00009948, 0x9280b212 },
{ 0x0000994c, 0x00020028 },
{ 0x00009954, 0x5d50e188 },
{ 0x00009958, 0x00081fff },
{ 0x0000c95c, 0x004b6a8e },
{ 0x0000c968, 0x000003ce },
{ 0x00009970, 0x190fb515 },
{ 0x00009974, 0x00000000 },
{ 0x00009978, 0x00000001 },
{ 0x0000997c, 0x00000000 },
{ 0x00009980, 0x00000000 },
{ 0x00009984, 0x00000000 },
{ 0x00009988, 0x00000000 },
{ 0x0000998c, 0x00000000 },
{ 0x00009990, 0x00000000 },
{ 0x00009994, 0x00000000 },
{ 0x00009998, 0x00000000 },
{ 0x0000999c, 0x00000000 },
{ 0x000099a0, 0x00000000 },
{ 0x000099a4, 0x00000001 },
{ 0x000099a8, 0x001fff00 },
{ 0x000099ac, 0x00000000 },
{ 0x000099b0, 0x03051000 },
{ 0x000099dc, 0x00000000 },
{ 0x000099e0, 0x00000200 },
{ 0x000099e4, 0xaaaaaaaa },
{ 0x000099e8, 0x3c466478 },
{ 0x000099ec, 0x000000aa },
{ 0x000099fc, 0x00001042 },
{ 0x00009b00, 0x00000000 },
{ 0x00009b04, 0x00000001 },
{ 0x00009b08, 0x00000002 },
{ 0x00009b0c, 0x00000003 },
{ 0x00009b10, 0x00000004 },
{ 0x00009b14, 0x00000005 },
{ 0x00009b18, 0x00000008 },
{ 0x00009b1c, 0x00000009 },
{ 0x00009b20, 0x0000000a },
{ 0x00009b24, 0x0000000b },
{ 0x00009b28, 0x0000000c },
{ 0x00009b2c, 0x0000000d },
{ 0x00009b30, 0x00000010 },
{ 0x00009b34, 0x00000011 },
{ 0x00009b38, 0x00000012 },
{ 0x00009b3c, 0x00000013 },
{ 0x00009b40, 0x00000014 },
{ 0x00009b44, 0x00000015 },
{ 0x00009b48, 0x00000018 },
{ 0x00009b4c, 0x00000019 },
{ 0x00009b50, 0x0000001a },
{ 0x00009b54, 0x0000001b },
{ 0x00009b58, 0x0000001c },
{ 0x00009b5c, 0x0000001d },
{ 0x00009b60, 0x00000020 },
{ 0x00009b64, 0x00000021 },
{ 0x00009b68, 0x00000022 },
{ 0x00009b6c, 0x00000023 },
{ 0x00009b70, 0x00000024 },
{ 0x00009b74, 0x00000025 },
{ 0x00009b78, 0x00000028 },
{ 0x00009b7c, 0x00000029 },
{ 0x00009b80, 0x0000002a },
{ 0x00009b84, 0x0000002b },
{ 0x00009b88, 0x0000002c },
{ 0x00009b8c, 0x0000002d },
{ 0x00009b90, 0x00000030 },
{ 0x00009b94, 0x00000031 },
{ 0x00009b98, 0x00000032 },
{ 0x00009b9c, 0x00000033 },
{ 0x00009ba0, 0x00000034 },
{ 0x00009ba4, 0x00000035 },
{ 0x00009ba8, 0x00000035 },
{ 0x00009bac, 0x00000035 },
{ 0x00009bb0, 0x00000035 },
{ 0x00009bb4, 0x00000035 },
{ 0x00009bb8, 0x00000035 },
{ 0x00009bbc, 0x00000035 },
{ 0x00009bc0, 0x00000035 },
{ 0x00009bc4, 0x00000035 },
{ 0x00009bc8, 0x00000035 },
{ 0x00009bcc, 0x00000035 },
{ 0x00009bd0, 0x00000035 },
{ 0x00009bd4, 0x00000035 },
{ 0x00009bd8, 0x00000035 },
{ 0x00009bdc, 0x00000035 },
{ 0x00009be0, 0x00000035 },
{ 0x00009be4, 0x00000035 },
{ 0x00009be8, 0x00000035 },
{ 0x00009bec, 0x00000035 },
{ 0x00009bf0, 0x00000035 },
{ 0x00009bf4, 0x00000035 },
{ 0x00009bf8, 0x00000010 },
{ 0x00009bfc, 0x0000001a },
{ 0x0000a210, 0x40806333 },
{ 0x0000a214, 0x00106c10 },
{ 0x0000a218, 0x009c4060 },
{ 0x0000a220, 0x018830c6 },
{ 0x0000a224, 0x00000400 },
{ 0x0000a228, 0x00000bb5 },
{ 0x0000a22c, 0x00000011 },
{ 0x0000a234, 0x20202020 },
{ 0x0000a238, 0x20202020 },
{ 0x0000a23c, 0x13c889af },
{ 0x0000a240, 0x38490a20 },
{ 0x0000a244, 0x00007bb6 },
{ 0x0000a248, 0x0fff3ffc },
{ 0x0000a24c, 0x00000001 },
{ 0x0000a250, 0x0000a000 },
{ 0x0000a254, 0x00000000 },
{ 0x0000a258, 0x0cc75380 },
{ 0x0000a25c, 0x0f0f0f01 },
{ 0x0000a260, 0xdfa91f01 },
{ 0x0000a268, 0x00000000 },
{ 0x0000a26c, 0x0e79e5c6 },
{ 0x0000b26c, 0x0e79e5c6 },
{ 0x0000c26c, 0x0e79e5c6 },
{ 0x0000d270, 0x00820820 },
{ 0x0000a278, 0x1ce739ce },
{ 0x0000a27c, 0x051701ce },
{ 0x0000a338, 0x00000000 },
{ 0x0000a33c, 0x00000000 },
{ 0x0000a340, 0x00000000 },
{ 0x0000a344, 0x00000000 },
{ 0x0000a348, 0x3fffffff },
{ 0x0000a34c, 0x3fffffff },
{ 0x0000a350, 0x3fffffff },
{ 0x0000a354, 0x0003ffff },
{ 0x0000a358, 0x79a8aa1f },
{ 0x0000d35c, 0x07ffffef },
{ 0x0000d360, 0x0fffffe7 },
{ 0x0000d364, 0x17ffffe5 },
{ 0x0000d368, 0x1fffffe4 },
{ 0x0000d36c, 0x37ffffe3 },
{ 0x0000d370, 0x3fffffe3 },
{ 0x0000d374, 0x57ffffe3 },
{ 0x0000d378, 0x5fffffe2 },
{ 0x0000d37c, 0x7fffffe2 },
{ 0x0000d380, 0x7f3c7bba },
{ 0x0000d384, 0xf3307ff0 },
{ 0x0000a388, 0x08000000 },
{ 0x0000a38c, 0x20202020 },
{ 0x0000a390, 0x20202020 },
{ 0x0000a394, 0x1ce739ce },
{ 0x0000a398, 0x000001ce },
{ 0x0000a39c, 0x00000001 },
{ 0x0000a3a0, 0x00000000 },
{ 0x0000a3a4, 0x00000000 },
{ 0x0000a3a8, 0x00000000 },
{ 0x0000a3ac, 0x00000000 },
{ 0x0000a3b0, 0x00000000 },
{ 0x0000a3b4, 0x00000000 },
{ 0x0000a3b8, 0x00000000 },
{ 0x0000a3bc, 0x00000000 },
{ 0x0000a3c0, 0x00000000 },
{ 0x0000a3c4, 0x00000000 },
{ 0x0000a3c8, 0x00000246 },
{ 0x0000a3cc, 0x20202020 },
{ 0x0000a3d0, 0x20202020 },
{ 0x0000a3d4, 0x20202020 },
{ 0x0000a3dc, 0x1ce739ce },
{ 0x0000a3e0, 0x000001ce },
};
static const u32 ar5416Bank0[][2] = {
{ 0x000098b0, 0x1e5795e5 },
{ 0x000098e0, 0x02008020 },
};
static const u32 ar5416BB_RfGain[][3] = {
{ 0x00009a00, 0x00000000, 0x00000000 },
{ 0x00009a04, 0x00000040, 0x00000040 },
{ 0x00009a08, 0x00000080, 0x00000080 },
{ 0x00009a0c, 0x000001a1, 0x00000141 },
{ 0x00009a10, 0x000001e1, 0x00000181 },
{ 0x00009a14, 0x00000021, 0x000001c1 },
{ 0x00009a18, 0x00000061, 0x00000001 },
{ 0x00009a1c, 0x00000168, 0x00000041 },
{ 0x00009a20, 0x000001a8, 0x000001a8 },
{ 0x00009a24, 0x000001e8, 0x000001e8 },
{ 0x00009a28, 0x00000028, 0x00000028 },
{ 0x00009a2c, 0x00000068, 0x00000068 },
{ 0x00009a30, 0x00000189, 0x000000a8 },
{ 0x00009a34, 0x000001c9, 0x00000169 },
{ 0x00009a38, 0x00000009, 0x000001a9 },
{ 0x00009a3c, 0x00000049, 0x000001e9 },
{ 0x00009a40, 0x00000089, 0x00000029 },
{ 0x00009a44, 0x00000170, 0x00000069 },
{ 0x00009a48, 0x000001b0, 0x00000190 },
{ 0x00009a4c, 0x000001f0, 0x000001d0 },
{ 0x00009a50, 0x00000030, 0x00000010 },
{ 0x00009a54, 0x00000070, 0x00000050 },
{ 0x00009a58, 0x00000191, 0x00000090 },
{ 0x00009a5c, 0x000001d1, 0x00000151 },
{ 0x00009a60, 0x00000011, 0x00000191 },
{ 0x00009a64, 0x00000051, 0x000001d1 },
{ 0x00009a68, 0x00000091, 0x00000011 },
{ 0x00009a6c, 0x000001b8, 0x00000051 },
{ 0x00009a70, 0x000001f8, 0x00000198 },
{ 0x00009a74, 0x00000038, 0x000001d8 },
{ 0x00009a78, 0x00000078, 0x00000018 },
{ 0x00009a7c, 0x00000199, 0x00000058 },
{ 0x00009a80, 0x000001d9, 0x00000098 },
{ 0x00009a84, 0x00000019, 0x00000159 },
{ 0x00009a88, 0x00000059, 0x00000199 },
{ 0x00009a8c, 0x00000099, 0x000001d9 },
{ 0x00009a90, 0x000000d9, 0x00000019 },
{ 0x00009a94, 0x000000f9, 0x00000059 },
{ 0x00009a98, 0x000000f9, 0x00000099 },
{ 0x00009a9c, 0x000000f9, 0x000000d9 },
{ 0x00009aa0, 0x000000f9, 0x000000f9 },
{ 0x00009aa4, 0x000000f9, 0x000000f9 },
{ 0x00009aa8, 0x000000f9, 0x000000f9 },
{ 0x00009aac, 0x000000f9, 0x000000f9 },
{ 0x00009ab0, 0x000000f9, 0x000000f9 },
{ 0x00009ab4, 0x000000f9, 0x000000f9 },
{ 0x00009ab8, 0x000000f9, 0x000000f9 },
{ 0x00009abc, 0x000000f9, 0x000000f9 },
{ 0x00009ac0, 0x000000f9, 0x000000f9 },
{ 0x00009ac4, 0x000000f9, 0x000000f9 },
{ 0x00009ac8, 0x000000f9, 0x000000f9 },
{ 0x00009acc, 0x000000f9, 0x000000f9 },
{ 0x00009ad0, 0x000000f9, 0x000000f9 },
{ 0x00009ad4, 0x000000f9, 0x000000f9 },
{ 0x00009ad8, 0x000000f9, 0x000000f9 },
{ 0x00009adc, 0x000000f9, 0x000000f9 },
{ 0x00009ae0, 0x000000f9, 0x000000f9 },
{ 0x00009ae4, 0x000000f9, 0x000000f9 },
{ 0x00009ae8, 0x000000f9, 0x000000f9 },
{ 0x00009aec, 0x000000f9, 0x000000f9 },
{ 0x00009af0, 0x000000f9, 0x000000f9 },
{ 0x00009af4, 0x000000f9, 0x000000f9 },
{ 0x00009af8, 0x000000f9, 0x000000f9 },
{ 0x00009afc, 0x000000f9, 0x000000f9 },
};
static const u32 ar5416Bank1[][2] = {
{ 0x000098b0, 0x02108421 },
{ 0x000098ec, 0x00000008 },
};
static const u32 ar5416Bank2[][2] = {
{ 0x000098b0, 0x0e73ff17 },
{ 0x000098e0, 0x00000420 },
};
static const u32 ar5416Bank3[][3] = {
{ 0x000098f0, 0x01400018, 0x01c00018 },
};
static const u32 ar5416Bank6[][3] = {
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00e00000, 0x00e00000 },
{ 0x0000989c, 0x005e0000, 0x005e0000 },
{ 0x0000989c, 0x00120000, 0x00120000 },
{ 0x0000989c, 0x00620000, 0x00620000 },
{ 0x0000989c, 0x00020000, 0x00020000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x40ff0000, 0x40ff0000 },
{ 0x0000989c, 0x005f0000, 0x005f0000 },
{ 0x0000989c, 0x00870000, 0x00870000 },
{ 0x0000989c, 0x00f90000, 0x00f90000 },
{ 0x0000989c, 0x007b0000, 0x007b0000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x00f50000, 0x00f50000 },
{ 0x0000989c, 0x00dc0000, 0x00dc0000 },
{ 0x0000989c, 0x00110000, 0x00110000 },
{ 0x0000989c, 0x006100a8, 0x006100a8 },
{ 0x0000989c, 0x004210a2, 0x004210a2 },
{ 0x0000989c, 0x0014008f, 0x0014008f },
{ 0x0000989c, 0x00c40003, 0x00c40003 },
{ 0x0000989c, 0x003000f2, 0x003000f2 },
{ 0x0000989c, 0x00440016, 0x00440016 },
{ 0x0000989c, 0x00410040, 0x00410040 },
{ 0x0000989c, 0x0001805e, 0x0001805e },
{ 0x0000989c, 0x0000c0ab, 0x0000c0ab },
{ 0x0000989c, 0x000000f1, 0x000000f1 },
{ 0x0000989c, 0x00002081, 0x00002081 },
{ 0x0000989c, 0x000000d4, 0x000000d4 },
{ 0x000098d0, 0x0000000f, 0x0010000f },
};
static const u32 ar5416Bank6TPC[][3] = {
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00e00000, 0x00e00000 },
{ 0x0000989c, 0x005e0000, 0x005e0000 },
{ 0x0000989c, 0x00120000, 0x00120000 },
{ 0x0000989c, 0x00620000, 0x00620000 },
{ 0x0000989c, 0x00020000, 0x00020000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x40ff0000, 0x40ff0000 },
{ 0x0000989c, 0x005f0000, 0x005f0000 },
{ 0x0000989c, 0x00870000, 0x00870000 },
{ 0x0000989c, 0x00f90000, 0x00f90000 },
{ 0x0000989c, 0x007b0000, 0x007b0000 },
{ 0x0000989c, 0x00ff0000, 0x00ff0000 },
{ 0x0000989c, 0x00f50000, 0x00f50000 },
{ 0x0000989c, 0x00dc0000, 0x00dc0000 },
{ 0x0000989c, 0x00110000, 0x00110000 },
{ 0x0000989c, 0x006100a8, 0x006100a8 },
{ 0x0000989c, 0x00423022, 0x00423022 },
{ 0x0000989c, 0x201400df, 0x201400df },
{ 0x0000989c, 0x00c40002, 0x00c40002 },
{ 0x0000989c, 0x003000f2, 0x003000f2 },
{ 0x0000989c, 0x00440016, 0x00440016 },
{ 0x0000989c, 0x00410040, 0x00410040 },
{ 0x0000989c, 0x0001805e, 0x0001805e },
{ 0x0000989c, 0x0000c0ab, 0x0000c0ab },
{ 0x0000989c, 0x000000e1, 0x000000e1 },
{ 0x0000989c, 0x00007081, 0x00007081 },
{ 0x0000989c, 0x000000d4, 0x000000d4 },
{ 0x000098d0, 0x0000000f, 0x0010000f },
};
static const u32 ar5416Bank7[][2] = {
{ 0x0000989c, 0x00000500 },
{ 0x0000989c, 0x00000800 },
{ 0x000098cc, 0x0000000e },
};
static const u32 ar5416Addac[][2] = {
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000003 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x0000000c },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000030 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000060 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000058 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
{0x000098cc, 0x00000000 },
};
static const u32 ar5416Modes_9100[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
{ 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
{ 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
{ 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
{ 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf },
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
{ 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
{ 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
{ 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e },
{ 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
{ 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
{ 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
{ 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
{ 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
{ 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
{ 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d },
{ 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 },
{ 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
{ 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e },
{ 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff },
#ifdef TB243
{ 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
{ 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
{ 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 },
{ 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 },
#else
{ 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
{ 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
{ 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 },
{ 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
#endif
{ 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 },
{ 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
{ 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
{ 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 },
{ 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 },
{ 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
{ 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
{ 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 },
{ 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
{ 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
{ 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa },
{ 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 },
{ 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 },
{ 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 },
{ 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b },
{ 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b },
{ 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a },
{ 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf },
{ 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f },
{ 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f },
{ 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f },
{ 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
};
#endif /* INITVALS_AR5008_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,593 @@
/*
* Copyright (c) 2008-2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "hw.h"
#include "ar5008_initvals.h"
#include "ar9001_initvals.h"
#include "ar9002_initvals.h"
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
static bool ar9002_hw_macversion_supported(u32 macversion)
{
switch (macversion) {
case AR_SREV_VERSION_5416_PCI:
case AR_SREV_VERSION_5416_PCIE:
case AR_SREV_VERSION_9160:
case AR_SREV_VERSION_9100:
case AR_SREV_VERSION_9280:
case AR_SREV_VERSION_9285:
case AR_SREV_VERSION_9287:
case AR_SREV_VERSION_9271:
return true;
default:
break;
}
return false;
}
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
{
if (AR_SREV_9271(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
ARRAY_SIZE(ar9271Modes_9271), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniCommon_normal_cck_fir_coeff_9271,
ar9271Common_normal_cck_fir_coeff_9271,
ARRAY_SIZE(ar9271Common_normal_cck_fir_coeff_9271), 2);
INIT_INI_ARRAY(&ah->iniCommon_japan_2484_cck_fir_coeff_9271,
ar9271Common_japan_2484_cck_fir_coeff_9271,
ARRAY_SIZE(ar9271Common_japan_2484_cck_fir_coeff_9271), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
ar9271Modes_9271_1_0_only,
ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 6);
INIT_INI_ARRAY(&ah->iniModes_high_power_tx_gain_9271,
ar9271Modes_high_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 6);
INIT_INI_ARRAY(&ah->iniModes_normal_power_tx_gain_9271,
ar9271Modes_normal_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 6);
return;
}
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
ARRAY_SIZE(ar9287Modes_9287_1_1), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
ARRAY_SIZE(ar9287Common_9287_1_1), 2);
if (ah->config.pcie_clock_req)
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_off_L1_9287_1_1,
ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2);
else
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_always_on_L1_9287_1_1,
ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1),
2);
} else if (AR_SREV_9287_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0,
ARRAY_SIZE(ar9287Modes_9287_1_0), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0,
ARRAY_SIZE(ar9287Common_9287_1_0), 2);
if (ah->config.pcie_clock_req)
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_off_L1_9287_1_0,
ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2);
else
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9287PciePhy_clkreq_always_on_L1_9287_1_0,
ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0),
2);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
ARRAY_SIZE(ar9285Common_9285_1_2), 2);
if (ah->config.pcie_clock_req) {
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9285PciePhy_clkreq_off_L1_9285_1_2,
ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
} else {
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
2);
}
} else if (AR_SREV_9285_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285,
ARRAY_SIZE(ar9285Modes_9285), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285,
ARRAY_SIZE(ar9285Common_9285), 2);
if (ah->config.pcie_clock_req) {
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9285PciePhy_clkreq_off_L1_9285,
ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
} else {
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9285PciePhy_clkreq_always_on_L1_9285,
ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
}
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
ARRAY_SIZE(ar9280Modes_9280_2), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
ARRAY_SIZE(ar9280Common_9280_2), 2);
if (ah->config.pcie_clock_req) {
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9280PciePhy_clkreq_off_L1_9280,
ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2);
} else {
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9280PciePhy_clkreq_always_on_L1_9280,
ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
}
INIT_INI_ARRAY(&ah->iniModesAdditional,
ar9280Modes_fast_clock_9280_2,
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
} else if (AR_SREV_9280_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280,
ARRAY_SIZE(ar9280Modes_9280), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280,
ARRAY_SIZE(ar9280Common_9280), 2);
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
ARRAY_SIZE(ar5416Modes_9160), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
ARRAY_SIZE(ar5416Common_9160), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160,
ARRAY_SIZE(ar5416Bank0_9160), 2);
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160,
ARRAY_SIZE(ar5416BB_RfGain_9160), 3);
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160,
ARRAY_SIZE(ar5416Bank1_9160), 2);
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160,
ARRAY_SIZE(ar5416Bank2_9160), 2);
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160,
ARRAY_SIZE(ar5416Bank3_9160), 3);
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160,
ARRAY_SIZE(ar5416Bank6_9160), 3);
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160,
ARRAY_SIZE(ar5416Bank6TPC_9160), 3);
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160,
ARRAY_SIZE(ar5416Bank7_9160), 2);
if (AR_SREV_9160_11(ah)) {
INIT_INI_ARRAY(&ah->iniAddac,
ar5416Addac_91601_1,
ARRAY_SIZE(ar5416Addac_91601_1), 2);
} else {
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
ARRAY_SIZE(ar5416Addac_9160), 2);
}
} else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
ARRAY_SIZE(ar5416Modes_9100), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
ARRAY_SIZE(ar5416Common_9100), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100,
ARRAY_SIZE(ar5416Bank0_9100), 2);
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100,
ARRAY_SIZE(ar5416BB_RfGain_9100), 3);
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100,
ARRAY_SIZE(ar5416Bank1_9100), 2);
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100,
ARRAY_SIZE(ar5416Bank2_9100), 2);
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100,
ARRAY_SIZE(ar5416Bank3_9100), 3);
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
ARRAY_SIZE(ar5416Bank6_9100), 3);
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100,
ARRAY_SIZE(ar5416Bank7_9100), 2);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
ARRAY_SIZE(ar5416Addac_9100), 2);
} else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
ARRAY_SIZE(ar5416Modes), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
ARRAY_SIZE(ar5416Common), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
ARRAY_SIZE(ar5416Bank0), 2);
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
ARRAY_SIZE(ar5416BB_RfGain), 3);
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
ARRAY_SIZE(ar5416Bank1), 2);
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
ARRAY_SIZE(ar5416Bank2), 2);
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
ARRAY_SIZE(ar5416Bank3), 3);
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
ARRAY_SIZE(ar5416Bank6), 3);
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
ARRAY_SIZE(ar5416Bank6TPC), 3);
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
ARRAY_SIZE(ar5416Bank7), 2);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
ARRAY_SIZE(ar5416Addac), 2);
}
}
/* Support for Japan ch.14 (2484) spread */
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah)
{
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniCckfirNormal,
ar9287Common_normal_cck_fir_coeff_92871_1,
ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_92871_1),
2);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
ar9287Common_japan_2484_cck_fir_coeff_92871_1,
ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_92871_1),
2);
}
}
static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
{
u32 rxgain_type;
if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
AR5416_EEP_MINOR_VER_17) {
rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE);
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_13db_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_23db_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
} else {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
}
}
static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah)
{
u32 txgain_type;
if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >=
AR5416_EEP_MINOR_VER_19) {
txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
}
}
static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
{
if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6);
else if (AR_SREV_9287_10(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_0,
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6);
else if (AR_SREV_9280_20(ah))
ar9280_20_hw_init_rxgain_ini(ah);
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6);
} else if (AR_SREV_9287_10(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_0,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6);
} else if (AR_SREV_9280_20(ah)) {
ar9280_20_hw_init_txgain_ini(ah);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE);
/* txgain table */
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_high_power,
ARRAY_SIZE(
ar9285Modes_XE2_0_high_power), 6);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_high_power_tx_gain_9285_1_2,
ARRAY_SIZE(
ar9285Modes_high_power_tx_gain_9285_1_2), 6);
}
} else {
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_normal_power,
ARRAY_SIZE(
ar9285Modes_XE2_0_normal_power), 6);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_original_tx_gain_9285_1_2,
ARRAY_SIZE(
ar9285Modes_original_tx_gain_9285_1_2), 6);
}
}
}
}
/*
* Helper for ASPM support.
*
* Disable PLL when in L0s as well as receiver clock when in L1.
* This power saving option must be enabled through the SerDes.
*
* Programming the SerDes must go through the same 288 bit serial shift
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
int restore,
int power_off)
{
u8 i;
u32 val;
if (ah->is_pciexpress != true)
return;
/* Do not touch SerDes registers */
if (ah->config.pcie_powersave_enable == 2)
return;
/* Nothing to do on restore for 11N */
if (!restore) {
if (AR_SREV_9280_20_OR_LATER(ah)) {
/*
* AR9280 2.0 or later chips use SerDes values from the
* initvals.h initialized depending on chipset during
* __ath9k_hw_init()
*/
for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) {
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0),
INI_RA(&ah->iniPcieSerdes, i, 1));
}
} else if (AR_SREV_9280(ah) &&
(ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) {
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
/* RX shut off when elecidle is asserted */
REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
/* Shut off CLKREQ active in L1 */
if (ah->config.pcie_clock_req)
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
else
REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
/* Load the new settings */
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
} else {
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
/* RX shut off when elecidle is asserted */
REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
/*
* Ignore ah->ah_config.pcie_clock_req setting for
* pre-AR9280 11n
*/
REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
/* Load the new settings */
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
}
udelay(1000);
/* set bit 19 to allow forcing of pcie core into L1 state */
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
/* Several PCIe massages to ensure proper behaviour */
if (ah->config.pcie_waen) {
val = ah->config.pcie_waen;
if (!power_off)
val &= (~AR_WA_D3_L1_DISABLE);
} else {
if (AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
AR_SREV_9287(ah)) {
val = AR9285_WA_DEFAULT;
if (!power_off)
val &= (~AR_WA_D3_L1_DISABLE);
} else if (AR_SREV_9280(ah)) {
/*
* On AR9280 chips bit 22 of 0x4004 needs to be
* set otherwise card may disappear.
*/
val = AR9280_WA_DEFAULT;
if (!power_off)
val &= (~AR_WA_D3_L1_DISABLE);
} else
val = AR_WA_DEFAULT;
}
REG_WRITE(ah, AR_WA, val);
}
if (power_off) {
/*
* Set PCIe workaround bits
* bit 14 in WA register (disable L1) should only
* be set when device enters D3 and be cleared
* when device comes back to D0.
*/
if (ah->config.pcie_waen) {
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
} else {
if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) ||
AR_SREV_9287(ah)) &&
(AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) ||
(AR_SREV_9280(ah) &&
(AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) {
REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE);
}
}
}
}
static int ar9002_hw_get_radiorev(struct ath_hw *ah)
{
u32 val;
int i;
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
for (i = 0; i < 8; i++)
REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
return ath9k_hw_reverse_bits(val, 8);
}
int ar9002_hw_rf_claim(struct ath_hw *ah)
{
u32 val;
REG_WRITE(ah, AR_PHY(0), 0x00000007);
val = ar9002_hw_get_radiorev(ah);
switch (val & AR_RADIO_SREV_MAJOR) {
case 0:
val = AR_RAD5133_SREV_MAJOR;
break;
case AR_RAD5133_SREV_MAJOR:
case AR_RAD5122_SREV_MAJOR:
case AR_RAD2133_SREV_MAJOR:
case AR_RAD2122_SREV_MAJOR:
break;
default:
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
"Radio Chip Rev 0x%02X not supported\n",
val & AR_RADIO_SREV_MAJOR);
return -EOPNOTSUPP;
}
ah->hw_version.analog5GhzRev = val;
return 0;
}
/*
* Enable ASYNC FIFO
*
* If Async FIFO is enabled, the following counters change as MAC now runs
* at 117 Mhz instead of 88/44MHz when async FIFO is disabled.
*
* The values below tested for ht40 2 chain.
* Overwrite the delay/timeouts initialized in process ini.
*/
void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
{
if (AR_SREV_9287_12_OR_LATER(ah)) {
REG_WRITE(ah, AR_D_GBL_IFS_SIFS,
AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_D_GBL_IFS_SLOT,
AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_D_GBL_IFS_EIFS,
AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR);
REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR);
REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER,
AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768);
REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN,
AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL);
}
}
/*
* We don't enable WEP aggregation on mac80211 but we keep this
* around for HAL unification purposes.
*/
void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah)
{
if (AR_SREV_9287_12_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
AR_PCU_MISC_MODE2_ENABLE_AGGWEP);
}
}
/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
void ar9002_hw_attach_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
priv_ops->macversion_supported = ar9002_hw_macversion_supported;
ops->config_pci_powersave = ar9002_hw_configpcipowersave;
ar5008_hw_attach_phy_ops(ah);
if (AR_SREV_9280_10_OR_LATER(ah))
ar9002_hw_attach_phy_ops(ah);
ar9002_hw_attach_calib_ops(ah);
ar9002_hw_attach_mac_ops(ah);
}

View File

@ -0,0 +1,480 @@
/*
* Copyright (c) 2008-2009 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "hw.h"
#define AR_BufLen 0x00000fff
static void ar9002_hw_rx_enable(struct ath_hw *ah)
{
REG_WRITE(ah, AR_CR, AR_CR_RXE);
}
static void ar9002_hw_set_desc_link(void *ds, u32 ds_link)
{
((struct ath_desc*) ds)->ds_link = ds_link;
}
static void ar9002_hw_get_desc_link(void *ds, u32 **ds_link)
{
*ds_link = &((struct ath_desc *)ds)->ds_link;
}
static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
u32 mask2 = 0;
struct ath9k_hw_capabilities *pCap = &ah->caps;
u32 sync_cause = 0;
bool fatal_int = false;
struct ath_common *common = ath9k_hw_common(ah);
if (!AR_SREV_9100(ah)) {
if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
== AR_RTC_STATUS_ON) {
isr = REG_READ(ah, AR_ISR);
}
}
sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
AR_INTR_SYNC_DEFAULT;
*masked = 0;
if (!isr && !sync_cause)
return false;
} else {
*masked = 0;
isr = REG_READ(ah, AR_ISR);
}
if (isr) {
if (isr & AR_ISR_BCNMISC) {
u32 isr2;
isr2 = REG_READ(ah, AR_ISR_S2);
if (isr2 & AR_ISR_S2_TIM)
mask2 |= ATH9K_INT_TIM;
if (isr2 & AR_ISR_S2_DTIM)
mask2 |= ATH9K_INT_DTIM;
if (isr2 & AR_ISR_S2_DTIMSYNC)
mask2 |= ATH9K_INT_DTIMSYNC;
if (isr2 & (AR_ISR_S2_CABEND))
mask2 |= ATH9K_INT_CABEND;
if (isr2 & AR_ISR_S2_GTT)
mask2 |= ATH9K_INT_GTT;
if (isr2 & AR_ISR_S2_CST)
mask2 |= ATH9K_INT_CST;
if (isr2 & AR_ISR_S2_TSFOOR)
mask2 |= ATH9K_INT_TSFOOR;
}
isr = REG_READ(ah, AR_ISR_RAC);
if (isr == 0xffffffff) {
*masked = 0;
return false;
}
*masked = isr & ATH9K_INT_COMMON;
if (ah->config.rx_intr_mitigation) {
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
*masked |= ATH9K_INT_RX;
}
if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
*masked |= ATH9K_INT_RX;
if (isr &
(AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
AR_ISR_TXEOL)) {
u32 s0_s, s1_s;
*masked |= ATH9K_INT_TX;
s0_s = REG_READ(ah, AR_ISR_S0_S);
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK);
ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC);
s1_s = REG_READ(ah, AR_ISR_S1_S);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR);
ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL);
}
if (isr & AR_ISR_RXORN) {
ath_print(common, ATH_DBG_INTERRUPT,
"receive FIFO overrun interrupt\n");
}
if (!AR_SREV_9100(ah)) {
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
if (isr5 & AR_ISR_S5_TIM_TIMER)
*masked |= ATH9K_INT_TIM_TIMER;
}
}
*masked |= mask2;
}
if (AR_SREV_9100(ah))
return true;
if (isr & AR_ISR_GENTMR) {
u32 s5_s;
s5_s = REG_READ(ah, AR_ISR_S5_S);
if (isr & AR_ISR_GENTMR) {
ah->intr_gen_timer_trigger =
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
ah->intr_gen_timer_thresh =
MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
if (ah->intr_gen_timer_trigger)
*masked |= ATH9K_INT_GENTIMER;
}
}
if (sync_cause) {
fatal_int =
(sync_cause &
(AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR))
? true : false;
if (fatal_int) {
if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
ath_print(common, ATH_DBG_ANY,
"received PCI FATAL interrupt\n");
}
if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
ath_print(common, ATH_DBG_ANY,
"received PCI PERR interrupt\n");
}
*masked |= ATH9K_INT_FATAL;
}
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
ath_print(common, ATH_DBG_INTERRUPT,
"AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
REG_WRITE(ah, AR_RC, 0);
*masked |= ATH9K_INT_FATAL;
}
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
ath_print(common, ATH_DBG_INTERRUPT,
"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
}
REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
}
return true;
}
static void ar9002_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
bool is_firstseg, bool is_lastseg,
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_data = buf_addr;
if (is_firstseg) {
ads->ds_ctl1 |= seglen | (is_lastseg ? 0 : AR_TxMore);
} else if (is_lastseg) {
ads->ds_ctl0 = 0;
ads->ds_ctl1 = seglen;
ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
} else {
ads->ds_ctl0 = 0;
ads->ds_ctl1 = seglen | AR_TxMore;
ads->ds_ctl2 = 0;
ads->ds_ctl3 = 0;
}
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
}
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if ((ads->ds_txstatus9 & AR_TxDone) == 0)
return -EINPROGRESS;
ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
ts->ts_tstamp = ads->AR_SendTimestamp;
ts->ts_status = 0;
ts->ts_flags = 0;
if (ads->ds_txstatus1 & AR_FrmXmitOK)
ts->ts_status |= ATH9K_TX_ACKED;
if (ads->ds_txstatus1 & AR_ExcessiveRetries)
ts->ts_status |= ATH9K_TXERR_XRETRY;
if (ads->ds_txstatus1 & AR_Filtered)
ts->ts_status |= ATH9K_TXERR_FILT;
if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
ts->ts_status |= ATH9K_TXERR_FIFO;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus9 & AR_TxOpExceeded)
ts->ts_status |= ATH9K_TXERR_XTXOP;
if (ads->ds_txstatus1 & AR_TxTimerExpired)
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
if (ads->ds_txstatus1 & AR_DescCfgErr)
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus0 & AR_TxBaStatus) {
ts->ts_flags |= ATH9K_TX_BA;
ts->ba_low = ads->AR_BaBitmapLow;
ts->ba_high = ads->AR_BaBitmapHigh;
}
ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
switch (ts->ts_rateindex) {
case 0:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
break;
case 1:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
break;
case 2:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
break;
case 3:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
break;
}
ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
ts->evm0 = ads->AR_TxEVM0;
ts->evm1 = ads->AR_TxEVM1;
ts->evm2 = ads->AR_TxEVM2;
ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
ts->ts_antenna = 0;
return 0;
}
static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u32 keyIx,
enum ath9k_key_type keyType, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
txPower += ah->txpower_indexoffset;
if (txPower > 63)
txPower = 63;
ads->ds_ctl0 = (pktLen & AR_FrameLen)
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txPower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
ads->ds_ctl1 =
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
| SM(type, AR_FrameType)
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
ads->ds_ctl6 = SM(keyType, AR_EncrType);
if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
ads->ds_ctl8 = 0;
ads->ds_ctl9 = 0;
ads->ds_ctl10 = 0;
ads->ds_ctl11 = 0;
}
}
static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
struct ar5416_desc *last_ads = AR5416DESC(lastds);
u32 ds_ctl0;
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
ds_ctl0 = ads->ds_ctl0;
if (flags & ATH9K_TXDESC_RTSENA) {
ds_ctl0 &= ~AR_CTSEnable;
ds_ctl0 |= AR_RTSEnable;
} else {
ds_ctl0 &= ~AR_RTSEnable;
ds_ctl0 |= AR_CTSEnable;
}
ads->ds_ctl0 = ds_ctl0;
} else {
ads->ds_ctl0 =
(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
}
ads->ds_ctl2 = set11nTries(series, 0)
| set11nTries(series, 1)
| set11nTries(series, 2)
| set11nTries(series, 3)
| (durUpdateEn ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ads->ds_ctl3 = set11nRate(series, 0)
| set11nRate(series, 1)
| set11nRate(series, 2)
| set11nRate(series, 3);
ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
| set11nPktDurRTSCTS(series, 1);
ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
| set11nPktDurRTSCTS(series, 3);
ads->ds_ctl7 = set11nRateFlags(series, 0)
| set11nRateFlags(series, 1)
| set11nRateFlags(series, 2)
| set11nRateFlags(series, 3)
| SM(rtsctsRate, AR_RTSCTSRate);
last_ads->ds_ctl2 = ads->ds_ctl2;
last_ads->ds_ctl3 = ads->ds_ctl3;
}
static void ar9002_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
ads->ds_ctl6 &= ~AR_AggrLen;
ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
}
static void ar9002_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
u32 numDelims)
{
struct ar5416_desc *ads = AR5416DESC(ds);
unsigned int ctl6;
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
ctl6 = ads->ds_ctl6;
ctl6 &= ~AR_PadDelim;
ctl6 |= SM(numDelims, AR_PadDelim);
ads->ds_ctl6 = ctl6;
}
static void ar9002_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 |= AR_IsAggr;
ads->ds_ctl1 &= ~AR_MoreAggr;
ads->ds_ctl6 &= ~AR_PadDelim;
}
static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
}
static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
u32 burstDuration)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl2 &= ~AR_BurstDur;
ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
}
static void ar9002_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
u32 vmf)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if (vmf)
ads->ds_ctl0 |= AR_VirtMoreFrag;
else
ads->ds_ctl0 &= ~AR_VirtMoreFrag;
}
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
struct ath9k_hw_capabilities *pCap = &ah->caps;
ads->ds_ctl1 = size & AR_BufLen;
if (flags & ATH9K_RXDESC_INTREQ)
ads->ds_ctl1 |= AR_RxIntrReq;
ads->ds_rxstatus8 &= ~AR_RxDone;
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
memset(&(ads->u), 0, sizeof(ads->u));
}
EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
{
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
ops->rx_enable = ar9002_hw_rx_enable;
ops->set_desc_link = ar9002_hw_set_desc_link;
ops->get_desc_link = ar9002_hw_get_desc_link;
ops->get_isr = ar9002_hw_get_isr;
ops->fill_txdesc = ar9002_hw_fill_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc;
ops->set11n_txdesc = ar9002_hw_set11n_txdesc;
ops->set11n_ratescenario = ar9002_hw_set11n_ratescenario;
ops->set11n_aggr_first = ar9002_hw_set11n_aggr_first;
ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle;
ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last;
ops->clr11n_aggr = ar9002_hw_clr11n_aggr;
ops->set11n_burstduration = ar9002_hw_set11n_burstduration;
ops->set11n_virtualmorefrag = ar9002_hw_set11n_virtualmorefrag;
}

View File

@ -0,0 +1,539 @@
/*
* Copyright (c) 2008-2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: Programming Atheros 802.11n analog front end radios
*
* AR5416 MAC based PCI devices and AR518 MAC based PCI-Express
* devices have either an external AR2133 analog front end radio for single
* band 2.4 GHz communication or an AR5133 analog front end radio for dual
* band 2.4 GHz / 5 GHz communication.
*
* All devices after the AR5416 and AR5418 family starting with the AR9280
* have their analog front radios, MAC/BB and host PCIe/USB interface embedded
* into a single-chip and require less programming.
*
* The following single-chips exist with a respective embedded radio:
*
* AR9280 - 11n dual-band 2x2 MIMO for PCIe
* AR9281 - 11n single-band 1x2 MIMO for PCIe
* AR9285 - 11n single-band 1x1 for PCIe
* AR9287 - 11n single-band 2x2 MIMO for PCIe
*
* AR9220 - 11n dual-band 2x2 MIMO for PCI
* AR9223 - 11n single-band 2x2 MIMO for PCI
*
* AR9287 - 11n single-band 1x1 MIMO for USB
*/
#include "hw.h"
#include "ar9002_phy.h"
/**
* ar9002_hw_set_channel - set channel on single-chip device
* @ah: atheros hardware structure
* @chan:
*
* This is the function to change channel on single-chip devices, that is
* all devices after ar9280.
*
* This function takes the channel value in MHz and sets
* hardware channel value. Assumes writes have been enabled to analog bus.
*
* Actual Expression,
*
* For 2GHz channel,
* Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
* (freq_ref = 40MHz)
*
* For 5GHz channel,
* Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
* (freq_ref = 40MHz/(24>>amodeRefSel))
*/
static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
{
u16 bMode, fracMode, aModeRefSel = 0;
u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
struct chan_centers centers;
u32 refDivA = 24;
ath9k_hw_get_channel_centers(ah, chan, &centers);
freq = centers.synth_center;
reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
reg32 &= 0xc0000000;
if (freq < 4800) { /* 2 GHz, fractional mode */
u32 txctl;
int regWrites = 0;
bMode = 1;
fracMode = 1;
aModeRefSel = 0;
channelSel = CHANSEL_2G(freq);
if (AR_SREV_9287_11_OR_LATER(ah)) {
if (freq == 2484) {
/* Enable channel spreading for channel 14 */
REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
1, regWrites);
} else {
REG_WRITE_ARRAY(&ah->iniCckfirNormal,
1, regWrites);
}
} else {
txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
if (freq == 2484) {
/* Enable channel spreading for channel 14 */
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
} else {
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
}
}
} else {
bMode = 0;
fracMode = 0;
switch (ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
case 0:
if ((freq % 20) == 0)
aModeRefSel = 3;
else if ((freq % 10) == 0)
aModeRefSel = 2;
if (aModeRefSel)
break;
case 1:
default:
aModeRefSel = 0;
/*
* Enable 2G (fractional) mode for channels
* which are 5MHz spaced.
*/
fracMode = 1;
refDivA = 1;
channelSel = CHANSEL_5G(freq);
/* RefDivA setting */
REG_RMW_FIELD(ah, AR_AN_SYNTH9,
AR_AN_SYNTH9_REFDIVA, refDivA);
}
if (!fracMode) {
ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
channelSel = ndiv & 0x1ff;
channelFrac = (ndiv & 0xfffffe00) * 2;
channelSel = (channelSel << 17) | channelFrac;
}
}
reg32 = reg32 |
(bMode << 29) |
(fracMode << 28) | (aModeRefSel << 26) | (channelSel);
REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
ah->curchan = chan;
ah->curchan_rad_index = -1;
return 0;
}
/**
* ar9002_hw_spur_mitigate - convert baseband spur frequency
* @ah: atheros hardware structure
* @chan:
*
* For single-chip solutions. Converts to baseband spur frequency given the
* input channel frequency and compute register settings below.
*/
static void ar9002_hw_spur_mitigate(struct ath_hw *ah,
struct ath9k_channel *chan)
{
int bb_spur = AR_NO_SPUR;
int freq;
int bin, cur_bin;
int bb_spur_off, spur_subchannel_sd;
int spur_freq_sd;
int spur_delta_phase;
int denominator;
int upper, lower, cur_vit_mask;
int tmp, newVal;
int i;
int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
};
int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
};
int inc[4] = { 0, 100, 0, 0 };
struct chan_centers centers;
int8_t mask_m[123];
int8_t mask_p[123];
int8_t mask_amt;
int tmp_mask;
int cur_bb_spur;
bool is2GHz = IS_CHAN_2GHZ(chan);
memset(&mask_m, 0, sizeof(int8_t) * 123);
memset(&mask_p, 0, sizeof(int8_t) * 123);
ath9k_hw_get_channel_centers(ah, chan, &centers);
freq = centers.synth_center;
ah->config.spurmode = SPUR_ENABLE_EEPROM;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
if (is2GHz)
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
else
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
if (AR_NO_SPUR == cur_bb_spur)
break;
cur_bb_spur = cur_bb_spur - freq;
if (IS_CHAN_HT40(chan)) {
if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
bb_spur = cur_bb_spur;
break;
}
} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
bb_spur = cur_bb_spur;
break;
}
}
if (AR_NO_SPUR == bb_spur) {
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
return;
} else {
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
}
bin = bb_spur * 320;
tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
ENABLE_REGWRITE_BUFFER(ah);
newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
if (IS_CHAN_HT40(chan)) {
if (bb_spur < 0) {
spur_subchannel_sd = 1;
bb_spur_off = bb_spur + 10;
} else {
spur_subchannel_sd = 0;
bb_spur_off = bb_spur - 10;
}
} else {
spur_subchannel_sd = 0;
bb_spur_off = bb_spur;
}
if (IS_CHAN_HT40(chan))
spur_delta_phase =
((bb_spur * 262144) /
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
else
spur_delta_phase =
((bb_spur * 524288) /
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
REG_WRITE(ah, AR_PHY_TIMING11, newVal);
newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
cur_bin = -6000;
upper = bin + 100;
lower = bin - 100;
for (i = 0; i < 4; i++) {
int pilot_mask = 0;
int chan_mask = 0;
int bp = 0;
for (bp = 0; bp < 30; bp++) {
if ((cur_bin > lower) && (cur_bin < upper)) {
pilot_mask = pilot_mask | 0x1 << bp;
chan_mask = chan_mask | 0x1 << bp;
}
cur_bin += 100;
}
cur_bin += inc[i];
REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
REG_WRITE(ah, chan_mask_reg[i], chan_mask);
}
cur_vit_mask = 6100;
upper = bin + 120;
lower = bin - 120;
for (i = 0; i < 123; i++) {
if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
/* workaround for gcc bug #37014 */
volatile int tmp_v = abs(cur_vit_mask - bin);
if (tmp_v < 75)
mask_amt = 1;
else
mask_amt = 0;
if (cur_vit_mask < 0)
mask_m[abs(cur_vit_mask / 100)] = mask_amt;
else
mask_p[cur_vit_mask / 100] = mask_amt;
}
cur_vit_mask -= 100;
}
tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
| (mask_m[48] << 26) | (mask_m[49] << 24)
| (mask_m[50] << 22) | (mask_m[51] << 20)
| (mask_m[52] << 18) | (mask_m[53] << 16)
| (mask_m[54] << 14) | (mask_m[55] << 12)
| (mask_m[56] << 10) | (mask_m[57] << 8)
| (mask_m[58] << 6) | (mask_m[59] << 4)
| (mask_m[60] << 2) | (mask_m[61] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
tmp_mask = (mask_m[31] << 28)
| (mask_m[32] << 26) | (mask_m[33] << 24)
| (mask_m[34] << 22) | (mask_m[35] << 20)
| (mask_m[36] << 18) | (mask_m[37] << 16)
| (mask_m[48] << 14) | (mask_m[39] << 12)
| (mask_m[40] << 10) | (mask_m[41] << 8)
| (mask_m[42] << 6) | (mask_m[43] << 4)
| (mask_m[44] << 2) | (mask_m[45] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
| (mask_m[18] << 26) | (mask_m[18] << 24)
| (mask_m[20] << 22) | (mask_m[20] << 20)
| (mask_m[22] << 18) | (mask_m[22] << 16)
| (mask_m[24] << 14) | (mask_m[24] << 12)
| (mask_m[25] << 10) | (mask_m[26] << 8)
| (mask_m[27] << 6) | (mask_m[28] << 4)
| (mask_m[29] << 2) | (mask_m[30] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
| (mask_m[2] << 26) | (mask_m[3] << 24)
| (mask_m[4] << 22) | (mask_m[5] << 20)
| (mask_m[6] << 18) | (mask_m[7] << 16)
| (mask_m[8] << 14) | (mask_m[9] << 12)
| (mask_m[10] << 10) | (mask_m[11] << 8)
| (mask_m[12] << 6) | (mask_m[13] << 4)
| (mask_m[14] << 2) | (mask_m[15] << 0);
REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
tmp_mask = (mask_p[15] << 28)
| (mask_p[14] << 26) | (mask_p[13] << 24)
| (mask_p[12] << 22) | (mask_p[11] << 20)
| (mask_p[10] << 18) | (mask_p[9] << 16)
| (mask_p[8] << 14) | (mask_p[7] << 12)
| (mask_p[6] << 10) | (mask_p[5] << 8)
| (mask_p[4] << 6) | (mask_p[3] << 4)
| (mask_p[2] << 2) | (mask_p[1] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
tmp_mask = (mask_p[30] << 28)
| (mask_p[29] << 26) | (mask_p[28] << 24)
| (mask_p[27] << 22) | (mask_p[26] << 20)
| (mask_p[25] << 18) | (mask_p[24] << 16)
| (mask_p[23] << 14) | (mask_p[22] << 12)
| (mask_p[21] << 10) | (mask_p[20] << 8)
| (mask_p[19] << 6) | (mask_p[18] << 4)
| (mask_p[17] << 2) | (mask_p[16] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
tmp_mask = (mask_p[45] << 28)
| (mask_p[44] << 26) | (mask_p[43] << 24)
| (mask_p[42] << 22) | (mask_p[41] << 20)
| (mask_p[40] << 18) | (mask_p[39] << 16)
| (mask_p[38] << 14) | (mask_p[37] << 12)
| (mask_p[36] << 10) | (mask_p[35] << 8)
| (mask_p[34] << 6) | (mask_p[33] << 4)
| (mask_p[32] << 2) | (mask_p[31] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
| (mask_p[59] << 26) | (mask_p[58] << 24)
| (mask_p[57] << 22) | (mask_p[56] << 20)
| (mask_p[55] << 18) | (mask_p[54] << 16)
| (mask_p[53] << 14) | (mask_p[52] << 12)
| (mask_p[51] << 10) | (mask_p[50] << 8)
| (mask_p[49] << 6) | (mask_p[48] << 4)
| (mask_p[47] << 2) | (mask_p[46] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
}
static void ar9002_olc_init(struct ath_hw *ah)
{
u32 i;
if (!OLC_FOR_AR9280_20_LATER)
return;
if (OLC_FOR_AR9287_10_LATER) {
REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9,
AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL);
ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0,
AR9287_AN_TXPC0_TXPCMODE,
AR9287_AN_TXPC0_TXPCMODE_S,
AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE);
udelay(100);
} else {
for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++)
ah->originalGain[i] =
MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4),
AR_PHY_TX_GAIN);
ah->PDADCdelta = 0;
}
}
static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
u32 pll;
pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
if (chan && IS_CHAN_5GHZ(chan)) {
pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
if (AR_SREV_9280_20(ah)) {
if (((chan->channel % 20) == 0)
|| ((chan->channel % 10) == 0))
pll = 0x2850;
else
pll = 0x142c;
}
} else {
pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
}
return pll;
}
static void ar9002_hw_do_getnf(struct ath_hw *ah,
int16_t nfarray[NUM_NF_READINGS])
{
struct ath_common *common = ath9k_hw_common(ah);
int16_t nf;
nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
if (nf & 0x100)
nf = 0 - ((nf ^ 0x1ff) + 1);
ath_print(common, ATH_DBG_CALIBRATE,
"NF calibrated [ctl] [chain 0] is %d\n", nf);
if (AR_SREV_9271(ah) && (nf >= -114))
nf = -116;
nfarray[0] = nf;
if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) {
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
AR9280_PHY_CH1_MINCCA_PWR);
if (nf & 0x100)
nf = 0 - ((nf ^ 0x1ff) + 1);
ath_print(common, ATH_DBG_CALIBRATE,
"NF calibrated [ctl] [chain 1] is %d\n", nf);
nfarray[1] = nf;
}
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
if (nf & 0x100)
nf = 0 - ((nf ^ 0x1ff) + 1);
ath_print(common, ATH_DBG_CALIBRATE,
"NF calibrated [ext] [chain 0] is %d\n", nf);
if (AR_SREV_9271(ah) && (nf >= -114))
nf = -116;
nfarray[3] = nf;
if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) {
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
AR9280_PHY_CH1_EXT_MINCCA_PWR);
if (nf & 0x100)
nf = 0 - ((nf ^ 0x1ff) + 1);
ath_print(common, ATH_DBG_CALIBRATE,
"NF calibrated [ext] [chain 1] is %d\n", nf);
nfarray[4] = nf;
}
}
void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
priv_ops->set_rf_regs = NULL;
priv_ops->rf_alloc_ext_banks = NULL;
priv_ops->rf_free_ext_banks = NULL;
priv_ops->rf_set_freq = ar9002_hw_set_channel;
priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate;
priv_ops->olc_init = ar9002_olc_init;
priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
priv_ops->do_getnf = ar9002_hw_do_getnf;
}

View File

@ -0,0 +1,572 @@
/*
* Copyright (c) 2008-2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef AR9002_PHY_H
#define AR9002_PHY_H
#define AR_PHY_TEST 0x9800
#define PHY_AGC_CLR 0x10000000
#define RFSILENT_BB 0x00002000
#define AR_PHY_TURBO 0x9804
#define AR_PHY_FC_TURBO_MODE 0x00000001
#define AR_PHY_FC_TURBO_SHORT 0x00000002
#define AR_PHY_FC_DYN2040_EN 0x00000004
#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
/* For 25 MHz channel spacing -- not used but supported by hw */
#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
#define AR_PHY_FC_HT_EN 0x00000040
#define AR_PHY_FC_SHORT_GI_40 0x00000080
#define AR_PHY_FC_WALSH 0x00000100
#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
#define AR_PHY_TEST2 0x9808
#define AR_PHY_TIMING2 0x9810
#define AR_PHY_TIMING3 0x9814
#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
#define AR_PHY_TIMING3_DSC_MAN_S 17
#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
#define AR_PHY_TIMING3_DSC_EXP_S 13
#define AR_PHY_CHIP_ID_REV_0 0x80
#define AR_PHY_CHIP_ID_REV_1 0x81
#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
#define AR_PHY_ACTIVE 0x981C
#define AR_PHY_ACTIVE_EN 0x00000001
#define AR_PHY_ACTIVE_DIS 0x00000000
#define AR_PHY_RF_CTL2 0x9824
#define AR_PHY_TX_END_DATA_START 0x000000FF
#define AR_PHY_TX_END_DATA_START_S 0
#define AR_PHY_TX_END_PA_ON 0x0000FF00
#define AR_PHY_TX_END_PA_ON_S 8
#define AR_PHY_RF_CTL3 0x9828
#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
#define AR_PHY_ADC_CTL 0x982C
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000
#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
#define AR_PHY_ADC_SERIAL_CTL 0x9830
#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
#define AR_PHY_RF_CTL4 0x9834
#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000
#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000
#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00
#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
#define AR_PHY_TSTDAC_CONST 0x983c
#define AR_PHY_SETTLING 0x9844
#define AR_PHY_SETTLING_SWITCH 0x00003F80
#define AR_PHY_SETTLING_SWITCH_S 7
#define AR_PHY_RXGAIN 0x9848
#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
#define AR_PHY_DESIRED_SZ 0x9850
#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
#define AR_PHY_DESIRED_SZ_ADC_S 0
#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
#define AR_PHY_DESIRED_SZ_PGA_S 8
#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
#define AR_PHY_FIND_SIG 0x9858
#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
#define AR_PHY_FIND_SIG_FIRSTEP_S 12
#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
#define AR_PHY_FIND_SIG_FIRPWR_S 18
#define AR_PHY_AGC_CTL1 0x985C
#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80
#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000
#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
#define AR_PHY_CCA 0x9864
#define AR_PHY_MINCCA_PWR 0x0FF80000
#define AR_PHY_MINCCA_PWR_S 19
#define AR_PHY_CCA_THRESH62 0x0007F000
#define AR_PHY_CCA_THRESH62_S 12
#define AR9280_PHY_MINCCA_PWR 0x1FF00000
#define AR9280_PHY_MINCCA_PWR_S 20
#define AR9280_PHY_CCA_THRESH62 0x000FF000
#define AR9280_PHY_CCA_THRESH62_S 12
#define AR_PHY_SFCORR_LOW 0x986C
#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
#define AR_PHY_SFCORR 0x9868
#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
#define AR_PHY_SFCORR_M2COUNT_THR_S 0
#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
#define AR_PHY_SFCORR_M1_THRESH_S 17
#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
#define AR_PHY_SFCORR_M2_THRESH_S 24
#define AR_PHY_SLEEP_CTR_CONTROL 0x9870
#define AR_PHY_SLEEP_CTR_LIMIT 0x9874
#define AR_PHY_SYNTH_CONTROL 0x9874
#define AR_PHY_SLEEP_SCAL 0x9878
#define AR_PHY_PLL_CTL 0x987c
#define AR_PHY_PLL_CTL_40 0xaa
#define AR_PHY_PLL_CTL_40_5413 0x04
#define AR_PHY_PLL_CTL_44 0xab
#define AR_PHY_PLL_CTL_44_2133 0xeb
#define AR_PHY_PLL_CTL_40_2133 0xea
#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */
#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */
#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */
#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/
#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/
#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/
#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/
#define AR_PHY_RX_DELAY 0x9914
#define AR_PHY_SEARCH_START_DELAY 0x9918
#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12))
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000
#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
#define AR_PHY_TIMING5 0x9924
#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
#define AR_PHY_POWER_TX_RATE1 0x9934
#define AR_PHY_POWER_TX_RATE2 0x9938
#define AR_PHY_POWER_TX_RATE_MAX 0x993c
#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
#define AR_PHY_FRAME_CTL 0x9944
#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038
#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
#define AR_PHY_TXPWRADJ 0x994C
#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0
#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
#define AR_PHY_RADAR_EXT 0x9940
#define AR_PHY_RADAR_EXT_ENA 0x00004000
#define AR_PHY_RADAR_0 0x9954
#define AR_PHY_RADAR_0_ENA 0x00000001
#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
#define AR_PHY_RADAR_0_INBAND 0x0000003e
#define AR_PHY_RADAR_0_INBAND_S 1
#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
#define AR_PHY_RADAR_0_PRSSI_S 6
#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
#define AR_PHY_RADAR_0_HEIGHT_S 12
#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
#define AR_PHY_RADAR_0_RRSSI_S 18
#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
#define AR_PHY_RADAR_0_FIRPWR_S 24
#define AR_PHY_RADAR_1 0x9958
#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
#define AR_PHY_RADAR_1_MAXLEN_S 0
#define AR_PHY_SWITCH_CHAIN_0 0x9960
#define AR_PHY_SWITCH_COM 0x9964
#define AR_PHY_SIGMA_DELTA 0x996C
#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8
#define AR_PHY_SIGMA_DELTA_FILT2_S 3
#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00
#define AR_PHY_SIGMA_DELTA_FILT1_S 8
#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
#define AR_PHY_RESTART 0x9970
#define AR_PHY_RESTART_DIV_GC 0x001C0000
#define AR_PHY_RESTART_DIV_GC_S 18
#define AR_PHY_RFBUS_REQ 0x997C
#define AR_PHY_RFBUS_REQ_EN 0x00000001
#define AR_PHY_TIMING7 0x9980
#define AR_PHY_TIMING8 0x9984
#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF
#define AR_PHY_TIMING8_PILOT_MASK_2_S 0
#define AR_PHY_BIN_MASK2_1 0x9988
#define AR_PHY_BIN_MASK2_2 0x998c
#define AR_PHY_BIN_MASK2_3 0x9990
#define AR_PHY_BIN_MASK2_4 0x9994
#define AR_PHY_BIN_MASK_1 0x9900
#define AR_PHY_BIN_MASK_2 0x9904
#define AR_PHY_BIN_MASK_3 0x9908
#define AR_PHY_MASK_CTL 0x990c
#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF
#define AR_PHY_BIN_MASK2_4_MASK_4_S 0
#define AR_PHY_TIMING9 0x9998
#define AR_PHY_TIMING10 0x999c
#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF
#define AR_PHY_TIMING10_PILOT_MASK_2_S 0
#define AR_PHY_TIMING11 0x99a0
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
#define AR_PHY_RX_CHAINMASK 0x99a4
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
#define AR_PHY_9285_ANT_DIV_CTL 0x01000000
#define AR_PHY_9285_ANT_DIV_CTL_S 24
#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
#define AR_PHY_9285_ANT_DIV_LNA1 2
#define AR_PHY_9285_ANT_DIV_LNA2 1
#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
#define AR_PHY_9285_ANT_DIV_GAINTB_0 0
#define AR_PHY_9285_ANT_DIV_GAINTB_1 1
#define AR_PHY_EXT_CCA0 0x99b8
#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
#define AR_PHY_EXT_CCA0_THRESH62_S 0
#define AR_PHY_EXT_CCA 0x99bc
#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00
#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9
#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
#define AR_PHY_EXT_CCA_THRESH62_S 16
#define AR_PHY_EXT_MINCCA_PWR 0xFF800000
#define AR_PHY_EXT_MINCCA_PWR_S 23
#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000
#define AR9280_PHY_EXT_MINCCA_PWR_S 16
#define AR_PHY_SFCORR_EXT 0x99c0
#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
#define AR_PHY_HALFGI 0x99D0
#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0
#define AR_PHY_HALFGI_DSC_MAN_S 4
#define AR_PHY_HALFGI_DSC_EXP 0x0000000F
#define AR_PHY_HALFGI_DSC_EXP_S 0
#define AR_PHY_CHAN_INFO_MEMORY 0x99DC
#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0
#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC
#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000
#define AR_PHY_M_SLEEP 0x99f0
#define AR_PHY_REFCLKDLY 0x99f4
#define AR_PHY_REFCLKPD 0x99f8
#define AR_PHY_CALMODE 0x99f0
#define AR_PHY_CALMODE_IQ 0x00000000
#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12))
#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12))
#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12))
#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12))
#define AR_PHY_CURRENT_RSSI 0x9c1c
#define AR9280_PHY_CURRENT_RSSI 0x9c3c
#define AR_PHY_RFBUS_GRANT 0x9C20
#define AR_PHY_RFBUS_GRANT_EN 0x00000001
#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
#define AR_PHY_CHAN_INFO_GAIN 0x9CFC
#define AR_PHY_MODE 0xA200
#define AR_PHY_MODE_ASYNCFIFO 0x80
#define AR_PHY_MODE_AR2133 0x08
#define AR_PHY_MODE_AR5111 0x00
#define AR_PHY_MODE_AR5112 0x08
#define AR_PHY_MODE_DYNAMIC 0x04
#define AR_PHY_MODE_RF2GHZ 0x02
#define AR_PHY_MODE_RF5GHZ 0x00
#define AR_PHY_MODE_CCK 0x01
#define AR_PHY_MODE_OFDM 0x00
#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
#define AR_PHY_CCK_TX_CTRL 0xA204
#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
#define AR_PHY_CCK_DETECT 0xA208
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
/* [12:6] settling time for antenna switch */
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
#define AR_PHY_GAIN_2GHZ 0xA20C
#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00
#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F
#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000
#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000
#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0
#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F
#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
#define AR_PHY_CCK_RXCTRL4 0xA21C
#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000
#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
#define AR_PHY_DAG_CTRLCCK 0xA228
#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
#define AR_PHY_FORCE_CLKEN_CCK 0xA22C
#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
#define AR_PHY_POWER_TX_RATE3 0xA234
#define AR_PHY_POWER_TX_RATE4 0xA238
#define AR_PHY_SCRM_SEQ_XR 0xA23C
#define AR_PHY_HEADER_DETECT_XR 0xA240
#define AR_PHY_CHIRP_DETECTED_XR 0xA244
#define AR_PHY_BLUETOOTH 0xA254
#define AR_PHY_TPCRG1 0xA258
#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
#define AR_PHY_TX_PWRCTRL4 0xa264
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
#define AR_PHY_TX_PWRCTRL6_0 0xa270
#define AR_PHY_TX_PWRCTRL6_1 0xb270
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
#define AR_PHY_TX_PWRCTRL7 0xa274
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
#define AR_PHY_TX_PWRCTRL9 0xa27C
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
#define AR_PHY_TX_GAIN_TBL1 0xa300
#define AR_PHY_TX_GAIN 0x0007F000
#define AR_PHY_TX_GAIN_S 12
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
#define AR_PHY_MASK2_M_31_45 0xa3a4
#define AR_PHY_MASK2_M_16_30 0xa3a8
#define AR_PHY_MASK2_M_00_15 0xa3ac
#define AR_PHY_MASK2_P_15_01 0xa3b8
#define AR_PHY_MASK2_P_30_16 0xa3bc
#define AR_PHY_MASK2_P_45_31 0xa3c0
#define AR_PHY_MASK2_P_61_45 0xa3c4
#define AR_PHY_SPUR_REG 0x994c
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18)
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9)
#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
#define AR_PHY_PILOT_MASK_01_30 0xa3b0
#define AR_PHY_PILOT_MASK_31_60 0xa3b4
#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
#define AR_PHY_ANALOG_SWAP 0xa268
#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
#define AR_PHY_TPCRG5 0xA26C
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
/* Carrier leak calibration control, do it after AGC calibration */
#define AR_PHY_CL_CAL_CTL 0xA358
#define AR_PHY_CL_CAL_ENABLE 0x00000002
#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
#define AR_PHY_POWER_TX_RATE5 0xA38C
#define AR_PHY_POWER_TX_RATE6 0xA390
#define AR_PHY_CAL_CHAINMASK 0xA39C
#define AR_PHY_POWER_TX_SUB 0xA3C8
#define AR_PHY_POWER_TX_RATE7 0xA3CC
#define AR_PHY_POWER_TX_RATE8 0xA3D0
#define AR_PHY_POWER_TX_RATE9 0xA3D4
#define AR_PHY_XPA_CFG 0xA3D8
#define AR_PHY_FORCE_XPA_CFG 0x000000001
#define AR_PHY_FORCE_XPA_CFG_S 0
#define AR_PHY_CH1_CCA 0xa864
#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000
#define AR_PHY_CH1_MINCCA_PWR_S 19
#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000
#define AR9280_PHY_CH1_MINCCA_PWR_S 20
#define AR_PHY_CH2_CCA 0xb864
#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000
#define AR_PHY_CH2_MINCCA_PWR_S 19
#define AR_PHY_CH1_EXT_CCA 0xa9bc
#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000
#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
#define AR_PHY_CH2_EXT_CCA 0xb9bc
#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000
#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
#endif

View File

@ -0,0 +1,802 @@
/*
* Copyright (c) 2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "hw.h"
#include "hw-ops.h"
#include "ar9003_phy.h"
static void ar9003_hw_setup_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal)
{
struct ath_common *common = ath9k_hw_common(ah);
/* Select calibration to run */
switch (currCal->calData->calType) {
case IQ_MISMATCH_CAL:
/*
* Start calibration with
* 2^(INIT_IQCAL_LOG_COUNT_MAX+1) samples
*/
REG_RMW_FIELD(ah, AR_PHY_TIMING4,
AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
currCal->calData->calCountMax);
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
ath_print(common, ATH_DBG_CALIBRATE,
"starting IQ Mismatch Calibration\n");
/* Kick-off cal */
REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
break;
case TEMP_COMP_CAL:
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
AR_PHY_65NM_CH0_THERM_LOCAL, 1);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
AR_PHY_65NM_CH0_THERM_START, 1);
ath_print(common, ATH_DBG_CALIBRATE,
"starting Temperature Compensation Calibration\n");
break;
case ADC_DC_INIT_CAL:
case ADC_GAIN_CAL:
case ADC_DC_CAL:
/* Not yet */
break;
}
}
/*
* Generic calibration routine.
* Recalibrate the lower PHY chips to account for temperature/environment
* changes.
*/
static bool ar9003_hw_per_calibration(struct ath_hw *ah,
struct ath9k_channel *ichan,
u8 rxchainmask,
struct ath9k_cal_list *currCal)
{
/* Cal is assumed not done until explicitly set below */
bool iscaldone = false;
/* Calibration in progress. */
if (currCal->calState == CAL_RUNNING) {
/* Check to see if it has finished. */
if (!(REG_READ(ah, AR_PHY_TIMING4) & AR_PHY_TIMING4_DO_CAL)) {
/*
* Accumulate cal measures for active chains
*/
currCal->calData->calCollect(ah);
ah->cal_samples++;
if (ah->cal_samples >=
currCal->calData->calNumSamples) {
unsigned int i, numChains = 0;
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (rxchainmask & (1 << i))
numChains++;
}
/*
* Process accumulated data
*/
currCal->calData->calPostProc(ah, numChains);
/* Calibration has finished. */
ichan->CalValid |= currCal->calData->calType;
currCal->calState = CAL_DONE;
iscaldone = true;
} else {
/*
* Set-up collection of another sub-sample until we
* get desired number
*/
ar9003_hw_setup_calibration(ah, currCal);
}
}
} else if (!(ichan->CalValid & currCal->calData->calType)) {
/* If current cal is marked invalid in channel, kick it off */
ath9k_hw_reset_calibration(ah, currCal);
}
return iscaldone;
}
static bool ar9003_hw_calibrate(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
bool longcal)
{
bool iscaldone = true;
struct ath9k_cal_list *currCal = ah->cal_list_curr;
/*
* For given calibration:
* 1. Call generic cal routine
* 2. When this cal is done (isCalDone) if we have more cals waiting
* (eg after reset), mask this to upper layers by not propagating
* isCalDone if it is set to TRUE.
* Instead, change isCalDone to FALSE and setup the waiting cal(s)
* to be run.
*/
if (currCal &&
(currCal->calState == CAL_RUNNING ||
currCal->calState == CAL_WAITING)) {
iscaldone = ar9003_hw_per_calibration(ah, chan,
rxchainmask, currCal);
if (iscaldone) {
ah->cal_list_curr = currCal = currCal->calNext;
if (currCal->calState == CAL_WAITING) {
iscaldone = false;
ath9k_hw_reset_calibration(ah, currCal);
}
}
}
/* Do NF cal only at longer intervals */
if (longcal) {
/*
* Load the NF from history buffer of the current channel.
* NF is slow time-variant, so it is OK to use a historical
* value.
*/
ath9k_hw_loadnf(ah, ah->curchan);
/* start NF calibration, without updating BB NF register */
ath9k_hw_start_nfcal(ah);
}
return iscaldone;
}
static void ar9003_hw_iqcal_collect(struct ath_hw *ah)
{
int i;
/* Accumulate IQ cal measures for active chains */
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
ah->totalPowerMeasI[i] +=
REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
ah->totalPowerMeasQ[i] +=
REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
ah->totalIqCorrMeas[i] +=
(int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
"%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
ah->cal_samples, i, ah->totalPowerMeasI[i],
ah->totalPowerMeasQ[i],
ah->totalIqCorrMeas[i]);
}
}
static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
{
struct ath_common *common = ath9k_hw_common(ah);
u32 powerMeasQ, powerMeasI, iqCorrMeas;
u32 qCoffDenom, iCoffDenom;
int32_t qCoff, iCoff;
int iqCorrNeg, i;
const u_int32_t offset_array[3] = {
AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B1,
AR_PHY_RX_IQCAL_CORR_B2,
};
for (i = 0; i < numChains; i++) {
powerMeasI = ah->totalPowerMeasI[i];
powerMeasQ = ah->totalPowerMeasQ[i];
iqCorrMeas = ah->totalIqCorrMeas[i];
ath_print(common, ATH_DBG_CALIBRATE,
"Starting IQ Cal and Correction for Chain %d\n",
i);
ath_print(common, ATH_DBG_CALIBRATE,
"Orignal: Chn %diq_corr_meas = 0x%08x\n",
i, ah->totalIqCorrMeas[i]);
iqCorrNeg = 0;
if (iqCorrMeas > 0x80000000) {
iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
iqCorrNeg = 1;
}
ath_print(common, ATH_DBG_CALIBRATE,
"Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
ath_print(common, ATH_DBG_CALIBRATE,
"Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
ath_print(common, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
iqCorrNeg);
iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 256;
qCoffDenom = powerMeasQ / 64;
if ((iCoffDenom != 0) && (qCoffDenom != 0)) {
iCoff = iqCorrMeas / iCoffDenom;
qCoff = powerMeasI / qCoffDenom - 64;
ath_print(common, ATH_DBG_CALIBRATE,
"Chn %d iCoff = 0x%08x\n", i, iCoff);
ath_print(common, ATH_DBG_CALIBRATE,
"Chn %d qCoff = 0x%08x\n", i, qCoff);
/* Force bounds on iCoff */
if (iCoff >= 63)
iCoff = 63;
else if (iCoff <= -63)
iCoff = -63;
/* Negate iCoff if iqCorrNeg == 0 */
if (iqCorrNeg == 0x0)
iCoff = -iCoff;
/* Force bounds on qCoff */
if (qCoff >= 63)
qCoff = 63;
else if (qCoff <= -63)
qCoff = -63;
iCoff = iCoff & 0x7f;
qCoff = qCoff & 0x7f;
ath_print(common, ATH_DBG_CALIBRATE,
"Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
i, iCoff, qCoff);
ath_print(common, ATH_DBG_CALIBRATE,
"Register offset (0x%04x) "
"before update = 0x%x\n",
offset_array[i],
REG_READ(ah, offset_array[i]));
REG_RMW_FIELD(ah, offset_array[i],
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
iCoff);
REG_RMW_FIELD(ah, offset_array[i],
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
qCoff);
ath_print(common, ATH_DBG_CALIBRATE,
"Register offset (0x%04x) QI COFF "
"(bitfields 0x%08x) after update = 0x%x\n",
offset_array[i],
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
REG_READ(ah, offset_array[i]));
ath_print(common, ATH_DBG_CALIBRATE,
"Register offset (0x%04x) QQ COFF "
"(bitfields 0x%08x) after update = 0x%x\n",
offset_array[i],
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF,
REG_READ(ah, offset_array[i]));
ath_print(common, ATH_DBG_CALIBRATE,
"IQ Cal and Correction done for Chain %d\n",
i);
}
}
REG_SET_BIT(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE);
ath_print(common, ATH_DBG_CALIBRATE,
"IQ Cal and Correction (offset 0x%04x) enabled "
"(bit position 0x%08x). New Value 0x%08x\n",
(unsigned) (AR_PHY_RX_IQCAL_CORR_B0),
AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE,
REG_READ(ah, AR_PHY_RX_IQCAL_CORR_B0));
}
static const struct ath9k_percal_data iq_cal_single_sample = {
IQ_MISMATCH_CAL,
MIN_CAL_SAMPLES,
PER_MAX_LOG_COUNT,
ar9003_hw_iqcal_collect,
ar9003_hw_iqcalibrate
};
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
{
ah->iq_caldata.calData = &iq_cal_single_sample;
ah->supp_cals = IQ_MISMATCH_CAL;
}
static bool ar9003_hw_iscal_supported(struct ath_hw *ah,
enum ath9k_cal_types calType)
{
switch (calType & ah->supp_cals) {
case IQ_MISMATCH_CAL:
/*
* XXX: Run IQ Mismatch for non-CCK only
* Note that CHANNEL_B is never set though.
*/
return true;
case ADC_GAIN_CAL:
case ADC_DC_CAL:
return false;
case TEMP_COMP_CAL:
return true;
}
return false;
}
/*
* solve 4x4 linear equation used in loopback iq cal.
*/
static bool ar9003_hw_solve_iq_cal(struct ath_hw *ah,
s32 sin_2phi_1,
s32 cos_2phi_1,
s32 sin_2phi_2,
s32 cos_2phi_2,
s32 mag_a0_d0,
s32 phs_a0_d0,
s32 mag_a1_d0,
s32 phs_a1_d0,
s32 solved_eq[])
{
s32 f1 = cos_2phi_1 - cos_2phi_2,
f3 = sin_2phi_1 - sin_2phi_2,
f2;
s32 mag_tx, phs_tx, mag_rx, phs_rx;
const s32 result_shift = 1 << 15;
struct ath_common *common = ath9k_hw_common(ah);
f2 = (f1 * f1 + f3 * f3) / result_shift;
if (!f2) {
ath_print(common, ATH_DBG_CALIBRATE, "Divide by 0\n");
return false;
}
/* mag mismatch, tx */
mag_tx = f1 * (mag_a0_d0 - mag_a1_d0) + f3 * (phs_a0_d0 - phs_a1_d0);
/* phs mismatch, tx */
phs_tx = f3 * (-mag_a0_d0 + mag_a1_d0) + f1 * (phs_a0_d0 - phs_a1_d0);
mag_tx = (mag_tx / f2);
phs_tx = (phs_tx / f2);
/* mag mismatch, rx */
mag_rx = mag_a0_d0 - (cos_2phi_1 * mag_tx + sin_2phi_1 * phs_tx) /
result_shift;
/* phs mismatch, rx */
phs_rx = phs_a0_d0 + (sin_2phi_1 * mag_tx - cos_2phi_1 * phs_tx) /
result_shift;
solved_eq[0] = mag_tx;
solved_eq[1] = phs_tx;
solved_eq[2] = mag_rx;
solved_eq[3] = phs_rx;
return true;
}
static s32 ar9003_hw_find_mag_approx(struct ath_hw *ah, s32 in_re, s32 in_im)
{
s32 abs_i = abs(in_re),
abs_q = abs(in_im),
max_abs, min_abs;
if (abs_i > abs_q) {
max_abs = abs_i;
min_abs = abs_q;
} else {
max_abs = abs_q;
min_abs = abs_i;
}
return max_abs - (max_abs / 32) + (min_abs / 8) + (min_abs / 4);
}
#define DELPT 32
static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
s32 chain_idx,
const s32 iq_res[],
s32 iqc_coeff[])
{
s32 i2_m_q2_a0_d0, i2_p_q2_a0_d0, iq_corr_a0_d0,
i2_m_q2_a0_d1, i2_p_q2_a0_d1, iq_corr_a0_d1,
i2_m_q2_a1_d0, i2_p_q2_a1_d0, iq_corr_a1_d0,
i2_m_q2_a1_d1, i2_p_q2_a1_d1, iq_corr_a1_d1;
s32 mag_a0_d0, mag_a1_d0, mag_a0_d1, mag_a1_d1,
phs_a0_d0, phs_a1_d0, phs_a0_d1, phs_a1_d1,
sin_2phi_1, cos_2phi_1,
sin_2phi_2, cos_2phi_2;
s32 mag_tx, phs_tx, mag_rx, phs_rx;
s32 solved_eq[4], mag_corr_tx, phs_corr_tx, mag_corr_rx, phs_corr_rx,
q_q_coff, q_i_coff;
const s32 res_scale = 1 << 15;
const s32 delpt_shift = 1 << 8;
s32 mag1, mag2;
struct ath_common *common = ath9k_hw_common(ah);
i2_m_q2_a0_d0 = iq_res[0] & 0xfff;
i2_p_q2_a0_d0 = (iq_res[0] >> 12) & 0xfff;
iq_corr_a0_d0 = ((iq_res[0] >> 24) & 0xff) + ((iq_res[1] & 0xf) << 8);
if (i2_m_q2_a0_d0 > 0x800)
i2_m_q2_a0_d0 = -((0xfff - i2_m_q2_a0_d0) + 1);
if (i2_p_q2_a0_d0 > 0x800)
i2_p_q2_a0_d0 = -((0xfff - i2_p_q2_a0_d0) + 1);
if (iq_corr_a0_d0 > 0x800)
iq_corr_a0_d0 = -((0xfff - iq_corr_a0_d0) + 1);
i2_m_q2_a0_d1 = (iq_res[1] >> 4) & 0xfff;
i2_p_q2_a0_d1 = (iq_res[2] & 0xfff);
iq_corr_a0_d1 = (iq_res[2] >> 12) & 0xfff;
if (i2_m_q2_a0_d1 > 0x800)
i2_m_q2_a0_d1 = -((0xfff - i2_m_q2_a0_d1) + 1);
if (i2_p_q2_a0_d1 > 0x800)
i2_p_q2_a0_d1 = -((0xfff - i2_p_q2_a0_d1) + 1);
if (iq_corr_a0_d1 > 0x800)
iq_corr_a0_d1 = -((0xfff - iq_corr_a0_d1) + 1);
i2_m_q2_a1_d0 = ((iq_res[2] >> 24) & 0xff) + ((iq_res[3] & 0xf) << 8);
i2_p_q2_a1_d0 = (iq_res[3] >> 4) & 0xfff;
iq_corr_a1_d0 = iq_res[4] & 0xfff;
if (i2_m_q2_a1_d0 > 0x800)
i2_m_q2_a1_d0 = -((0xfff - i2_m_q2_a1_d0) + 1);
if (i2_p_q2_a1_d0 > 0x800)
i2_p_q2_a1_d0 = -((0xfff - i2_p_q2_a1_d0) + 1);
if (iq_corr_a1_d0 > 0x800)
iq_corr_a1_d0 = -((0xfff - iq_corr_a1_d0) + 1);
i2_m_q2_a1_d1 = (iq_res[4] >> 12) & 0xfff;
i2_p_q2_a1_d1 = ((iq_res[4] >> 24) & 0xff) + ((iq_res[5] & 0xf) << 8);
iq_corr_a1_d1 = (iq_res[5] >> 4) & 0xfff;
if (i2_m_q2_a1_d1 > 0x800)
i2_m_q2_a1_d1 = -((0xfff - i2_m_q2_a1_d1) + 1);
if (i2_p_q2_a1_d1 > 0x800)
i2_p_q2_a1_d1 = -((0xfff - i2_p_q2_a1_d1) + 1);
if (iq_corr_a1_d1 > 0x800)
iq_corr_a1_d1 = -((0xfff - iq_corr_a1_d1) + 1);
if ((i2_p_q2_a0_d0 == 0) || (i2_p_q2_a0_d1 == 0) ||
(i2_p_q2_a1_d0 == 0) || (i2_p_q2_a1_d1 == 0)) {
ath_print(common, ATH_DBG_CALIBRATE,
"Divide by 0:\na0_d0=%d\n"
"a0_d1=%d\na2_d0=%d\na1_d1=%d\n",
i2_p_q2_a0_d0, i2_p_q2_a0_d1,
i2_p_q2_a1_d0, i2_p_q2_a1_d1);
return false;
}
mag_a0_d0 = (i2_m_q2_a0_d0 * res_scale) / i2_p_q2_a0_d0;
phs_a0_d0 = (iq_corr_a0_d0 * res_scale) / i2_p_q2_a0_d0;
mag_a0_d1 = (i2_m_q2_a0_d1 * res_scale) / i2_p_q2_a0_d1;
phs_a0_d1 = (iq_corr_a0_d1 * res_scale) / i2_p_q2_a0_d1;
mag_a1_d0 = (i2_m_q2_a1_d0 * res_scale) / i2_p_q2_a1_d0;
phs_a1_d0 = (iq_corr_a1_d0 * res_scale) / i2_p_q2_a1_d0;
mag_a1_d1 = (i2_m_q2_a1_d1 * res_scale) / i2_p_q2_a1_d1;
phs_a1_d1 = (iq_corr_a1_d1 * res_scale) / i2_p_q2_a1_d1;
/* w/o analog phase shift */
sin_2phi_1 = (((mag_a0_d0 - mag_a0_d1) * delpt_shift) / DELPT);
/* w/o analog phase shift */
cos_2phi_1 = (((phs_a0_d1 - phs_a0_d0) * delpt_shift) / DELPT);
/* w/ analog phase shift */
sin_2phi_2 = (((mag_a1_d0 - mag_a1_d1) * delpt_shift) / DELPT);
/* w/ analog phase shift */
cos_2phi_2 = (((phs_a1_d1 - phs_a1_d0) * delpt_shift) / DELPT);
/*
* force sin^2 + cos^2 = 1;
* find magnitude by approximation
*/
mag1 = ar9003_hw_find_mag_approx(ah, cos_2phi_1, sin_2phi_1);
mag2 = ar9003_hw_find_mag_approx(ah, cos_2phi_2, sin_2phi_2);
if ((mag1 == 0) || (mag2 == 0)) {
ath_print(common, ATH_DBG_CALIBRATE,
"Divide by 0: mag1=%d, mag2=%d\n",
mag1, mag2);
return false;
}
/* normalization sin and cos by mag */
sin_2phi_1 = (sin_2phi_1 * res_scale / mag1);
cos_2phi_1 = (cos_2phi_1 * res_scale / mag1);
sin_2phi_2 = (sin_2phi_2 * res_scale / mag2);
cos_2phi_2 = (cos_2phi_2 * res_scale / mag2);
/* calculate IQ mismatch */
if (!ar9003_hw_solve_iq_cal(ah,
sin_2phi_1, cos_2phi_1,
sin_2phi_2, cos_2phi_2,
mag_a0_d0, phs_a0_d0,
mag_a1_d0,
phs_a1_d0, solved_eq)) {
ath_print(common, ATH_DBG_CALIBRATE,
"Call to ar9003_hw_solve_iq_cal() failed.\n");
return false;
}
mag_tx = solved_eq[0];
phs_tx = solved_eq[1];
mag_rx = solved_eq[2];
phs_rx = solved_eq[3];
ath_print(common, ATH_DBG_CALIBRATE,
"chain %d: mag mismatch=%d phase mismatch=%d\n",
chain_idx, mag_tx/res_scale, phs_tx/res_scale);
if (res_scale == mag_tx) {
ath_print(common, ATH_DBG_CALIBRATE,
"Divide by 0: mag_tx=%d, res_scale=%d\n",
mag_tx, res_scale);
return false;
}
/* calculate and quantize Tx IQ correction factor */
mag_corr_tx = (mag_tx * res_scale) / (res_scale - mag_tx);
phs_corr_tx = -phs_tx;
q_q_coff = (mag_corr_tx * 128 / res_scale);
q_i_coff = (phs_corr_tx * 256 / res_scale);
ath_print(common, ATH_DBG_CALIBRATE,
"tx chain %d: mag corr=%d phase corr=%d\n",
chain_idx, q_q_coff, q_i_coff);
if (q_i_coff < -63)
q_i_coff = -63;
if (q_i_coff > 63)
q_i_coff = 63;
if (q_q_coff < -63)
q_q_coff = -63;
if (q_q_coff > 63)
q_q_coff = 63;
iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
ath_print(common, ATH_DBG_CALIBRATE,
"tx chain %d: iq corr coeff=%x\n",
chain_idx, iqc_coeff[0]);
if (-mag_rx == res_scale) {
ath_print(common, ATH_DBG_CALIBRATE,
"Divide by 0: mag_rx=%d, res_scale=%d\n",
mag_rx, res_scale);
return false;
}
/* calculate and quantize Rx IQ correction factors */
mag_corr_rx = (-mag_rx * res_scale) / (res_scale + mag_rx);
phs_corr_rx = -phs_rx;
q_q_coff = (mag_corr_rx * 128 / res_scale);
q_i_coff = (phs_corr_rx * 256 / res_scale);
ath_print(common, ATH_DBG_CALIBRATE,
"rx chain %d: mag corr=%d phase corr=%d\n",
chain_idx, q_q_coff, q_i_coff);
if (q_i_coff < -63)
q_i_coff = -63;
if (q_i_coff > 63)
q_i_coff = 63;
if (q_q_coff < -63)
q_q_coff = -63;
if (q_q_coff > 63)
q_q_coff = 63;
iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
ath_print(common, ATH_DBG_CALIBRATE,
"rx chain %d: iq corr coeff=%x\n",
chain_idx, iqc_coeff[1]);
return true;
}
static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
AR_PHY_TX_IQCAL_STATUS_B0,
AR_PHY_TX_IQCAL_STATUS_B1,
AR_PHY_TX_IQCAL_STATUS_B2,
};
const u32 tx_corr_coeff[AR9300_MAX_CHAINS] = {
AR_PHY_TX_IQCAL_CORR_COEFF_01_B0,
AR_PHY_TX_IQCAL_CORR_COEFF_01_B1,
AR_PHY_TX_IQCAL_CORR_COEFF_01_B2,
};
const u32 rx_corr[AR9300_MAX_CHAINS] = {
AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B1,
AR_PHY_RX_IQCAL_CORR_B2,
};
const u_int32_t chan_info_tab[] = {
AR_PHY_CHAN_INFO_TAB_0,
AR_PHY_CHAN_INFO_TAB_1,
AR_PHY_CHAN_INFO_TAB_2,
};
s32 iq_res[6];
s32 iqc_coeff[2];
s32 i, j;
u32 num_chains = 0;
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (ah->txchainmask & (1 << i))
num_chains++;
}
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
DELPT);
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
AR_PHY_TX_IQCAL_START_DO_CAL,
AR_PHY_TX_IQCAL_START_DO_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
AR_PHY_TX_IQCAL_START_DO_CAL,
0, AH_WAIT_TIMEOUT)) {
ath_print(common, ATH_DBG_CALIBRATE,
"Tx IQ Cal not complete.\n");
goto TX_IQ_CAL_FAILED;
}
for (i = 0; i < num_chains; i++) {
ath_print(common, ATH_DBG_CALIBRATE,
"Doing Tx IQ Cal for chain %d.\n", i);
if (REG_READ(ah, txiqcal_status[i]) &
AR_PHY_TX_IQCAL_STATUS_FAILED) {
ath_print(common, ATH_DBG_CALIBRATE,
"Tx IQ Cal failed for chain %d.\n", i);
goto TX_IQ_CAL_FAILED;
}
for (j = 0; j < 3; j++) {
u_int8_t idx = 2 * j,
offset = 4 * j;
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
AR_PHY_CHAN_INFO_TAB_S2_READ, 0);
/* 32 bits */
iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset);
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
AR_PHY_CHAN_INFO_TAB_S2_READ, 1);
/* 16 bits */
iq_res[idx+1] = 0xffff & REG_READ(ah,
chan_info_tab[i] +
offset);
ath_print(common, ATH_DBG_CALIBRATE,
"IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
idx, iq_res[idx], idx+1, iq_res[idx+1]);
}
if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) {
ath_print(common, ATH_DBG_CALIBRATE,
"Failed in calculation of IQ correction.\n");
goto TX_IQ_CAL_FAILED;
}
ath_print(common, ATH_DBG_CALIBRATE,
"IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n",
iqc_coeff[0], iqc_coeff[1]);
REG_RMW_FIELD(ah, tx_corr_coeff[i],
AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
iqc_coeff[0]);
REG_RMW_FIELD(ah, rx_corr[i],
AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF,
iqc_coeff[1] >> 7);
REG_RMW_FIELD(ah, rx_corr[i],
AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF,
iqc_coeff[1]);
}
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
return;
TX_IQ_CAL_FAILED:
ath_print(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
return;
}
static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
/*
* 0x7 = 0b111 , AR9003 needs to be configured for 3-chain mode before
* running AGC/TxIQ cals
*/
ar9003_hw_set_chain_masks(ah, 0x7, 0x7);
/* Calibrate the AGC */
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
REG_READ(ah, AR_PHY_AGC_CONTROL) |
AR_PHY_AGC_CONTROL_CAL);
/* Poll for offset calibration complete */
if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
0, AH_WAIT_TIMEOUT)) {
ath_print(common, ATH_DBG_CALIBRATE,
"offset calibration failed to "
"complete in 1ms; noisy environment?\n");
return false;
}
/* Do Tx IQ Calibration */
ar9003_hw_tx_iq_cal(ah);
/* Revert chainmasks to their original values before NF cal */
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
/* Initialize list pointers */
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
if (ar9003_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
INIT_CAL(&ah->iq_caldata);
INSERT_CAL(ah, &ah->iq_caldata);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling IQ Calibration.\n");
}
if (ar9003_hw_iscal_supported(ah, TEMP_COMP_CAL)) {
INIT_CAL(&ah->tempCompCalData);
INSERT_CAL(ah, &ah->tempCompCalData);
ath_print(common, ATH_DBG_CALIBRATE,
"enabling Temperature Compensation Calibration.\n");
}
/* Initialize current pointer to first element in list */
ah->cal_list_curr = ah->cal_list;
if (ah->cal_list_curr)
ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
chan->CalValid = 0;
return true;
}
void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
priv_ops->init_cal_settings = ar9003_hw_init_cal_settings;
priv_ops->init_cal = ar9003_hw_init_cal;
priv_ops->setup_calibration = ar9003_hw_setup_calibration;
priv_ops->iscal_supported = ar9003_hw_iscal_supported;
ops->calibrate = ar9003_hw_calibrate;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,323 @@
#ifndef AR9003_EEPROM_H
#define AR9003_EEPROM_H
#include <linux/types.h>
#define AR9300_EEP_VER 0xD000
#define AR9300_EEP_VER_MINOR_MASK 0xFFF
#define AR9300_EEP_MINOR_VER_1 0x1
#define AR9300_EEP_MINOR_VER AR9300_EEP_MINOR_VER_1
/* 16-bit offset location start of calibration struct */
#define AR9300_EEP_START_LOC 256
#define AR9300_NUM_5G_CAL_PIERS 8
#define AR9300_NUM_2G_CAL_PIERS 3
#define AR9300_NUM_5G_20_TARGET_POWERS 8
#define AR9300_NUM_5G_40_TARGET_POWERS 8
#define AR9300_NUM_2G_CCK_TARGET_POWERS 2
#define AR9300_NUM_2G_20_TARGET_POWERS 3
#define AR9300_NUM_2G_40_TARGET_POWERS 3
/* #define AR9300_NUM_CTLS 21 */
#define AR9300_NUM_CTLS_5G 9
#define AR9300_NUM_CTLS_2G 12
#define AR9300_CTL_MODE_M 0xF
#define AR9300_NUM_BAND_EDGES_5G 8
#define AR9300_NUM_BAND_EDGES_2G 4
#define AR9300_NUM_PD_GAINS 4
#define AR9300_PD_GAINS_IN_MASK 4
#define AR9300_PD_GAIN_ICEPTS 5
#define AR9300_EEPROM_MODAL_SPURS 5
#define AR9300_MAX_RATE_POWER 63
#define AR9300_NUM_PDADC_VALUES 128
#define AR9300_NUM_RATES 16
#define AR9300_BCHAN_UNUSED 0xFF
#define AR9300_MAX_PWR_RANGE_IN_HALF_DB 64
#define AR9300_OPFLAGS_11A 0x01
#define AR9300_OPFLAGS_11G 0x02
#define AR9300_OPFLAGS_5G_HT40 0x04
#define AR9300_OPFLAGS_2G_HT40 0x08
#define AR9300_OPFLAGS_5G_HT20 0x10
#define AR9300_OPFLAGS_2G_HT20 0x20
#define AR9300_EEPMISC_BIG_ENDIAN 0x01
#define AR9300_EEPMISC_WOW 0x02
#define AR9300_CUSTOMER_DATA_SIZE 20
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
#define AR9300_MAX_CHAINS 3
#define AR9300_ANT_16S 25
#define AR9300_FUTURE_MODAL_SZ 6
#define AR9300_NUM_ANT_CHAIN_FIELDS 7
#define AR9300_NUM_ANT_COMMON_FIELDS 4
#define AR9300_SIZE_ANT_CHAIN_FIELD 3
#define AR9300_SIZE_ANT_COMMON_FIELD 4
#define AR9300_ANT_CHAIN_MASK 0x7
#define AR9300_ANT_COMMON_MASK 0xf
#define AR9300_CHAIN_0_IDX 0
#define AR9300_CHAIN_1_IDX 1
#define AR9300_CHAIN_2_IDX 2
#define AR928X_NUM_ANT_CHAIN_FIELDS 6
#define AR928X_SIZE_ANT_CHAIN_FIELD 2
#define AR928X_ANT_CHAIN_MASK 0x3
/* Delta from which to start power to pdadc table */
/* This offset is used in both open loop and closed loop power control
* schemes. In open loop power control, it is not really needed, but for
* the "sake of consistency" it was kept. For certain AP designs, this
* value is overwritten by the value in the flag "pwrTableOffset" just
* before writing the pdadc vs pwr into the chip registers.
*/
#define AR9300_PWR_TABLE_OFFSET 0
/* enable flags for voltage and temp compensation */
#define ENABLE_TEMP_COMPENSATION 0x01
#define ENABLE_VOLT_COMPENSATION 0x02
/* byte addressable */
#define AR9300_EEPROM_SIZE (16*1024)
#define FIXED_CCA_THRESHOLD 15
#define AR9300_BASE_ADDR 0x3ff
enum targetPowerHTRates {
HT_TARGET_RATE_0_8_16,
HT_TARGET_RATE_1_3_9_11_17_19,
HT_TARGET_RATE_4,
HT_TARGET_RATE_5,
HT_TARGET_RATE_6,
HT_TARGET_RATE_7,
HT_TARGET_RATE_12,
HT_TARGET_RATE_13,
HT_TARGET_RATE_14,
HT_TARGET_RATE_15,
HT_TARGET_RATE_20,
HT_TARGET_RATE_21,
HT_TARGET_RATE_22,
HT_TARGET_RATE_23
};
enum targetPowerLegacyRates {
LEGACY_TARGET_RATE_6_24,
LEGACY_TARGET_RATE_36,
LEGACY_TARGET_RATE_48,
LEGACY_TARGET_RATE_54
};
enum targetPowerCckRates {
LEGACY_TARGET_RATE_1L_5L,
LEGACY_TARGET_RATE_5S,
LEGACY_TARGET_RATE_11L,
LEGACY_TARGET_RATE_11S
};
enum ar9300_Rates {
ALL_TARGET_LEGACY_6_24,
ALL_TARGET_LEGACY_36,
ALL_TARGET_LEGACY_48,
ALL_TARGET_LEGACY_54,
ALL_TARGET_LEGACY_1L_5L,
ALL_TARGET_LEGACY_5S,
ALL_TARGET_LEGACY_11L,
ALL_TARGET_LEGACY_11S,
ALL_TARGET_HT20_0_8_16,
ALL_TARGET_HT20_1_3_9_11_17_19,
ALL_TARGET_HT20_4,
ALL_TARGET_HT20_5,
ALL_TARGET_HT20_6,
ALL_TARGET_HT20_7,
ALL_TARGET_HT20_12,
ALL_TARGET_HT20_13,
ALL_TARGET_HT20_14,
ALL_TARGET_HT20_15,
ALL_TARGET_HT20_20,
ALL_TARGET_HT20_21,
ALL_TARGET_HT20_22,
ALL_TARGET_HT20_23,
ALL_TARGET_HT40_0_8_16,
ALL_TARGET_HT40_1_3_9_11_17_19,
ALL_TARGET_HT40_4,
ALL_TARGET_HT40_5,
ALL_TARGET_HT40_6,
ALL_TARGET_HT40_7,
ALL_TARGET_HT40_12,
ALL_TARGET_HT40_13,
ALL_TARGET_HT40_14,
ALL_TARGET_HT40_15,
ALL_TARGET_HT40_20,
ALL_TARGET_HT40_21,
ALL_TARGET_HT40_22,
ALL_TARGET_HT40_23,
ar9300RateSize,
};
struct eepFlags {
u8 opFlags;
u8 eepMisc;
} __packed;
enum CompressAlgorithm {
_CompressNone = 0,
_CompressLzma,
_CompressPairs,
_CompressBlock,
_Compress4,
_Compress5,
_Compress6,
_Compress7,
};
struct ar9300_base_eep_hdr {
u16 regDmn[2];
/* 4 bits tx and 4 bits rx */
u8 txrxMask;
struct eepFlags opCapFlags;
u8 rfSilent;
u8 blueToothOptions;
u8 deviceCap;
/* takes lower byte in eeprom location */
u8 deviceType;
/* offset in dB to be added to beginning
* of pdadc table in calibration
*/
int8_t pwrTableOffset;
u8 params_for_tuning_caps[2];
/*
* bit0 - enable tx temp comp
* bit1 - enable tx volt comp
* bit2 - enable fastClock - default to 1
* bit3 - enable doubling - default to 1
* bit4 - enable internal regulator - default to 1
*/
u8 featureEnable;
/* misc flags: bit0 - turn down drivestrength */
u8 miscConfiguration;
u8 eepromWriteEnableGpio;
u8 wlanDisableGpio;
u8 wlanLedGpio;
u8 rxBandSelectGpio;
u8 txrxgain;
/* SW controlled internal regulator fields */
u32 swreg;
} __packed;
struct ar9300_modal_eep_header {
/* 4 idle, t1, t2, b (4 bits per setting) */
u32 antCtrlCommon;
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
u32 antCtrlCommon2;
/* 6 idle, t, r, rx1, rx12, b (2 bits each) */
u16 antCtrlChain[AR9300_MAX_CHAINS];
/* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
u8 xatten1DB[AR9300_MAX_CHAINS];
/* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */
u8 xatten1Margin[AR9300_MAX_CHAINS];
int8_t tempSlope;
int8_t voltSlope;
/* spur channels in usual fbin coding format */
u8 spurChans[AR9300_EEPROM_MODAL_SPURS];
/* 3 Check if the register is per chain */
int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
u8 ob[AR9300_MAX_CHAINS];
u8 db_stage2[AR9300_MAX_CHAINS];
u8 db_stage3[AR9300_MAX_CHAINS];
u8 db_stage4[AR9300_MAX_CHAINS];
u8 xpaBiasLvl;
u8 txFrameToDataStart;
u8 txFrameToPaOn;
u8 txClip;
int8_t antennaGain;
u8 switchSettling;
int8_t adcDesiredSize;
u8 txEndToXpaOff;
u8 txEndToRxOn;
u8 txFrameToXpaOn;
u8 thresh62;
u8 futureModal[32];
} __packed;
struct ar9300_cal_data_per_freq_op_loop {
int8_t refPower;
/* pdadc voltage at power measurement */
u8 voltMeas;
/* pcdac used for power measurement */
u8 tempMeas;
/* range is -60 to -127 create a mapping equation 1db resolution */
int8_t rxNoisefloorCal;
/*range is same as noisefloor */
int8_t rxNoisefloorPower;
/* temp measured when noisefloor cal was performed */
u8 rxTempMeas;
} __packed;
struct cal_tgt_pow_legacy {
u8 tPow2x[4];
} __packed;
struct cal_tgt_pow_ht {
u8 tPow2x[14];
} __packed;
struct cal_ctl_edge_pwr {
u8 tPower:6,
flag:2;
} __packed;
struct cal_ctl_data_2g {
struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G];
} __packed;
struct cal_ctl_data_5g {
struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G];
} __packed;
struct ar9300_eeprom {
u8 eepromVersion;
u8 templateVersion;
u8 macAddr[6];
u8 custData[AR9300_CUSTOMER_DATA_SIZE];
struct ar9300_base_eep_hdr baseEepHeader;
struct ar9300_modal_eep_header modalHeader2G;
u8 calFreqPier2G[AR9300_NUM_2G_CAL_PIERS];
struct ar9300_cal_data_per_freq_op_loop
calPierData2G[AR9300_MAX_CHAINS][AR9300_NUM_2G_CAL_PIERS];
u8 calTarget_freqbin_Cck[AR9300_NUM_2G_CCK_TARGET_POWERS];
u8 calTarget_freqbin_2G[AR9300_NUM_2G_20_TARGET_POWERS];
u8 calTarget_freqbin_2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
u8 calTarget_freqbin_2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
struct cal_tgt_pow_legacy
calTargetPowerCck[AR9300_NUM_2G_CCK_TARGET_POWERS];
struct cal_tgt_pow_legacy
calTargetPower2G[AR9300_NUM_2G_20_TARGET_POWERS];
struct cal_tgt_pow_ht
calTargetPower2GHT20[AR9300_NUM_2G_20_TARGET_POWERS];
struct cal_tgt_pow_ht
calTargetPower2GHT40[AR9300_NUM_2G_40_TARGET_POWERS];
u8 ctlIndex_2G[AR9300_NUM_CTLS_2G];
u8 ctl_freqbin_2G[AR9300_NUM_CTLS_2G][AR9300_NUM_BAND_EDGES_2G];
struct cal_ctl_data_2g ctlPowerData_2G[AR9300_NUM_CTLS_2G];
struct ar9300_modal_eep_header modalHeader5G;
u8 calFreqPier5G[AR9300_NUM_5G_CAL_PIERS];
struct ar9300_cal_data_per_freq_op_loop
calPierData5G[AR9300_MAX_CHAINS][AR9300_NUM_5G_CAL_PIERS];
u8 calTarget_freqbin_5G[AR9300_NUM_5G_20_TARGET_POWERS];
u8 calTarget_freqbin_5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
u8 calTarget_freqbin_5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
struct cal_tgt_pow_legacy
calTargetPower5G[AR9300_NUM_5G_20_TARGET_POWERS];
struct cal_tgt_pow_ht
calTargetPower5GHT20[AR9300_NUM_5G_20_TARGET_POWERS];
struct cal_tgt_pow_ht
calTargetPower5GHT40[AR9300_NUM_5G_40_TARGET_POWERS];
u8 ctlIndex_5G[AR9300_NUM_CTLS_5G];
u8 ctl_freqbin_5G[AR9300_NUM_CTLS_5G][AR9300_NUM_BAND_EDGES_5G];
struct cal_ctl_data_5g ctlPowerData_5G[AR9300_NUM_CTLS_5G];
} __packed;
s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah);
s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah);
#endif

View File

@ -0,0 +1,205 @@
/*
* Copyright (c) 2008-2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "hw.h"
#include "ar9003_mac.h"
#include "ar9003_initvals.h"
/* General hardware code for the AR9003 hadware family */
static bool ar9003_hw_macversion_supported(u32 macversion)
{
switch (macversion) {
case AR_SREV_VERSION_9300:
return true;
default:
break;
}
return false;
}
/* AR9003 2.0 - new INI format (pre, core, post arrays per subsystem) */
/*
* XXX: move TX/RX gain INI to its own init_mode_gain_regs after
* ensuring it does not affect hardware bring up
*/
static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
{
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9300_2p0_mac_core,
ARRAY_SIZE(ar9300_2p0_mac_core), 2);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9300_2p0_mac_postamble,
ARRAY_SIZE(ar9300_2p0_mac_postamble), 5);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9300_2p0_baseband_core,
ARRAY_SIZE(ar9300_2p0_baseband_core), 2);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9300_2p0_baseband_postamble,
ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9300_2p0_radio_core,
ARRAY_SIZE(ar9300_2p0_radio_core), 2);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9300_2p0_radio_postamble,
ARRAY_SIZE(ar9300_2p0_radio_postamble), 5);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9300_2p0_soc_preamble,
ARRAY_SIZE(ar9300_2p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9300_2p0_soc_postamble,
ARRAY_SIZE(ar9300_2p0_soc_postamble), 5);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p0,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
5);
/* Load PCIE SERDES settings from INI */
/* Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9300PciePhy_pll_on_clkreq_disable_L1_2p0,
ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0),
2);
/* Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
ar9300PciePhy_clkreq_enable_L1_2p0,
ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0),
2);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesAdditional,
ar9300Modes_fast_clock_2p0,
ARRAY_SIZE(ar9300Modes_fast_clock_2p0),
3);
}
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_tx_gain_idx(ah)) {
case 0:
default:
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0),
5);
break;
case 1:
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0),
5);
break;
case 2:
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0),
5);
break;
}
}
static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
{
switch (ar9003_hw_get_rx_gain_idx(ah)) {
case 0:
default:
INIT_INI_ARRAY(&ah->iniModesRxGain, ar9300Common_rx_gain_table_2p0,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p0),
2);
break;
case 1:
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p0,
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0),
2);
break;
}
}
/* set gain table pointers according to values read from the eeprom */
static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
{
ar9003_tx_gain_table_apply(ah);
ar9003_rx_gain_table_apply(ah);
}
/*
* Helper for ASPM support.
*
* Disable PLL when in L0s as well as receiver clock when in L1.
* This power saving option must be enabled through the SerDes.
*
* Programming the SerDes must go through the same 288 bit serial shift
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
int restore,
int power_off)
{
if (ah->is_pciexpress != true)
return;
/* Do not touch SerDes registers */
if (ah->config.pcie_powersave_enable == 2)
return;
/* Nothing to do on restore for 11N */
if (!restore) {
/* set bit 19 to allow forcing of pcie core into L1 state */
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
/* Several PCIe massages to ensure proper behaviour */
if (ah->config.pcie_waen)
REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
}
}
/* Sets up the AR9003 hardware familiy callbacks */
void ar9003_hw_attach_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
priv_ops->macversion_supported = ar9003_hw_macversion_supported;
ops->config_pci_powersave = ar9003_hw_configpcipowersave;
ar9003_hw_attach_phy_ops(ah);
ar9003_hw_attach_calib_ops(ah);
ar9003_hw_attach_mac_ops(ah);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,611 @@
/*
* Copyright (c) 2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "hw.h"
#include "ar9003_mac.h"
static void ar9003_hw_rx_enable(struct ath_hw *hw)
{
REG_WRITE(hw, AR_CR, 0);
}
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
{
int checksum;
checksum = ads->info + ads->link
+ ads->data0 + ads->ctl3
+ ads->data1 + ads->ctl5
+ ads->data2 + ads->ctl7
+ ads->data3 + ads->ctl9;
return ((checksum & 0xffff) + (checksum >> 16)) & AR_TxPtrChkSum;
}
static void ar9003_hw_set_desc_link(void *ds, u32 ds_link)
{
struct ar9003_txc *ads = ds;
ads->link = ds_link;
ads->ctl10 &= ~AR_TxPtrChkSum;
ads->ctl10 |= ar9003_calc_ptr_chksum(ads);
}
static void ar9003_hw_get_desc_link(void *ds, u32 **ds_link)
{
struct ar9003_txc *ads = ds;
*ds_link = &ads->link;
}
static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
{
u32 isr = 0;
u32 mask2 = 0;
struct ath9k_hw_capabilities *pCap = &ah->caps;
u32 sync_cause = 0;
struct ath_common *common = ath9k_hw_common(ah);
if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M)
== AR_RTC_STATUS_ON)
isr = REG_READ(ah, AR_ISR);
}
sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
*masked = 0;
if (!isr && !sync_cause)
return false;
if (isr) {
if (isr & AR_ISR_BCNMISC) {
u32 isr2;
isr2 = REG_READ(ah, AR_ISR_S2);
mask2 |= ((isr2 & AR_ISR_S2_TIM) >>
MAP_ISR_S2_TIM);
mask2 |= ((isr2 & AR_ISR_S2_DTIM) >>
MAP_ISR_S2_DTIM);
mask2 |= ((isr2 & AR_ISR_S2_DTIMSYNC) >>
MAP_ISR_S2_DTIMSYNC);
mask2 |= ((isr2 & AR_ISR_S2_CABEND) >>
MAP_ISR_S2_CABEND);
mask2 |= ((isr2 & AR_ISR_S2_GTT) <<
MAP_ISR_S2_GTT);
mask2 |= ((isr2 & AR_ISR_S2_CST) <<
MAP_ISR_S2_CST);
mask2 |= ((isr2 & AR_ISR_S2_TSFOOR) >>
MAP_ISR_S2_TSFOOR);
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
REG_WRITE(ah, AR_ISR_S2, isr2);
isr &= ~AR_ISR_BCNMISC;
}
}
if ((pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED))
isr = REG_READ(ah, AR_ISR_RAC);
if (isr == 0xffffffff) {
*masked = 0;
return false;
}
*masked = isr & ATH9K_INT_COMMON;
if (ah->config.rx_intr_mitigation)
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
*masked |= ATH9K_INT_RXLP;
if (ah->config.tx_intr_mitigation)
if (isr & (AR_ISR_TXMINTR | AR_ISR_TXINTM))
*masked |= ATH9K_INT_TX;
if (isr & (AR_ISR_LP_RXOK | AR_ISR_RXERR))
*masked |= ATH9K_INT_RXLP;
if (isr & AR_ISR_HP_RXOK)
*masked |= ATH9K_INT_RXHP;
if (isr & (AR_ISR_TXOK | AR_ISR_TXERR | AR_ISR_TXEOL)) {
*masked |= ATH9K_INT_TX;
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
u32 s0, s1;
s0 = REG_READ(ah, AR_ISR_S0);
REG_WRITE(ah, AR_ISR_S0, s0);
s1 = REG_READ(ah, AR_ISR_S1);
REG_WRITE(ah, AR_ISR_S1, s1);
isr &= ~(AR_ISR_TXOK | AR_ISR_TXERR |
AR_ISR_TXEOL);
}
}
if (isr & AR_ISR_GENTMR) {
u32 s5;
if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)
s5 = REG_READ(ah, AR_ISR_S5_S);
else
s5 = REG_READ(ah, AR_ISR_S5);
ah->intr_gen_timer_trigger =
MS(s5, AR_ISR_S5_GENTIMER_TRIG);
ah->intr_gen_timer_thresh =
MS(s5, AR_ISR_S5_GENTIMER_THRESH);
if (ah->intr_gen_timer_trigger)
*masked |= ATH9K_INT_GENTIMER;
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
REG_WRITE(ah, AR_ISR_S5, s5);
isr &= ~AR_ISR_GENTMR;
}
}
*masked |= mask2;
if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) {
REG_WRITE(ah, AR_ISR, isr);
(void) REG_READ(ah, AR_ISR);
}
}
if (sync_cause) {
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
REG_WRITE(ah, AR_RC, 0);
*masked |= ATH9K_INT_FATAL;
}
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT)
ath_print(common, ATH_DBG_INTERRUPT,
"AR_INTR_SYNC_LOCAL_TIMEOUT\n");
REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
}
return true;
}
static void ar9003_hw_fill_txdesc(struct ath_hw *ah, void *ds, u32 seglen,
bool is_firstseg, bool is_lastseg,
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
unsigned int descid = 0;
ads->info = (ATHEROS_VENDOR_ID << AR_DescId_S) |
(1 << AR_TxRxDesc_S) |
(1 << AR_CtrlStat_S) |
(qcu << AR_TxQcuNum_S) | 0x17;
ads->data0 = buf_addr;
ads->data1 = 0;
ads->data2 = 0;
ads->data3 = 0;
ads->ctl3 = (seglen << AR_BufLen_S);
ads->ctl3 &= AR_BufLen;
/* Fill in pointer checksum and descriptor id */
ads->ctl10 = ar9003_calc_ptr_chksum(ads);
ads->ctl10 |= (descid << AR_TxDescId_S);
if (is_firstseg) {
ads->ctl12 |= (is_lastseg ? 0 : AR_TxMore);
} else if (is_lastseg) {
ads->ctl11 = 0;
ads->ctl12 = 0;
ads->ctl13 = AR9003TXC_CONST(ds0)->ctl13;
ads->ctl14 = AR9003TXC_CONST(ds0)->ctl14;
} else {
/* XXX Intermediate descriptor in a multi-descriptor frame.*/
ads->ctl11 = 0;
ads->ctl12 = AR_TxMore;
ads->ctl13 = 0;
ads->ctl14 = 0;
}
}
static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
struct ar9003_txs *ads;
ads = &ah->ts_ring[ah->ts_tail];
if ((ads->status8 & AR_TxDone) == 0)
return -EINPROGRESS;
ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
if ((MS(ads->ds_info, AR_DescId) != ATHEROS_VENDOR_ID) ||
(MS(ads->ds_info, AR_TxRxDesc) != 1)) {
ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT,
"Tx Descriptor error %x\n", ads->ds_info);
memset(ads, 0, sizeof(*ads));
return -EIO;
}
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
ts->desc_id = MS(ads->status1, AR_TxDescId);
ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
ts->ts_tstamp = ads->status4;
ts->ts_status = 0;
ts->ts_flags = 0;
if (ads->status3 & AR_ExcessiveRetries)
ts->ts_status |= ATH9K_TXERR_XRETRY;
if (ads->status3 & AR_Filtered)
ts->ts_status |= ATH9K_TXERR_FILT;
if (ads->status3 & AR_FIFOUnderrun) {
ts->ts_status |= ATH9K_TXERR_FIFO;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->status8 & AR_TxOpExceeded)
ts->ts_status |= ATH9K_TXERR_XTXOP;
if (ads->status3 & AR_TxTimerExpired)
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
if (ads->status3 & AR_DescCfgErr)
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
if (ads->status3 & AR_TxDataUnderrun) {
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->status3 & AR_TxDelimUnderrun) {
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->status2 & AR_TxBaStatus) {
ts->ts_flags |= ATH9K_TX_BA;
ts->ba_low = ads->status5;
ts->ba_high = ads->status6;
}
ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx);
ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined);
ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
ts->ts_antenna = 0;
ts->tid = MS(ads->status8, AR_TxTid);
memset(ads, 0, sizeof(*ads));
return 0;
}
static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktlen, enum ath9k_pkt_type type, u32 txpower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
txpower += ah->txpower_indexoffset;
if (txpower > 63)
txpower = 63;
ads->ctl11 = (pktlen & AR_FrameLen)
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txpower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0);
ads->ctl12 =
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
| SM(type, AR_FrameType)
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
ads->ctl17 = SM(keyType, AR_EncrType) |
(flags & ATH9K_TXDESC_LDPC ? AR_LDPC : 0);
ads->ctl18 = 0;
ads->ctl19 = AR_Not_Sounding;
ads->ctl20 = 0;
ads->ctl21 = 0;
ads->ctl22 = 0;
}
static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
struct ar9003_txc *last_ads = (struct ar9003_txc *) lastds;
u_int32_t ctl11;
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
ctl11 = ads->ctl11;
if (flags & ATH9K_TXDESC_RTSENA) {
ctl11 &= ~AR_CTSEnable;
ctl11 |= AR_RTSEnable;
} else {
ctl11 &= ~AR_RTSEnable;
ctl11 |= AR_CTSEnable;
}
ads->ctl11 = ctl11;
} else {
ads->ctl11 = (ads->ctl11 & ~(AR_RTSEnable | AR_CTSEnable));
}
ads->ctl13 = set11nTries(series, 0)
| set11nTries(series, 1)
| set11nTries(series, 2)
| set11nTries(series, 3)
| (durUpdateEn ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ads->ctl14 = set11nRate(series, 0)
| set11nRate(series, 1)
| set11nRate(series, 2)
| set11nRate(series, 3);
ads->ctl15 = set11nPktDurRTSCTS(series, 0)
| set11nPktDurRTSCTS(series, 1);
ads->ctl16 = set11nPktDurRTSCTS(series, 2)
| set11nPktDurRTSCTS(series, 3);
ads->ctl18 = set11nRateFlags(series, 0)
| set11nRateFlags(series, 1)
| set11nRateFlags(series, 2)
| set11nRateFlags(series, 3)
| SM(rtsctsRate, AR_RTSCTSRate);
ads->ctl19 = AR_Not_Sounding;
last_ads->ctl13 = ads->ctl13;
last_ads->ctl14 = ads->ctl14;
}
static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
ads->ctl17 &= ~AR_AggrLen;
ads->ctl17 |= SM(aggrLen, AR_AggrLen);
}
static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
u32 numDelims)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
unsigned int ctl17;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
/*
* We use a stack variable to manipulate ctl6 to reduce uncached
* read modify, modfiy, write.
*/
ctl17 = ads->ctl17;
ctl17 &= ~AR_PadDelim;
ctl17 |= SM(numDelims, AR_PadDelim);
ads->ctl17 = ctl17;
}
static void ar9003_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= AR_IsAggr;
ads->ctl12 &= ~AR_MoreAggr;
ads->ctl17 &= ~AR_PadDelim;
}
static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr);
}
static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
u32 burstDuration)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl13 &= ~AR_BurstDur;
ads->ctl13 |= SM(burstDuration, AR_BurstDur);
}
static void ar9003_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
u32 vmf)
{
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
if (vmf)
ads->ctl11 |= AR_VirtMoreFrag;
else
ads->ctl11 &= ~AR_VirtMoreFrag;
}
void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
{
struct ath_hw_ops *ops = ath9k_hw_ops(hw);
ops->rx_enable = ar9003_hw_rx_enable;
ops->set_desc_link = ar9003_hw_set_desc_link;
ops->get_desc_link = ar9003_hw_get_desc_link;
ops->get_isr = ar9003_hw_get_isr;
ops->fill_txdesc = ar9003_hw_fill_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc;
ops->set11n_txdesc = ar9003_hw_set11n_txdesc;
ops->set11n_ratescenario = ar9003_hw_set11n_ratescenario;
ops->set11n_aggr_first = ar9003_hw_set11n_aggr_first;
ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle;
ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last;
ops->clr11n_aggr = ar9003_hw_clr11n_aggr;
ops->set11n_burstduration = ar9003_hw_set11n_burstduration;
ops->set11n_virtualmorefrag = ar9003_hw_set11n_virtualmorefrag;
}
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
{
REG_WRITE(ah, AR_DATABUF_SIZE, buf_size & AR_DATABUF_SIZE_MASK);
}
EXPORT_SYMBOL(ath9k_hw_set_rx_bufsize);
void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
enum ath9k_rx_qtype qtype)
{
if (qtype == ATH9K_RX_QUEUE_HP)
REG_WRITE(ah, AR_HP_RXDP, rxdp);
else
REG_WRITE(ah, AR_LP_RXDP, rxdp);
}
EXPORT_SYMBOL(ath9k_hw_addrxbuf_edma);
int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
void *buf_addr)
{
struct ar9003_rxs *rxsp = (struct ar9003_rxs *) buf_addr;
unsigned int phyerr;
/* TODO: byte swap on big endian for ar9300_10 */
if ((rxsp->status11 & AR_RxDone) == 0)
return -EINPROGRESS;
if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
return -EINVAL;
if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
return -EINPROGRESS;
if (!rxs)
return 0;
rxs->rs_status = 0;
rxs->rs_flags = 0;
rxs->rs_datalen = rxsp->status2 & AR_DataLen;
rxs->rs_tstamp = rxsp->status3;
/* XXX: Keycache */
rxs->rs_rssi = MS(rxsp->status5, AR_RxRSSICombined);
rxs->rs_rssi_ctl0 = MS(rxsp->status1, AR_RxRSSIAnt00);
rxs->rs_rssi_ctl1 = MS(rxsp->status1, AR_RxRSSIAnt01);
rxs->rs_rssi_ctl2 = MS(rxsp->status1, AR_RxRSSIAnt02);
rxs->rs_rssi_ext0 = MS(rxsp->status5, AR_RxRSSIAnt10);
rxs->rs_rssi_ext1 = MS(rxsp->status5, AR_RxRSSIAnt11);
rxs->rs_rssi_ext2 = MS(rxsp->status5, AR_RxRSSIAnt12);
if (rxsp->status11 & AR_RxKeyIdxValid)
rxs->rs_keyix = MS(rxsp->status11, AR_KeyIdx);
else
rxs->rs_keyix = ATH9K_RXKEYIX_INVALID;
rxs->rs_rate = MS(rxsp->status1, AR_RxRate);
rxs->rs_more = (rxsp->status2 & AR_RxMore) ? 1 : 0;
rxs->rs_isaggr = (rxsp->status11 & AR_RxAggr) ? 1 : 0;
rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0;
rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7);
rxs->rs_flags = (rxsp->status4 & AR_GI) ? ATH9K_RX_GI : 0;
rxs->rs_flags |= (rxsp->status4 & AR_2040) ? ATH9K_RX_2040 : 0;
rxs->evm0 = rxsp->status6;
rxs->evm1 = rxsp->status7;
rxs->evm2 = rxsp->status8;
rxs->evm3 = rxsp->status9;
rxs->evm4 = (rxsp->status10 & 0xffff);
if (rxsp->status11 & AR_PreDelimCRCErr)
rxs->rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
if (rxsp->status11 & AR_PostDelimCRCErr)
rxs->rs_flags |= ATH9K_RX_DELIM_CRC_POST;
if (rxsp->status11 & AR_DecryptBusyErr)
rxs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
if ((rxsp->status11 & AR_RxFrameOK) == 0) {
if (rxsp->status11 & AR_CRCErr) {
rxs->rs_status |= ATH9K_RXERR_CRC;
} else if (rxsp->status11 & AR_PHYErr) {
rxs->rs_status |= ATH9K_RXERR_PHY;
phyerr = MS(rxsp->status11, AR_PHYErrCode);
rxs->rs_phyerr = phyerr;
} else if (rxsp->status11 & AR_DecryptCRCErr) {
rxs->rs_status |= ATH9K_RXERR_DECRYPT;
} else if (rxsp->status11 & AR_MichaelErr) {
rxs->rs_status |= ATH9K_RXERR_MIC;
}
}
return 0;
}
EXPORT_SYMBOL(ath9k_hw_process_rxdesc_edma);
void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah)
{
ah->ts_tail = 0;
memset((void *) ah->ts_ring, 0,
ah->ts_size * sizeof(struct ar9003_txs));
ath_print(ath9k_hw_common(ah), ATH_DBG_XMIT,
"TS Start 0x%x End 0x%x Virt %p, Size %d\n",
ah->ts_paddr_start, ah->ts_paddr_end,
ah->ts_ring, ah->ts_size);
REG_WRITE(ah, AR_Q_STATUS_RING_START, ah->ts_paddr_start);
REG_WRITE(ah, AR_Q_STATUS_RING_END, ah->ts_paddr_end);
}
void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
u32 ts_paddr_start,
u8 size)
{
ah->ts_paddr_start = ts_paddr_start;
ah->ts_paddr_end = ts_paddr_start + (size * sizeof(struct ar9003_txs));
ah->ts_size = size;
ah->ts_ring = (struct ar9003_txs *) ts_start;
ath9k_hw_reset_txstatus_ring(ah);
}
EXPORT_SYMBOL(ath9k_hw_setup_statusring);

View File

@ -0,0 +1,120 @@
/*
* Copyright (c) 2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef AR9003_MAC_H
#define AR9003_MAC_H
#define AR_DescId 0xffff0000
#define AR_DescId_S 16
#define AR_CtrlStat 0x00004000
#define AR_CtrlStat_S 14
#define AR_TxRxDesc 0x00008000
#define AR_TxRxDesc_S 15
#define AR_TxQcuNum 0x00000f00
#define AR_TxQcuNum_S 8
#define AR_BufLen 0x0fff0000
#define AR_BufLen_S 16
#define AR_TxDescId 0xffff0000
#define AR_TxDescId_S 16
#define AR_TxPtrChkSum 0x0000ffff
#define AR_TxTid 0xf0000000
#define AR_TxTid_S 28
#define AR_LowRxChain 0x00004000
#define AR_Not_Sounding 0x20000000
#define MAP_ISR_S2_CST 6
#define MAP_ISR_S2_GTT 6
#define MAP_ISR_S2_TIM 3
#define MAP_ISR_S2_CABEND 0
#define MAP_ISR_S2_DTIMSYNC 7
#define MAP_ISR_S2_DTIM 7
#define MAP_ISR_S2_TSFOOR 4
#define AR9003TXC_CONST(_ds) ((const struct ar9003_txc *) _ds)
struct ar9003_rxs {
u32 ds_info;
u32 status1;
u32 status2;
u32 status3;
u32 status4;
u32 status5;
u32 status6;
u32 status7;
u32 status8;
u32 status9;
u32 status10;
u32 status11;
} __packed;
/* Transmit Control Descriptor */
struct ar9003_txc {
u32 info; /* descriptor information */
u32 link; /* link pointer */
u32 data0; /* data pointer to 1st buffer */
u32 ctl3; /* DMA control 3 */
u32 data1; /* data pointer to 2nd buffer */
u32 ctl5; /* DMA control 5 */
u32 data2; /* data pointer to 3rd buffer */
u32 ctl7; /* DMA control 7 */
u32 data3; /* data pointer to 4th buffer */
u32 ctl9; /* DMA control 9 */
u32 ctl10; /* DMA control 10 */
u32 ctl11; /* DMA control 11 */
u32 ctl12; /* DMA control 12 */
u32 ctl13; /* DMA control 13 */
u32 ctl14; /* DMA control 14 */
u32 ctl15; /* DMA control 15 */
u32 ctl16; /* DMA control 16 */
u32 ctl17; /* DMA control 17 */
u32 ctl18; /* DMA control 18 */
u32 ctl19; /* DMA control 19 */
u32 ctl20; /* DMA control 20 */
u32 ctl21; /* DMA control 21 */
u32 ctl22; /* DMA control 22 */
u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
} __packed;
struct ar9003_txs {
u32 ds_info;
u32 status1;
u32 status2;
u32 status3;
u32 status4;
u32 status5;
u32 status6;
u32 status7;
u32 status8;
} __packed;
void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
void ath9k_hw_addrxbuf_edma(struct ath_hw *ah, u32 rxdp,
enum ath9k_rx_qtype qtype);
int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah,
struct ath_rx_status *rxs,
void *buf_addr);
void ath9k_hw_reset_txstatus_ring(struct ath_hw *ah);
void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
u32 ts_paddr_start,
u8 size);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,847 @@
/*
* Copyright (c) 2002-2010 Atheros Communications, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef AR9003_PHY_H
#define AR9003_PHY_H
/*
* Channel Register Map
*/
#define AR_CHAN_BASE 0x9800
#define AR_PHY_TIMING1 (AR_CHAN_BASE + 0x0)
#define AR_PHY_TIMING2 (AR_CHAN_BASE + 0x4)
#define AR_PHY_TIMING3 (AR_CHAN_BASE + 0x8)
#define AR_PHY_TIMING4 (AR_CHAN_BASE + 0xc)
#define AR_PHY_TIMING5 (AR_CHAN_BASE + 0x10)
#define AR_PHY_TIMING6 (AR_CHAN_BASE + 0x14)
#define AR_PHY_TIMING11 (AR_CHAN_BASE + 0x18)
#define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c)
#define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc)
#define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0)
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC 0x40000000
#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_AGC_S 30
#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR 0x80000000
#define AR_PHY_TIMING11_USE_SPUR_FILTER_IN_SELFCOR_S 31
#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT 0x4000000
#define AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT_S 26
#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 /* bins move with freq offset */
#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM_S 17
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x000000FF
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI 0x00000100
#define AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI_S 8
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL 0x03FC0000
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN 0x20000000
#define AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN_S 29
#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN 0x80000000
#define AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN_S 31
#define AR_PHY_FIND_SIG_LOW (AR_CHAN_BASE + 0x20)
#define AR_PHY_SFCORR (AR_CHAN_BASE + 0x24)
#define AR_PHY_SFCORR_LOW (AR_CHAN_BASE + 0x28)
#define AR_PHY_SFCORR_EXT (AR_CHAN_BASE + 0x2c)
#define AR_PHY_EXT_CCA (AR_CHAN_BASE + 0x30)
#define AR_PHY_RADAR_0 (AR_CHAN_BASE + 0x34)
#define AR_PHY_RADAR_1 (AR_CHAN_BASE + 0x38)
#define AR_PHY_RADAR_EXT (AR_CHAN_BASE + 0x3c)
#define AR_PHY_MULTICHAIN_CTRL (AR_CHAN_BASE + 0x80)
#define AR_PHY_PERCHAIN_CSD (AR_CHAN_BASE + 0x84)
#define AR_PHY_TX_PHASE_RAMP_0 (AR_CHAN_BASE + 0xd0)
#define AR_PHY_ADC_GAIN_DC_CORR_0 (AR_CHAN_BASE + 0xd4)
#define AR_PHY_IQ_ADC_MEAS_0_B0 (AR_CHAN_BASE + 0xc0)
#define AR_PHY_IQ_ADC_MEAS_1_B0 (AR_CHAN_BASE + 0xc4)
#define AR_PHY_IQ_ADC_MEAS_2_B0 (AR_CHAN_BASE + 0xc8)
#define AR_PHY_IQ_ADC_MEAS_3_B0 (AR_CHAN_BASE + 0xcc)
/* The following registers changed position from AR9300 1.0 to AR9300 2.0 */
#define AR_PHY_TX_PHASE_RAMP_0_9300_10 (AR_CHAN_BASE + 0xd0 - 0x10)
#define AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 (AR_CHAN_BASE + 0xd4 - 0x10)
#define AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 (AR_CHAN_BASE + 0xc0 + 0x8)
#define AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 (AR_CHAN_BASE + 0xc4 + 0x8)
#define AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 (AR_CHAN_BASE + 0xc8 + 0x8)
#define AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 (AR_CHAN_BASE + 0xcc + 0x8)
#define AR_PHY_TX_CRC (AR_CHAN_BASE + 0xa0)
#define AR_PHY_TST_DAC_CONST (AR_CHAN_BASE + 0xa4)
#define AR_PHY_SPUR_REPORT_0 (AR_CHAN_BASE + 0xa8)
#define AR_PHY_CHAN_INFO_TAB_0 (AR_CHAN_BASE + 0x300)
/*
* Channel Field Definitions
*/
#define AR_PHY_TIMING2_USE_FORCE_PPM 0x00001000
#define AR_PHY_TIMING2_FORCE_PPM_VAL 0x00000fff
#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
#define AR_PHY_TIMING3_DSC_MAN_S 17
#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
#define AR_PHY_TIMING3_DSC_EXP_S 13
#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX 0xF000
#define AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX_S 12
#define AR_PHY_TIMING4_DO_CAL 0x10000
#define AR_PHY_TIMING4_ENABLE_PILOT_MASK 0x10000000
#define AR_PHY_TIMING4_ENABLE_PILOT_MASK_S 28
#define AR_PHY_TIMING4_ENABLE_CHAN_MASK 0x20000000
#define AR_PHY_TIMING4_ENABLE_CHAN_MASK_S 29
#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER 0x40000000
#define AR_PHY_TIMING4_ENABLE_SPUR_FILTER_S 30
#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI 0x80000000
#define AR_PHY_TIMING4_ENABLE_SPUR_RSSI_S 31
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
#define AR_PHY_SFCORR_M2COUNT_THR_S 0
#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
#define AR_PHY_SFCORR_M1_THRESH_S 17
#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
#define AR_PHY_SFCORR_M2_THRESH_S 24
#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD 0x10000000
#define AR_PHY_SFCORR_EXT_SPUR_SUBCHANNEL_SD_S 28
#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
#define AR_PHY_EXT_CCA_THRESH62_S 16
#define AR_PHY_EXT_MINCCA_PWR 0x01FF0000
#define AR_PHY_EXT_MINCCA_PWR_S 16
#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE 0x00000001
#define AR_PHY_TIMING5_CYCPWR_THR1_ENABLE_S 0
#define AR_PHY_TIMING5_CYCPWR_THR1A 0x007F0000
#define AR_PHY_TIMING5_CYCPWR_THR1A_S 16
#define AR_PHY_TIMING5_RSSI_THR1A (0x7F << 16)
#define AR_PHY_TIMING5_RSSI_THR1A_S 16
#define AR_PHY_TIMING5_RSSI_THR1A_ENA (0x1 << 15)
#define AR_PHY_RADAR_0_ENA 0x00000001
#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
#define AR_PHY_RADAR_0_INBAND 0x0000003e
#define AR_PHY_RADAR_0_INBAND_S 1
#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
#define AR_PHY_RADAR_0_PRSSI_S 6
#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
#define AR_PHY_RADAR_0_HEIGHT_S 12
#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
#define AR_PHY_RADAR_0_RRSSI_S 18
#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
#define AR_PHY_RADAR_0_FIRPWR_S 24
#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
#define AR_PHY_RADAR_1_MAXLEN_S 0
#define AR_PHY_RADAR_EXT_ENA 0x00004000
#define AR_PHY_RADAR_DC_PWR_THRESH 0x007f8000
#define AR_PHY_RADAR_DC_PWR_THRESH_S 15
#define AR_PHY_RADAR_LB_DC_CAP 0x7f800000
#define AR_PHY_RADAR_LB_DC_CAP_S 23
#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW (0x3f << 6)
#define AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW_S 6
#define AR_PHY_FIND_SIG_LOW_FIRPWR (0x7f << 12)
#define AR_PHY_FIND_SIG_LOW_FIRPWR_S 12
#define AR_PHY_FIND_SIG_LOW_FIRPWR_SIGN_BIT 19
#define AR_PHY_FIND_SIG_LOW_RELSTEP 0x1f
#define AR_PHY_FIND_SIG_LOW_RELSTEP_S 0
#define AR_PHY_FIND_SIG_LOW_RELSTEP_SIGN_BIT 5
#define AR_PHY_CHAN_INFO_TAB_S2_READ 0x00000008
#define AR_PHY_CHAN_INFO_TAB_S2_READ_S 3
#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF 0x0000007F
#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_Q_COFF_S 0
#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF 0x00003F80
#define AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF_S 7
#define AR_PHY_RX_IQCAL_CORR_IQCORR_ENABLE 0x00004000
#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF 0x003f8000
#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF_S 15
#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF 0x1fc00000
#define AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF_S 22
/*
* MRC Register Map
*/
#define AR_MRC_BASE 0x9c00
#define AR_PHY_TIMING_3A (AR_MRC_BASE + 0x0)
#define AR_PHY_LDPC_CNTL1 (AR_MRC_BASE + 0x4)
#define AR_PHY_LDPC_CNTL2 (AR_MRC_BASE + 0x8)
#define AR_PHY_PILOT_SPUR_MASK (AR_MRC_BASE + 0xc)
#define AR_PHY_CHAN_SPUR_MASK (AR_MRC_BASE + 0x10)
#define AR_PHY_SGI_DELTA (AR_MRC_BASE + 0x14)
#define AR_PHY_ML_CNTL_1 (AR_MRC_BASE + 0x18)
#define AR_PHY_ML_CNTL_2 (AR_MRC_BASE + 0x1c)
#define AR_PHY_TST_ADC (AR_MRC_BASE + 0x20)
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A 0x00000FE0
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_IDX_A_S 5
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A 0x1F
#define AR_PHY_PILOT_SPUR_MASK_CF_PILOT_MASK_A_S 0
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A 0x00000FE0
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_IDX_A_S 5
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A 0x1F
#define AR_PHY_CHAN_SPUR_MASK_CF_CHAN_MASK_A_S 0
/*
* MRC Feild Definitions
*/
#define AR_PHY_SGI_DSC_MAN 0x0007FFF0
#define AR_PHY_SGI_DSC_MAN_S 4
#define AR_PHY_SGI_DSC_EXP 0x0000000F
#define AR_PHY_SGI_DSC_EXP_S 0
/*
* BBB Register Map
*/
#define AR_BBB_BASE 0x9d00
/*
* AGC Register Map
*/
#define AR_AGC_BASE 0x9e00
#define AR_PHY_SETTLING (AR_AGC_BASE + 0x0)
#define AR_PHY_FORCEMAX_GAINS_0 (AR_AGC_BASE + 0x4)
#define AR_PHY_GAINS_MINOFF0 (AR_AGC_BASE + 0x8)
#define AR_PHY_DESIRED_SZ (AR_AGC_BASE + 0xc)
#define AR_PHY_FIND_SIG (AR_AGC_BASE + 0x10)
#define AR_PHY_AGC (AR_AGC_BASE + 0x14)
#define AR_PHY_EXT_ATTEN_CTL_0 (AR_AGC_BASE + 0x18)
#define AR_PHY_CCA_0 (AR_AGC_BASE + 0x1c)
#define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20)
#define AR_PHY_RESTART (AR_AGC_BASE + 0x24)
#define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28)
#define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c)
#define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30)
#define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34)
#define AR_PHY_RIFS_SRCH (AR_AGC_BASE + 0x38)
#define AR_PHY_PEAK_DET_CTRL_1 (AR_AGC_BASE + 0x3c)
#define AR_PHY_PEAK_DET_CTRL_2 (AR_AGC_BASE + 0x40)
#define AR_PHY_RX_GAIN_BOUNDS_1 (AR_AGC_BASE + 0x44)
#define AR_PHY_RX_GAIN_BOUNDS_2 (AR_AGC_BASE + 0x48)
#define AR_PHY_RSSI_0 (AR_AGC_BASE + 0x180)
#define AR_PHY_SPUR_CCK_REP0 (AR_AGC_BASE + 0x184)
#define AR_PHY_CCK_DETECT (AR_AGC_BASE + 0x1c0)
#define AR_PHY_DAG_CTRLCCK (AR_AGC_BASE + 0x1c4)
#define AR_PHY_IQCORR_CTRL_CCK (AR_AGC_BASE + 0x1c8)
#define AR_PHY_CCK_SPUR_MIT (AR_AGC_BASE + 0x1cc)
#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR 0x000001fe
#define AR_PHY_CCK_SPUR_MIT_SPUR_RSSI_THR_S 1
#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE 0x60000000
#define AR_PHY_CCK_SPUR_MIT_SPUR_FILTER_TYPE_S 29
#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT 0x00000001
#define AR_PHY_CCK_SPUR_MIT_USE_CCK_SPUR_MIT_S 0
#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ 0x1ffffe00
#define AR_PHY_CCK_SPUR_MIT_CCK_SPUR_FREQ_S 9
#define AR_PHY_RX_OCGAIN (AR_AGC_BASE + 0x200)
#define AR_PHY_CCA_NOM_VAL_9300_2GHZ -110
#define AR_PHY_CCA_NOM_VAL_9300_5GHZ -115
#define AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ -125
#define AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ -125
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ -95
#define AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ -100
/*
* AGC Field Definitions
*/
#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN 0x00FC0000
#define AR_PHY_EXT_ATTEN_CTL_RXTX_MARGIN_S 18
#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN 0x00003C00
#define AR_PHY_EXT_ATTEN_CTL_BSW_MARGIN_S 10
#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN 0x0000001F
#define AR_PHY_EXT_ATTEN_CTL_BSW_ATTEN_S 0
#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN 0x003E0000
#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_MARGIN_S 17
#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN 0x0001F000
#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_MARGIN_S 12
#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB 0x00000FC0
#define AR_PHY_EXT_ATTEN_CTL_XATTEN2_DB_S 6
#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB 0x0000003F
#define AR_PHY_EXT_ATTEN_CTL_XATTEN1_DB_S 0
#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
#define AR_PHY_SETTLING_SWITCH 0x00003F80
#define AR_PHY_SETTLING_SWITCH_S 7
#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
#define AR_PHY_DESIRED_SZ_ADC_S 0
#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
#define AR_PHY_DESIRED_SZ_PGA_S 8
#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
#define AR_PHY_MINCCA_PWR 0x1FF00000
#define AR_PHY_MINCCA_PWR_S 20
#define AR_PHY_CCA_THRESH62 0x0007F000
#define AR_PHY_CCA_THRESH62_S 12
#define AR9280_PHY_MINCCA_PWR 0x1FF00000
#define AR9280_PHY_MINCCA_PWR_S 20
#define AR9280_PHY_CCA_THRESH62 0x000FF000
#define AR9280_PHY_CCA_THRESH62_S 12
#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
#define AR_PHY_EXT_CCA0_THRESH62_S 0
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR_S 9
#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
#define AR_PHY_RIFS_INIT_DELAY 0x3ff0000
#define AR_PHY_AGC_COARSE_LOW 0x00007F80
#define AR_PHY_AGC_COARSE_LOW_S 7
#define AR_PHY_AGC_COARSE_HIGH 0x003F8000
#define AR_PHY_AGC_COARSE_HIGH_S 15
#define AR_PHY_AGC_COARSE_PWR_CONST 0x0000007F
#define AR_PHY_AGC_COARSE_PWR_CONST_S 0
#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
#define AR_PHY_FIND_SIG_FIRSTEP_S 12
#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
#define AR_PHY_FIND_SIG_FIRPWR_S 18
#define AR_PHY_FIND_SIG_FIRPWR_SIGN_BIT 25
#define AR_PHY_FIND_SIG_RELPWR (0x1f << 6)
#define AR_PHY_FIND_SIG_RELPWR_S 6
#define AR_PHY_FIND_SIG_RELPWR_SIGN_BIT 11
#define AR_PHY_FIND_SIG_RELSTEP 0x1f
#define AR_PHY_FIND_SIG_RELSTEP_S 0
#define AR_PHY_FIND_SIG_RELSTEP_SIGN_BIT 5
#define AR_PHY_RESTART_DIV_GC 0x001C0000
#define AR_PHY_RESTART_DIV_GC_S 18
#define AR_PHY_RESTART_ENA 0x01
#define AR_PHY_DC_RESTART_DIS 0x40000000
#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON 0xFF000000
#define AR_PHY_TPC_OLPC_GAIN_DELTA_PAL_ON_S 24
#define AR_PHY_TPC_OLPC_GAIN_DELTA 0x00FF0000
#define AR_PHY_TPC_OLPC_GAIN_DELTA_S 16
#define AR_PHY_TPC_6_ERROR_EST_MODE 0x03000000
#define AR_PHY_TPC_6_ERROR_EST_MODE_S 24
/*
* SM Register Map
*/
#define AR_SM_BASE 0xa200
#define AR_PHY_D2_CHIP_ID (AR_SM_BASE + 0x0)
#define AR_PHY_GEN_CTRL (AR_SM_BASE + 0x4)
#define AR_PHY_MODE (AR_SM_BASE + 0x8)
#define AR_PHY_ACTIVE (AR_SM_BASE + 0xc)
#define AR_PHY_SPUR_MASK_A (AR_SM_BASE + 0x20)
#define AR_PHY_SPUR_MASK_B (AR_SM_BASE + 0x24)
#define AR_PHY_SPECTRAL_SCAN (AR_SM_BASE + 0x28)
#define AR_PHY_RADAR_BW_FILTER (AR_SM_BASE + 0x2c)
#define AR_PHY_SEARCH_START_DELAY (AR_SM_BASE + 0x30)
#define AR_PHY_MAX_RX_LEN (AR_SM_BASE + 0x34)
#define AR_PHY_FRAME_CTL (AR_SM_BASE + 0x38)
#define AR_PHY_RFBUS_REQ (AR_SM_BASE + 0x3c)
#define AR_PHY_RFBUS_GRANT (AR_SM_BASE + 0x40)
#define AR_PHY_RIFS (AR_SM_BASE + 0x44)
#define AR_PHY_RX_CLR_DELAY (AR_SM_BASE + 0x50)
#define AR_PHY_RX_DELAY (AR_SM_BASE + 0x54)
#define AR_PHY_XPA_TIMING_CTL (AR_SM_BASE + 0x64)
#define AR_PHY_MISC_PA_CTL (AR_SM_BASE + 0x80)
#define AR_PHY_SWITCH_CHAIN_0 (AR_SM_BASE + 0x84)
#define AR_PHY_SWITCH_COM (AR_SM_BASE + 0x88)
#define AR_PHY_SWITCH_COM_2 (AR_SM_BASE + 0x8c)
#define AR_PHY_RX_CHAINMASK (AR_SM_BASE + 0xa0)
#define AR_PHY_CAL_CHAINMASK (AR_SM_BASE + 0xc0)
#define AR_PHY_CALMODE (AR_SM_BASE + 0xc8)
#define AR_PHY_FCAL_1 (AR_SM_BASE + 0xcc)
#define AR_PHY_FCAL_2_0 (AR_SM_BASE + 0xd0)
#define AR_PHY_DFT_TONE_CTL_0 (AR_SM_BASE + 0xd4)
#define AR_PHY_CL_CAL_CTL (AR_SM_BASE + 0xd8)
#define AR_PHY_CL_TAB_0 (AR_SM_BASE + 0x100)
#define AR_PHY_SYNTH_CONTROL (AR_SM_BASE + 0x140)
#define AR_PHY_ADDAC_CLK_SEL (AR_SM_BASE + 0x144)
#define AR_PHY_PLL_CTL (AR_SM_BASE + 0x148)
#define AR_PHY_ANALOG_SWAP (AR_SM_BASE + 0x14c)
#define AR_PHY_ADDAC_PARA_CTL (AR_SM_BASE + 0x150)
#define AR_PHY_XPA_CFG (AR_SM_BASE + 0x158)
#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A 0x0001FC00
#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_IDX_A_S 10
#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A 0x3FF
#define AR_PHY_SPUR_MASK_A_CF_PUNC_MASK_A_S 0
#define AR_PHY_TEST (AR_SM_BASE + 0x160)
#define AR_PHY_TEST_BBB_OBS_SEL 0x780000
#define AR_PHY_TEST_BBB_OBS_SEL_S 19
#define AR_PHY_TEST_RX_OBS_SEL_BIT5_S 23
#define AR_PHY_TEST_RX_OBS_SEL_BIT5 (1 << AR_PHY_TEST_RX_OBS_SEL_BIT5_S)
#define AR_PHY_TEST_CHAIN_SEL 0xC0000000
#define AR_PHY_TEST_CHAIN_SEL_S 30
#define AR_PHY_TEST_CTL_STATUS (AR_SM_BASE + 0x164)
#define AR_PHY_TEST_CTL_TSTDAC_EN 0x1
#define AR_PHY_TEST_CTL_TSTDAC_EN_S 0
#define AR_PHY_TEST_CTL_TX_OBS_SEL 0x1C
#define AR_PHY_TEST_CTL_TX_OBS_SEL_S 2
#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL 0x60
#define AR_PHY_TEST_CTL_TX_OBS_MUX_SEL_S 5
#define AR_PHY_TEST_CTL_TSTADC_EN 0x100
#define AR_PHY_TEST_CTL_TSTADC_EN_S 8
#define AR_PHY_TEST_CTL_RX_OBS_SEL 0x3C00
#define AR_PHY_TEST_CTL_RX_OBS_SEL_S 10
#define AR_PHY_TSTDAC (AR_SM_BASE + 0x168)
#define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c)
#define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170)
#define AR_PHY_CHNINFO_NOISEPWR (AR_SM_BASE + 0x174)
#define AR_PHY_CHNINFO_GAINDIFF (AR_SM_BASE + 0x178)
#define AR_PHY_CHNINFO_FINETIM (AR_SM_BASE + 0x17c)
#define AR_PHY_CHAN_INFO_GAIN_0 (AR_SM_BASE + 0x180)
#define AR_PHY_SCRAMBLER_SEED (AR_SM_BASE + 0x190)
#define AR_PHY_CCK_TX_CTRL (AR_SM_BASE + 0x194)
#define AR_PHY_HEAVYCLIP_CTL (AR_SM_BASE + 0x1a4)
#define AR_PHY_HEAVYCLIP_20 (AR_SM_BASE + 0x1a8)
#define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac)
#define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0)
#define AR_PHY_PWRTX_MAX (AR_SM_BASE + 0x1f0)
#define AR_PHY_POWER_TX_SUB (AR_SM_BASE + 0x1f4)
#define AR_PHY_TPC_4_B0 (AR_SM_BASE + 0x204)
#define AR_PHY_TPC_5_B0 (AR_SM_BASE + 0x208)
#define AR_PHY_TPC_6_B0 (AR_SM_BASE + 0x20c)
#define AR_PHY_TPC_11_B0 (AR_SM_BASE + 0x220)
#define AR_PHY_TPC_18 (AR_SM_BASE + 0x23c)
#define AR_PHY_TPC_19 (AR_SM_BASE + 0x240)
#define AR_PHY_TX_FORCED_GAIN (AR_SM_BASE + 0x258)
#define AR_PHY_PDADC_TAB_0 (AR_SM_BASE + 0x280)
#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448)
#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440)
#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c)
#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B0 (AR_SM_BASE + 0x450)
#define AR_PHY_PANIC_WD_STATUS (AR_SM_BASE + 0x5c0)
#define AR_PHY_PANIC_WD_CTL_1 (AR_SM_BASE + 0x5c4)
#define AR_PHY_PANIC_WD_CTL_2 (AR_SM_BASE + 0x5c8)
#define AR_PHY_BT_CTL (AR_SM_BASE + 0x5cc)
#define AR_PHY_ONLY_WARMRESET (AR_SM_BASE + 0x5d0)
#define AR_PHY_ONLY_CTL (AR_SM_BASE + 0x5d4)
#define AR_PHY_ECO_CTRL (AR_SM_BASE + 0x5dc)
#define AR_PHY_BB_THERM_ADC_1 (AR_SM_BASE + 0x248)
#define AR_PHY_65NM_CH0_SYNTH4 0x1608c
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT 0x00000002
#define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S 1
#define AR_PHY_65NM_CH0_SYNTH7 0x16098
#define AR_PHY_65NM_CH0_BIAS1 0x160c0
#define AR_PHY_65NM_CH0_BIAS2 0x160c4
#define AR_PHY_65NM_CH0_BIAS4 0x160cc
#define AR_PHY_65NM_CH0_RXTX4 0x1610c
#define AR_PHY_65NM_CH0_THERM 0x16290
#define AR_PHY_65NM_CH0_THERM_LOCAL 0x80000000
#define AR_PHY_65NM_CH0_THERM_LOCAL_S 31
#define AR_PHY_65NM_CH0_THERM_START 0x20000000
#define AR_PHY_65NM_CH0_THERM_START_S 29
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT 0x0000ff00
#define AR_PHY_65NM_CH0_THERM_SAR_ADC_OUT_S 8
#define AR_PHY_65NM_CH0_RXTX1 0x16100
#define AR_PHY_65NM_CH0_RXTX2 0x16104
#define AR_PHY_65NM_CH1_RXTX1 0x16500
#define AR_PHY_65NM_CH1_RXTX2 0x16504
#define AR_PHY_65NM_CH2_RXTX1 0x16900
#define AR_PHY_65NM_CH2_RXTX2 0x16904
#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT 0x00380000
#define AR_PHY_RX1DB_BIQUAD_LONG_SHIFT_S 19
#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT 0x00c00000
#define AR_PHY_RX6DB_BIQUAD_LONG_SHIFT_S 22
#define AR_PHY_LNAGAIN_LONG_SHIFT 0xe0000000
#define AR_PHY_LNAGAIN_LONG_SHIFT_S 29
#define AR_PHY_MXRGAIN_LONG_SHIFT 0x03000000
#define AR_PHY_MXRGAIN_LONG_SHIFT_S 24
#define AR_PHY_VGAGAIN_LONG_SHIFT 0x1c000000
#define AR_PHY_VGAGAIN_LONG_SHIFT_S 26
#define AR_PHY_SCFIR_GAIN_LONG_SHIFT 0x00000001
#define AR_PHY_SCFIR_GAIN_LONG_SHIFT_S 0
#define AR_PHY_MANRXGAIN_LONG_SHIFT 0x00000002
#define AR_PHY_MANRXGAIN_LONG_SHIFT_S 1
/*
* SM Field Definitions
*/
#define AR_PHY_CL_CAL_ENABLE 0x00000002
#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
#define AR_PHY_ADDAC_PARACTL_OFF_PWDADC 0x00008000
#define AR_PHY_FCAL20_CAP_STATUS_0 0x01f00000
#define AR_PHY_FCAL20_CAP_STATUS_0_S 20
#define AR_PHY_RFBUS_REQ_EN 0x00000001 /* request for RF bus */
#define AR_PHY_RFBUS_GRANT_EN 0x00000001 /* RF bus granted */
#define AR_PHY_GC_TURBO_MODE 0x00000001 /* set turbo mode bits */
#define AR_PHY_GC_TURBO_SHORT 0x00000002 /* set short symbols to turbo mode setting */
#define AR_PHY_GC_DYN2040_EN 0x00000004 /* enable dyn 20/40 mode */
#define AR_PHY_GC_DYN2040_PRI_ONLY 0x00000008 /* dyn 20/40 - primary only */
#define AR_PHY_GC_DYN2040_PRI_CH 0x00000010 /* dyn 20/40 - primary ch offset (0=+10MHz, 1=-10MHz)*/
#define AR_PHY_GC_DYN2040_PRI_CH_S 4
#define AR_PHY_GC_DYN2040_EXT_CH 0x00000020 /* dyn 20/40 - ext ch spacing (0=20MHz/ 1=25MHz) */
#define AR_PHY_GC_HT_EN 0x00000040 /* ht enable */
#define AR_PHY_GC_SHORT_GI_40 0x00000080 /* allow short GI for HT 40 */
#define AR_PHY_GC_WALSH 0x00000100 /* walsh spatial spreading for 2 chains,2 streams TX */
#define AR_PHY_GC_SINGLE_HT_LTF1 0x00000200 /* single length (4us) 1st HT long training symbol */
#define AR_PHY_GC_GF_DETECT_EN 0x00000400 /* enable Green Field detection. Only affects rx, not tx */
#define AR_PHY_GC_ENABLE_DAC_FIFO 0x00000800 /* fifo between bb and dac */
#define AR_PHY_RX_DELAY_DELAY 0x00003FFF /* delay from wakeup to rx ena */
#define AR_PHY_CALMODE_IQ 0x00000000
#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
#define AR_PHY_MODE_OFDM 0x00000000
#define AR_PHY_MODE_CCK 0x00000001
#define AR_PHY_MODE_DYNAMIC 0x00000004
#define AR_PHY_MODE_DYNAMIC_S 2
#define AR_PHY_MODE_HALF 0x00000020
#define AR_PHY_MODE_QUARTER 0x00000040
#define AR_PHY_MAC_CLK_MODE 0x00000080
#define AR_PHY_MODE_DYN_CCK_DISABLE 0x00000100
#define AR_PHY_MODE_SVD_HALF 0x00000200
#define AR_PHY_ACTIVE_EN 0x00000001
#define AR_PHY_ACTIVE_DIS 0x00000000
#define AR_PHY_FORCE_XPA_CFG 0x000000001
#define AR_PHY_FORCE_XPA_CFG_S 0
#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF 0xFF000000
#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF_S 24
#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF 0x00FF0000
#define AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF_S 16
#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON 0x0000FF00
#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON_S 8
#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON 0x000000FF
#define AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON_S 0
#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
#define AR_PHY_TX_END_DATA_START 0x000000FF
#define AR_PHY_TX_END_DATA_START_S 0
#define AR_PHY_TX_END_PA_ON 0x0000FF00
#define AR_PHY_TX_END_PA_ON_S 8
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
#define AR_PHY_TPCGR1_FORCED_DAC_GAIN 0x0000003e
#define AR_PHY_TPCGR1_FORCED_DAC_GAIN_S 1
#define AR_PHY_TPCGR1_FORCE_DAC_GAIN 0x00000001
#define AR_PHY_TXGAIN_FORCE 0x00000001
#define AR_PHY_TXGAIN_FORCED_PADVGNRA 0x00003c00
#define AR_PHY_TXGAIN_FORCED_PADVGNRA_S 10
#define AR_PHY_TXGAIN_FORCED_PADVGNRB 0x0003c000
#define AR_PHY_TXGAIN_FORCED_PADVGNRB_S 14
#define AR_PHY_TXGAIN_FORCED_PADVGNRD 0x00c00000
#define AR_PHY_TXGAIN_FORCED_PADVGNRD_S 22
#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN 0x000003c0
#define AR_PHY_TXGAIN_FORCED_TXMXRGAIN_S 6
#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN 0x0000000e
#define AR_PHY_TXGAIN_FORCED_TXBB1DBGAIN_S 1
#define AR_PHY_POWER_TX_RATE1 0x9934
#define AR_PHY_POWER_TX_RATE2 0x9938
#define AR_PHY_POWER_TX_RATE_MAX 0x993c
#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
#define PHY_AGC_CLR 0x10000000
#define RFSILENT_BB 0x00002000
#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_MASK 0xFFF
#define AR_PHY_CHAN_INFO_GAIN_DIFF_PPM_SIGNED_BIT 0x800
#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x00000001
#define AR_PHY_SPECTRAL_SCAN_ENABLE_S 0
#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002
#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00
#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000
#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24
#define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004
#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000
#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18
#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001
#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0
#define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001
#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE 0x00003fff
#define AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE_S 0
#define AR_PHY_TPC_18_THERM_CAL_VALUE 0xff
#define AR_PHY_TPC_18_THERM_CAL_VALUE_S 0
#define AR_PHY_TPC_19_ALPHA_THERM 0xff
#define AR_PHY_TPC_19_ALPHA_THERM_S 0
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28
#define AR_PHY_BB_THERM_ADC_1_INIT_THERM 0x000000ff
#define AR_PHY_BB_THERM_ADC_1_INIT_THERM_S 0
/*
* Channel 1 Register Map
*/
#define AR_CHAN1_BASE 0xa800
#define AR_PHY_EXT_CCA_1 (AR_CHAN1_BASE + 0x30)
#define AR_PHY_TX_PHASE_RAMP_1 (AR_CHAN1_BASE + 0xd0)
#define AR_PHY_ADC_GAIN_DC_CORR_1 (AR_CHAN1_BASE + 0xd4)
#define AR_PHY_SPUR_REPORT_1 (AR_CHAN1_BASE + 0xa8)
#define AR_PHY_CHAN_INFO_TAB_1 (AR_CHAN1_BASE + 0x300)
#define AR_PHY_RX_IQCAL_CORR_B1 (AR_CHAN1_BASE + 0xdc)
/*
* Channel 1 Field Definitions
*/
#define AR_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
#define AR_PHY_CH1_EXT_MINCCA_PWR_S 16
/*
* AGC 1 Register Map
*/
#define AR_AGC1_BASE 0xae00
#define AR_PHY_FORCEMAX_GAINS_1 (AR_AGC1_BASE + 0x4)
#define AR_PHY_EXT_ATTEN_CTL_1 (AR_AGC1_BASE + 0x18)
#define AR_PHY_CCA_1 (AR_AGC1_BASE + 0x1c)
#define AR_PHY_CCA_CTRL_1 (AR_AGC1_BASE + 0x20)
#define AR_PHY_RSSI_1 (AR_AGC1_BASE + 0x180)
#define AR_PHY_SPUR_CCK_REP_1 (AR_AGC1_BASE + 0x184)
#define AR_PHY_RX_OCGAIN_2 (AR_AGC1_BASE + 0x200)
/*
* AGC 1 Field Definitions
*/
#define AR_PHY_CH1_MINCCA_PWR 0x1FF00000
#define AR_PHY_CH1_MINCCA_PWR_S 20
/*
* SM 1 Register Map
*/
#define AR_SM1_BASE 0xb200
#define AR_PHY_SWITCH_CHAIN_1 (AR_SM1_BASE + 0x84)
#define AR_PHY_FCAL_2_1 (AR_SM1_BASE + 0xd0)
#define AR_PHY_DFT_TONE_CTL_1 (AR_SM1_BASE + 0xd4)
#define AR_PHY_CL_TAB_1 (AR_SM1_BASE + 0x100)
#define AR_PHY_CHAN_INFO_GAIN_1 (AR_SM1_BASE + 0x180)
#define AR_PHY_TPC_4_B1 (AR_SM1_BASE + 0x204)
#define AR_PHY_TPC_5_B1 (AR_SM1_BASE + 0x208)
#define AR_PHY_TPC_6_B1 (AR_SM1_BASE + 0x20c)
#define AR_PHY_TPC_11_B1 (AR_SM1_BASE + 0x220)
#define AR_PHY_PDADC_TAB_1 (AR_SM1_BASE + 0x240)
#define AR_PHY_TX_IQCAL_STATUS_B1 (AR_SM1_BASE + 0x48c)
#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B1 (AR_SM1_BASE + 0x450)
/*
* Channel 2 Register Map
*/
#define AR_CHAN2_BASE 0xb800
#define AR_PHY_EXT_CCA_2 (AR_CHAN2_BASE + 0x30)
#define AR_PHY_TX_PHASE_RAMP_2 (AR_CHAN2_BASE + 0xd0)
#define AR_PHY_ADC_GAIN_DC_CORR_2 (AR_CHAN2_BASE + 0xd4)
#define AR_PHY_SPUR_REPORT_2 (AR_CHAN2_BASE + 0xa8)
#define AR_PHY_CHAN_INFO_TAB_2 (AR_CHAN2_BASE + 0x300)
#define AR_PHY_RX_IQCAL_CORR_B2 (AR_CHAN2_BASE + 0xdc)
/*
* Channel 2 Field Definitions
*/
#define AR_PHY_CH2_EXT_MINCCA_PWR 0x01FF0000
#define AR_PHY_CH2_EXT_MINCCA_PWR_S 16
/*
* AGC 2 Register Map
*/
#define AR_AGC2_BASE 0xbe00
#define AR_PHY_FORCEMAX_GAINS_2 (AR_AGC2_BASE + 0x4)
#define AR_PHY_EXT_ATTEN_CTL_2 (AR_AGC2_BASE + 0x18)
#define AR_PHY_CCA_2 (AR_AGC2_BASE + 0x1c)
#define AR_PHY_CCA_CTRL_2 (AR_AGC2_BASE + 0x20)
#define AR_PHY_RSSI_2 (AR_AGC2_BASE + 0x180)
/*
* AGC 2 Field Definitions
*/
#define AR_PHY_CH2_MINCCA_PWR 0x1FF00000
#define AR_PHY_CH2_MINCCA_PWR_S 20
/*
* SM 2 Register Map
*/
#define AR_SM2_BASE 0xc200
#define AR_PHY_SWITCH_CHAIN_2 (AR_SM2_BASE + 0x84)
#define AR_PHY_FCAL_2_2 (AR_SM2_BASE + 0xd0)
#define AR_PHY_DFT_TONE_CTL_2 (AR_SM2_BASE + 0xd4)
#define AR_PHY_CL_TAB_2 (AR_SM2_BASE + 0x100)
#define AR_PHY_CHAN_INFO_GAIN_2 (AR_SM2_BASE + 0x180)
#define AR_PHY_TPC_4_B2 (AR_SM2_BASE + 0x204)
#define AR_PHY_TPC_5_B2 (AR_SM2_BASE + 0x208)
#define AR_PHY_TPC_6_B2 (AR_SM2_BASE + 0x20c)
#define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220)
#define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240)
#define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c)
#define AR_PHY_TX_IQCAL_CORR_COEFF_01_B2 (AR_SM2_BASE + 0x450)
#define AR_PHY_TX_IQCAL_STATUS_B2_FAILED 0x00000001
/*
* AGC 3 Register Map
*/
#define AR_AGC3_BASE 0xce00
#define AR_PHY_RSSI_3 (AR_AGC3_BASE + 0x180)
/*
* Misc helper defines
*/
#define AR_PHY_CHAIN_OFFSET (AR_CHAN1_BASE - AR_CHAN_BASE)
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (AR_PHY_ADC_GAIN_DC_CORR_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_NEW_ADC_DC_GAIN_CORR_9300_10(_i) (AR_PHY_ADC_GAIN_DC_CORR_0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_SWITCH_CHAIN(_i) (AR_PHY_SWITCH_CHAIN_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_EXT_ATTEN_CTL(_i) (AR_PHY_EXT_ATTEN_CTL_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_RXGAIN(_i) (AR_PHY_FORCEMAX_GAINS_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_TPCRG5(_i) (AR_PHY_TPC_5_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_PDADC_TAB(_i) (AR_PHY_PDADC_TAB_0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_0(_i) (AR_PHY_IQ_ADC_MEAS_0_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_1(_i) (AR_PHY_IQ_ADC_MEAS_1_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_2(_i) (AR_PHY_IQ_ADC_MEAS_2_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_3(_i) (AR_PHY_IQ_ADC_MEAS_3_B0 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_0_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_0_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_1_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_1_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_2_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_2_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_CAL_MEAS_3_9300_10(_i) (AR_PHY_IQ_ADC_MEAS_3_B0_9300_10 + (AR_PHY_CHAIN_OFFSET * (_i)))
#define AR_PHY_BB_PANIC_NON_IDLE_ENABLE 0x00000001
#define AR_PHY_BB_PANIC_IDLE_ENABLE 0x00000002
#define AR_PHY_BB_PANIC_IDLE_MASK 0xFFFF0000
#define AR_PHY_BB_PANIC_NON_IDLE_MASK 0x0000FFFC
#define AR_PHY_BB_PANIC_RST_ENABLE 0x00000002
#define AR_PHY_BB_PANIC_IRQ_ENABLE 0x00000004
#define AR_PHY_BB_PANIC_CNTL2_MASK 0xFFFFFFF9
#define AR_PHY_BB_WD_STATUS 0x00000007
#define AR_PHY_BB_WD_STATUS_S 0
#define AR_PHY_BB_WD_DET_HANG 0x00000008
#define AR_PHY_BB_WD_DET_HANG_S 3
#define AR_PHY_BB_WD_RADAR_SM 0x000000F0
#define AR_PHY_BB_WD_RADAR_SM_S 4
#define AR_PHY_BB_WD_RX_OFDM_SM 0x00000F00
#define AR_PHY_BB_WD_RX_OFDM_SM_S 8
#define AR_PHY_BB_WD_RX_CCK_SM 0x0000F000
#define AR_PHY_BB_WD_RX_CCK_SM_S 12
#define AR_PHY_BB_WD_TX_OFDM_SM 0x000F0000
#define AR_PHY_BB_WD_TX_OFDM_SM_S 16
#define AR_PHY_BB_WD_TX_CCK_SM 0x00F00000
#define AR_PHY_BB_WD_TX_CCK_SM_S 20
#define AR_PHY_BB_WD_AGC_SM 0x0F000000
#define AR_PHY_BB_WD_AGC_SM_S 24
#define AR_PHY_BB_WD_SRCH_SM 0xF0000000
#define AR_PHY_BB_WD_SRCH_SM_S 28
#define AR_PHY_BB_WD_STATUS_CLR 0x00000008
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
#endif /* AR9003_PHY_H */

View File

@ -114,8 +114,10 @@ enum buffer_type {
#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY)
#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY)
#define ATH_TXSTATUS_RING_SIZE 64
struct ath_descdma {
struct ath_desc *dd_desc;
void *dd_desc;
dma_addr_t dd_desc_paddr;
u32 dd_desc_len;
struct ath_buf *dd_bufptr;
@ -123,7 +125,7 @@ struct ath_descdma {
int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
struct list_head *head, const char *name,
int nbuf, int ndesc);
int nbuf, int ndesc, bool is_tx);
void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
struct list_head *head);
@ -188,6 +190,7 @@ enum ATH_AGGR_STATUS {
ATH_AGGR_LIMITED,
};
#define ATH_TXFIFO_DEPTH 8
struct ath_txq {
u32 axq_qnum;
u32 *axq_link;
@ -197,6 +200,10 @@ struct ath_txq {
bool stopped;
bool axq_tx_inprogress;
struct list_head axq_acq;
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
struct list_head txq_fifo_pending;
u8 txq_headidx;
u8 txq_tailidx;
};
#define AGGR_CLEANUP BIT(1)
@ -223,6 +230,12 @@ struct ath_tx {
struct ath_descdma txdma;
};
struct ath_rx_edma {
struct sk_buff_head rx_fifo;
struct sk_buff_head rx_buffers;
u32 rx_fifo_hwsize;
};
struct ath_rx {
u8 defant;
u8 rxotherant;
@ -232,6 +245,8 @@ struct ath_rx {
spinlock_t rxbuflock;
struct list_head rxbuf;
struct ath_descdma rxdma;
struct ath_buf *rx_bufptr;
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
};
int ath_startrecv(struct ath_softc *sc);
@ -240,7 +255,7 @@ void ath_flushrecv(struct ath_softc *sc);
u32 ath_calcrxfilter(struct ath_softc *sc);
int ath_rx_init(struct ath_softc *sc, int nbufs);
void ath_rx_cleanup(struct ath_softc *sc);
int ath_rx_tasklet(struct ath_softc *sc, int flush);
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_setup(struct ath_softc *sc, int haltype);
@ -258,6 +273,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl);
void ath_tx_tasklet(struct ath_softc *sc);
void ath_tx_edma_tasklet(struct ath_softc *sc);
void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
@ -507,6 +523,8 @@ struct ath_softc {
struct ath_beacon_config cur_beacon_conf;
struct delayed_work tx_complete_work;
struct ath_btcoex btcoex;
struct ath_descdma txsdma;
};
struct ath_wiphy {

View File

@ -93,8 +93,6 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
}
ds->ds_data = bf->bf_buf_addr;
sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
@ -109,7 +107,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
/* NB: beacon's BufLen must be a multiple of 4 bytes */
ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
true, true, ds);
true, true, ds, bf->bf_buf_addr,
sc->beacon.beaconq);
memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
series[0].Tries = 1;

File diff suppressed because it is too large Load Diff

View File

@ -19,14 +19,6 @@
#include "hw.h"
extern const struct ath9k_percal_data iq_cal_multi_sample;
extern const struct ath9k_percal_data iq_cal_single_sample;
extern const struct ath9k_percal_data adc_gain_cal_multi_sample;
extern const struct ath9k_percal_data adc_gain_cal_single_sample;
extern const struct ath9k_percal_data adc_dc_cal_multi_sample;
extern const struct ath9k_percal_data adc_dc_cal_single_sample;
extern const struct ath9k_percal_data adc_init_dc_cal;
#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85
#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112
#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118
@ -76,7 +68,8 @@ enum ath9k_cal_types {
ADC_DC_INIT_CAL = 0x1,
ADC_GAIN_CAL = 0x2,
ADC_DC_CAL = 0x4,
IQ_MISMATCH_CAL = 0x8
IQ_MISMATCH_CAL = 0x8,
TEMP_COMP_CAL = 0x10,
};
enum ath9k_cal_state {
@ -122,14 +115,12 @@ struct ath9k_pacal_info{
bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
void ath9k_hw_start_nfcal(struct ath_hw *ah);
void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
int16_t ath9k_hw_getnf(struct ath_hw *ah,
struct ath9k_channel *chan);
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
u8 rxchainmask, bool longcal);
bool ath9k_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan);
void ath9k_hw_reset_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
#endif /* CALIB_H */

View File

@ -20,6 +20,7 @@
#include "../debug.h"
#include "hw.h"
#include "hw-ops.h"
/* Common header for Atheros 802.11n base driver cores */
@ -76,11 +77,12 @@ struct ath_buf {
an aggregate) */
struct ath_buf *bf_next; /* next subframe in the aggregate */
struct sk_buff *bf_mpdu; /* enclosing frame structure */
struct ath_desc *bf_desc; /* virtual addr of desc */
void *bf_desc; /* virtual addr of desc */
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer */
bool bf_stale;
bool bf_isnullfunc;
bool bf_tx_aborted;
u16 bf_flags;
struct ath_buf_state bf_state;
dma_addr_t bf_dmacontext;

View File

@ -180,8 +180,15 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
{
if (status)
sc->debug.stats.istats.total++;
if (status & ATH9K_INT_RX)
sc->debug.stats.istats.rxok++;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
if (status & ATH9K_INT_RXLP)
sc->debug.stats.istats.rxlp++;
if (status & ATH9K_INT_RXHP)
sc->debug.stats.istats.rxhp++;
} else {
if (status & ATH9K_INT_RX)
sc->debug.stats.istats.rxok++;
}
if (status & ATH9K_INT_RXEOL)
sc->debug.stats.istats.rxeol++;
if (status & ATH9K_INT_RXORN)
@ -223,8 +230,15 @@ static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
char buf[512];
unsigned int len = 0;
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp);
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp);
} else {
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RX", sc->debug.stats.istats.rxok);
}
len += snprintf(buf + len, sizeof(buf) - len,
"%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
len += snprintf(buf + len, sizeof(buf) - len,

View File

@ -35,6 +35,8 @@ struct ath_buf;
* struct ath_interrupt_stats - Contains statistics about interrupts
* @total: Total no. of interrupts generated so far
* @rxok: RX with no errors
* @rxlp: RX with low priority RX
* @rxhp: RX with high priority, uapsd only
* @rxeol: RX with no more RXDESC available
* @rxorn: RX FIFO overrun
* @txok: TX completed at the requested rate
@ -55,6 +57,8 @@ struct ath_buf;
struct ath_interrupt_stats {
u32 total;
u32 rxok;
u32 rxlp;
u32 rxhp;
u32 rxeol;
u32 rxorn;
u32 txok;

View File

@ -256,14 +256,13 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah)
{
int status;
if (AR_SREV_9287(ah)) {
ah->eep_map = EEP_MAP_AR9287;
ah->eep_ops = &eep_AR9287_ops;
if (AR_SREV_9300_20_OR_LATER(ah))
ah->eep_ops = &eep_ar9300_ops;
else if (AR_SREV_9287(ah)) {
ah->eep_ops = &eep_ar9287_ops;
} else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
ah->eep_map = EEP_MAP_4KBITS;
ah->eep_ops = &eep_4k_ops;
} else {
ah->eep_map = EEP_MAP_DEFAULT;
ah->eep_ops = &eep_def_ops;
}

View File

@ -19,6 +19,7 @@
#include "../ath.h"
#include <net/cfg80211.h>
#include "ar9003_eeprom.h"
#define AH_USE_EEPROM 0x1
@ -93,7 +94,6 @@
*/
#define AR9285_RDEXT_DEFAULT 0x1F
#define AR_EEPROM_MAC(i) (0x1d+(i))
#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s))
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM))
@ -155,6 +155,7 @@
#define AR5416_BCHAN_UNUSED 0xFF
#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
#define AR5416_MAX_CHAINS 3
#define AR9300_MAX_CHAINS 3
#define AR5416_PWR_TABLE_OFFSET_DB -5
/* Rx gain type values */
@ -249,16 +250,20 @@ enum eeprom_param {
EEP_MINOR_REV,
EEP_TX_MASK,
EEP_RX_MASK,
EEP_FSTCLK_5G,
EEP_RXGAIN_TYPE,
EEP_TXGAIN_TYPE,
EEP_OL_PWRCTRL,
EEP_TXGAIN_TYPE,
EEP_RC_CHAIN_MASK,
EEP_DAC_HPWR_5G,
EEP_FRAC_N_5G,
EEP_DEV_TYPE,
EEP_TEMPSENSE_SLOPE,
EEP_TEMPSENSE_SLOPE_PAL_ON,
EEP_PWR_TABLE_OFFSET
EEP_PWR_TABLE_OFFSET,
EEP_DRIVE_STRENGTH,
EEP_INTERNAL_REGULATOR,
EEP_SWREG
};
enum ar5416_rates {
@ -656,13 +661,6 @@ struct ath9k_country_entry {
u8 iso[3];
};
enum ath9k_eep_map {
EEP_MAP_DEFAULT = 0x0,
EEP_MAP_4KBITS,
EEP_MAP_AR9287,
EEP_MAP_MAX
};
struct eeprom_ops {
int (*check_eeprom)(struct ath_hw *hw);
u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
@ -713,6 +711,8 @@ int ath9k_hw_eeprom_init(struct ath_hw *ah);
extern const struct eeprom_ops eep_def_ops;
extern const struct eeprom_ops eep_4k_ops;
extern const struct eeprom_ops eep_AR9287_ops;
extern const struct eeprom_ops eep_ar9287_ops;
extern const struct eeprom_ops eep_ar9287_ops;
extern const struct eeprom_ops eep_ar9300_ops;
#endif /* EEPROM_H */

View File

@ -15,6 +15,7 @@
*/
#include "hw.h"
#include "ar9002_phy.h"
static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
{
@ -182,11 +183,11 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
switch (param) {
case EEP_NFTHRESH_2:
return pModal->noiseFloorThreshCh[0];
case AR_EEPROM_MAC(0):
case EEP_MAC_LSW:
return pBase->macAddr[0] << 8 | pBase->macAddr[1];
case AR_EEPROM_MAC(1):
case EEP_MAC_MID:
return pBase->macAddr[2] << 8 | pBase->macAddr[3];
case AR_EEPROM_MAC(2):
case EEP_MAC_MSW:
return pBase->macAddr[4] << 8 | pBase->macAddr[5];
case EEP_REG_0:
return pBase->regDmn[0];
@ -453,6 +454,8 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
&tMinCalPower, gainBoundaries,
pdadcValues, numXpdGain);
ENABLE_REGWRITE_BUFFER(ah);
if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
SM(pdGainOverlap_t2,
@ -493,6 +496,9 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
regOffset += 4;
}
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
}
}
@ -758,6 +764,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
}
ENABLE_REGWRITE_BUFFER(ah);
/* OFDM power per rate */
REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
ATH9K_POW_SM(ratesArray[rate18mb], 24)
@ -820,6 +828,9 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
}
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
}
static void ath9k_hw_4k_set_addac(struct ath_hw *ah,

View File

@ -15,6 +15,7 @@
*/
#include "hw.h"
#include "ar9002_phy.h"
static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah)
{
@ -172,11 +173,11 @@ static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah,
switch (param) {
case EEP_NFTHRESH_2:
return pModal->noiseFloorThreshCh[0];
case AR_EEPROM_MAC(0):
case EEP_MAC_LSW:
return pBase->macAddr[0] << 8 | pBase->macAddr[1];
case AR_EEPROM_MAC(1):
case EEP_MAC_MID:
return pBase->macAddr[2] << 8 | pBase->macAddr[3];
case AR_EEPROM_MAC(2):
case EEP_MAC_MSW:
return pBase->macAddr[4] << 8 | pBase->macAddr[5];
case EEP_REG_0:
return pBase->regDmn[0];
@ -1169,7 +1170,7 @@ static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,
#undef EEP_MAP9287_SPURCHAN
}
const struct eeprom_ops eep_AR9287_ops = {
const struct eeprom_ops eep_ar9287_ops = {
.check_eeprom = ath9k_hw_AR9287_check_eeprom,
.get_eeprom = ath9k_hw_AR9287_get_eeprom,
.fill_eeprom = ath9k_hw_AR9287_fill_eeprom,

View File

@ -15,6 +15,7 @@
*/
#include "hw.h"
#include "ar9002_phy.h"
static void ath9k_get_txgain_index(struct ath_hw *ah,
struct ath9k_channel *chan,
@ -222,6 +223,12 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
return -EINVAL;
}
/* Enable fixup for AR_AN_TOP2 if necessary */
if (AR_SREV_9280_10_OR_LATER(ah) &&
(eep->baseEepHeader.version & 0xff) > 0x0a &&
eep->baseEepHeader.pwdclkind == 0)
ah->need_an_top2_fixup = 1;
return 0;
}
@ -237,11 +244,11 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
return pModal[0].noiseFloorThreshCh[0];
case EEP_NFTHRESH_2:
return pModal[1].noiseFloorThreshCh[0];
case AR_EEPROM_MAC(0):
case EEP_MAC_LSW:
return pBase->macAddr[0] << 8 | pBase->macAddr[1];
case AR_EEPROM_MAC(1):
case EEP_MAC_MID:
return pBase->macAddr[2] << 8 | pBase->macAddr[3];
case AR_EEPROM_MAC(2):
case EEP_MAC_MSW:
return pBase->macAddr[4] << 8 | pBase->macAddr[5];
case EEP_REG_0:
return pBase->regDmn[0];

View File

@ -129,6 +129,7 @@ static void hif_usb_tx_cb(struct urb *urb)
TX_STAT_INC(skb_completed);
} else {
dev_kfree_skb_any(skb);
TX_STAT_INC(skb_dropped);
}
}
@ -149,11 +150,15 @@ static void hif_usb_tx_cb(struct urb *urb)
}
}
static inline void ath9k_skb_queue_purge(struct sk_buff_head *list)
static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
struct sk_buff_head *list)
{
struct sk_buff *skb;
while ((skb = __skb_dequeue(list)) != NULL)
while ((skb = __skb_dequeue(list)) != NULL) {
dev_kfree_skb_any(skb);
TX_STAT_INC(skb_dropped);
}
}
/* TX lock has to be taken */
@ -214,7 +219,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
ret = usb_submit_urb(tx_buf->urb, GFP_ATOMIC);
if (ret) {
tx_buf->len = tx_buf->offset = 0;
ath9k_skb_queue_purge(&tx_buf->skb_queue);
ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
__skb_queue_head_init(&tx_buf->skb_queue);
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
hif_dev->tx.tx_buf_cnt++;
@ -281,7 +286,7 @@ static void hif_usb_stop(void *hif_handle, u8 pipe_id)
unsigned long flags;
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
ath9k_skb_queue_purge(&hif_dev->tx.tx_skb_queue);
ath9k_skb_queue_purge(hif_dev, &hif_dev->tx.tx_skb_queue);
hif_dev->tx.tx_skb_cnt = 0;
hif_dev->tx.flags |= HIF_USB_TX_STOP;
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);

View File

@ -124,13 +124,13 @@ struct ath9k_htc_cap_target {
struct ath9k_htc_target_vif {
u8 index;
u8 des_bssid[ETH_ALEN];
enum htc_opmode opmode;
__be32 opmode;
u8 myaddr[ETH_ALEN];
u8 bssid[ETH_ALEN];
u32 flags;
u32 flags_ext;
u16 ps_sta;
u16 rtsthreshold;
__be16 rtsthreshold;
u8 ath_cap;
u8 node;
s8 mcast_rate;
@ -151,7 +151,7 @@ struct ath9k_htc_target_sta {
u8 sta_index;
u8 vif_index;
u8 vif_sta;
u16 flags; /* ATH_HTC_STA_* */
__be16 flags; /* ATH_HTC_STA_* */
u16 htcap;
u8 valid;
u16 capinfo;
@ -191,16 +191,16 @@ struct ath9k_htc_rate {
struct ath9k_htc_target_rate {
u8 sta_index;
u8 isnew;
u32 capflags;
__be32 capflags;
struct ath9k_htc_rate rates;
};
struct ath9k_htc_target_stats {
u32 tx_shortretry;
u32 tx_longretry;
u32 tx_xretries;
u32 ht_txunaggr_xretry;
u32 ht_tx_xretries;
__be32 tx_shortretry;
__be32 tx_longretry;
__be32 tx_xretries;
__be32 ht_txunaggr_xretry;
__be32 ht_tx_xretries;
} __packed;
struct ath9k_htc_vif {
@ -261,6 +261,7 @@ struct ath_tx_stats {
u32 buf_completed;
u32 skb_queued;
u32 skb_completed;
u32 skb_dropped;
};
struct ath_rx_stats {

View File

@ -26,7 +26,8 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv,
enum ath9k_int imask = 0;
int dtimperiod, dtimcount, sleepduration;
int cfpperiod, cfpcount, bmiss_timeout;
u32 nexttbtt = 0, intval, tsftu, htc_imask = 0;
u32 nexttbtt = 0, intval, tsftu;
__be32 htc_imask = 0;
u64 tsf;
int num_beacons, offset, dtim_dec_count, cfp_dec_count;
int ret;
@ -142,7 +143,8 @@ static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
{
struct ath_common *common = ath9k_hw_common(priv->ah);
enum ath9k_int imask = 0;
u32 nexttbtt, intval, htc_imask = 0;
u32 nexttbtt, intval;
__be32 htc_imask = 0;
int ret;
u8 cmd_rsp;
@ -244,25 +246,20 @@ void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
enum nl80211_iftype iftype;
struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
if (vif) {
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
iftype = vif->type;
cur_conf->beacon_interval = bss_conf->beacon_int;
cur_conf->dtim_period = bss_conf->dtim_period;
cur_conf->listen_interval = 1;
cur_conf->dtim_count = 1;
cur_conf->bmiss_timeout =
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
} else
iftype = priv->ah->opmode;
cur_conf->beacon_interval = bss_conf->beacon_int;
if (cur_conf->beacon_interval == 0)
cur_conf->beacon_interval = 100;
switch (iftype) {
cur_conf->dtim_period = bss_conf->dtim_period;
cur_conf->listen_interval = 1;
cur_conf->dtim_count = 1;
cur_conf->bmiss_timeout =
ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
switch (vif->type) {
case NL80211_IFTYPE_STATION:
ath9k_htc_beacon_config_sta(priv, cur_conf);
break;

View File

@ -213,7 +213,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
ath9k_hw_regulatory(priv->ah));
}
static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
@ -235,7 +235,7 @@ static unsigned int ath9k_ioread32(void *hw_priv, u32 reg_offset)
return be32_to_cpu(val);
}
static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
@ -257,9 +257,105 @@ static void ath9k_iowrite32(void *hw_priv, u32 val, u32 reg_offset)
}
}
static void ath9k_regwrite_buffer(void *hw_priv, u32 val, u32 reg_offset)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
u32 rsp_status;
int r;
mutex_lock(&priv->wmi->multi_write_mutex);
/* Store the register/value */
priv->wmi->multi_write[priv->wmi->multi_write_idx].reg =
cpu_to_be32(reg_offset);
priv->wmi->multi_write[priv->wmi->multi_write_idx].val =
cpu_to_be32(val);
priv->wmi->multi_write_idx++;
/* If the buffer is full, send it out. */
if (priv->wmi->multi_write_idx == MAX_CMD_NUMBER) {
r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
(u8 *) &priv->wmi->multi_write,
sizeof(struct register_write) * priv->wmi->multi_write_idx,
(u8 *) &rsp_status, sizeof(rsp_status),
100);
if (unlikely(r)) {
ath_print(common, ATH_DBG_WMI,
"REGISTER WRITE FAILED, multi len: %d\n",
priv->wmi->multi_write_idx);
}
priv->wmi->multi_write_idx = 0;
}
mutex_unlock(&priv->wmi->multi_write_mutex);
}
static void ath9k_regwrite(void *hw_priv, u32 val, u32 reg_offset)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
if (atomic_read(&priv->wmi->mwrite_cnt))
ath9k_regwrite_buffer(hw_priv, val, reg_offset);
else
ath9k_regwrite_single(hw_priv, val, reg_offset);
}
static void ath9k_enable_regwrite_buffer(void *hw_priv)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
atomic_inc(&priv->wmi->mwrite_cnt);
}
static void ath9k_disable_regwrite_buffer(void *hw_priv)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
atomic_dec(&priv->wmi->mwrite_cnt);
}
static void ath9k_regwrite_flush(void *hw_priv)
{
struct ath_hw *ah = (struct ath_hw *) hw_priv;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
u32 rsp_status;
int r;
mutex_lock(&priv->wmi->multi_write_mutex);
if (priv->wmi->multi_write_idx) {
r = ath9k_wmi_cmd(priv->wmi, WMI_REG_WRITE_CMDID,
(u8 *) &priv->wmi->multi_write,
sizeof(struct register_write) * priv->wmi->multi_write_idx,
(u8 *) &rsp_status, sizeof(rsp_status),
100);
if (unlikely(r)) {
ath_print(common, ATH_DBG_WMI,
"REGISTER WRITE FAILED, multi len: %d\n",
priv->wmi->multi_write_idx);
}
priv->wmi->multi_write_idx = 0;
}
mutex_unlock(&priv->wmi->multi_write_mutex);
}
static const struct ath_ops ath9k_common_ops = {
.read = ath9k_ioread32,
.write = ath9k_iowrite32,
.read = ath9k_regread,
.write = ath9k_regwrite,
.enable_write_buffer = ath9k_enable_regwrite_buffer,
.disable_write_buffer = ath9k_disable_regwrite_buffer,
.write_flush = ath9k_regwrite_flush,
};
static void ath_usb_read_cachesize(struct ath_common *common, int *csz)

View File

@ -125,7 +125,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
bool fastcc = true;
struct ieee80211_channel *channel = hw->conf.channel;
enum htc_phymode mode;
u16 htc_mode;
__be16 htc_mode;
u8 cmd_rsp;
int ret;
@ -378,7 +378,7 @@ static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
priv->tgt_rate.sta_index = ista->index;
priv->tgt_rate.isnew = 1;
trate = priv->tgt_rate;
priv->tgt_rate.capflags = caps;
priv->tgt_rate.capflags = cpu_to_be32(caps);
trate.capflags = cpu_to_be32(caps);
WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
@ -426,6 +426,7 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)
struct ath9k_htc_target_rate trate;
struct ath_common *common = ath9k_hw_common(priv->ah);
int ret;
u32 caps = be32_to_cpu(priv->tgt_rate.capflags);
u8 cmd_rsp;
memset(&trate, 0, sizeof(trate));
@ -433,11 +434,12 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)
trate = priv->tgt_rate;
if (is_cw40)
priv->tgt_rate.capflags |= WLAN_RC_40_FLAG;
caps |= WLAN_RC_40_FLAG;
else
priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG;
caps &= ~WLAN_RC_40_FLAG;
trate.capflags = cpu_to_be32(priv->tgt_rate.capflags);
priv->tgt_rate.capflags = cpu_to_be32(caps);
trate.capflags = cpu_to_be32(caps);
WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
if (ret) {
@ -609,6 +611,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len,
"%20s : %10u\n", "SKBs completed",
priv->debug.tx_stats.skb_completed);
len += snprintf(buf + len, sizeof(buf) - len,
"%20s : %10u\n", "SKBs dropped",
priv->debug.tx_stats.skb_dropped);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@ -960,7 +965,6 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
ath9k_unregister_led(&priv->tx_led);
ath9k_unregister_led(&priv->rx_led);
ath9k_unregister_led(&priv->radio_led);
ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
}
void ath9k_init_leds(struct ath9k_htc_priv *priv)
@ -1102,7 +1106,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
struct ath9k_channel *init_channel;
int ret = 0;
enum htc_phymode mode;
u16 htc_mode;
__be16 htc_mode;
u8 cmd_rsp;
ath_print(common, ATH_DBG_CONFIG,
@ -1687,7 +1691,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
spin_unlock_bh(&priv->beacon_lock);
priv->op_flags |= OP_FULL_RESET;
if (priv->op_flags & OP_ASSOCIATED)
ath9k_htc_beacon_config(priv, NULL);
ath9k_htc_beacon_config(priv, priv->vif);
ath_start_ani(priv);
mutex_unlock(&priv->mutex);
ath9k_htc_ps_restore(priv);

View File

@ -530,7 +530,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
}
rx_status->mactime = rxbuf->rxstatus.rs_tstamp;
rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
rx_status->band = hw->conf.channel->band;
rx_status->freq = hw->conf.channel->center_freq;
rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
@ -634,13 +634,8 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
rxstatus = (struct ath_htc_rx_status *)skb->data;
rxstatus->rs_tstamp = be64_to_cpu(rxstatus->rs_tstamp);
rxstatus->rs_datalen = be16_to_cpu(rxstatus->rs_datalen);
rxstatus->evm0 = be32_to_cpu(rxstatus->evm0);
rxstatus->evm1 = be32_to_cpu(rxstatus->evm1);
rxstatus->evm2 = be32_to_cpu(rxstatus->evm2);
if (rxstatus->rs_datalen - (len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
if (be16_to_cpu(rxstatus->rs_datalen) -
(len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
ath_print(common, ATH_DBG_FATAL,
"Corrupted RX data len, dropping "
"(epid: %d, dlen: %d, skblen: %d)\n",

View File

@ -368,7 +368,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
struct htc_frame_hdr *htc_hdr;
enum htc_endpoint_id epid;
struct htc_endpoint *endpoint;
u16 *msg_id;
__be16 *msg_id;
if (!htc_handle || !skb)
return;
@ -388,14 +388,14 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
/* Handle trailer */
if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
if (be32_to_cpu(*(u32 *) skb->data) == 0x00C60000)
if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
/* Move past the Watchdog pattern */
htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
}
/* Get the message ID */
msg_id = (u16 *) ((void *) htc_hdr +
sizeof(struct htc_frame_hdr));
msg_id = (__be16 *) ((void *) htc_hdr +
sizeof(struct htc_frame_hdr));
/* Now process HTC messages */
switch (be16_to_cpu(*msg_id)) {

View File

@ -59,20 +59,20 @@ enum htc_endpoint_id {
struct htc_frame_hdr {
u8 endpoint_id;
u8 flags;
u16 payload_len;
__be16 payload_len;
u8 control[4];
} __packed;
struct htc_ready_msg {
u16 message_id;
u16 credits;
u16 credit_size;
__be16 message_id;
__be16 credits;
__be16 credit_size;
u8 max_endpoints;
u8 pad;
} __packed;
struct htc_config_pipe_msg {
u16 message_id;
__be16 message_id;
u8 pipe_id;
u8 credits;
} __packed;
@ -192,9 +192,9 @@ enum htc_service_group_ids{
#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 8)
struct htc_conn_svc_msg {
u16 msg_id;
u16 service_id;
u16 con_flags;
__be16 msg_id;
__be16 service_id;
__be16 con_flags;
u8 dl_pipeid;
u8 ul_pipeid;
u8 svc_meta_len;
@ -209,17 +209,17 @@ struct htc_conn_svc_msg {
#define HTC_SERVICE_NO_MORE_EP 4
struct htc_conn_svc_rspmsg {
u16 msg_id;
u16 service_id;
__be16 msg_id;
__be16 service_id;
u8 status;
u8 endpoint_id;
u16 max_msg_len;
__be16 max_msg_len;
u8 svc_meta_len;
u8 pad;
} __packed;
struct htc_comp_msg {
u16 msg_id;
__be16 msg_id;
} __packed;
int htc_init(struct htc_target *target);

View File

@ -0,0 +1,280 @@
/*
* Copyright (c) 2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef ATH9K_HW_OPS_H
#define ATH9K_HW_OPS_H
#include "hw.h"
/* Hardware core and driver accessible callbacks */
static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah,
int restore,
int power_off)
{
ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off);
}
static inline void ath9k_hw_rxena(struct ath_hw *ah)
{
ath9k_hw_ops(ah)->rx_enable(ah);
}
static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds,
u32 link)
{
ath9k_hw_ops(ah)->set_desc_link(ds, link);
}
static inline void ath9k_hw_get_desc_link(struct ath_hw *ah, void *ds,
u32 **link)
{
ath9k_hw_ops(ah)->get_desc_link(ds, link);
}
static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
bool longcal)
{
return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
}
static inline bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
{
return ath9k_hw_ops(ah)->get_isr(ah, masked);
}
static inline void ath9k_hw_filltxdesc(struct ath_hw *ah, void *ds, u32 seglen,
bool is_firstseg, bool is_lastseg,
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu)
{
ath9k_hw_ops(ah)->fill_txdesc(ah, ds, seglen, is_firstseg, is_lastseg,
ds0, buf_addr, qcu);
}
static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts)
{
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
}
static inline void ath9k_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u32 keyIx,
enum ath9k_key_type keyType,
u32 flags)
{
ath9k_hw_ops(ah)->set11n_txdesc(ah, ds, pktLen, type, txPower, keyIx,
keyType, flags);
}
static inline void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
ath9k_hw_ops(ah)->set11n_ratescenario(ah, ds, lastds, durUpdateEn,
rtsctsRate, rtsctsDuration, series,
nseries, flags);
}
static inline void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
ath9k_hw_ops(ah)->set11n_aggr_first(ah, ds, aggrLen);
}
static inline void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
u32 numDelims)
{
ath9k_hw_ops(ah)->set11n_aggr_middle(ah, ds, numDelims);
}
static inline void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, void *ds)
{
ath9k_hw_ops(ah)->set11n_aggr_last(ah, ds);
}
static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds)
{
ath9k_hw_ops(ah)->clr11n_aggr(ah, ds);
}
static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds,
u32 burstDuration)
{
ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration);
}
static inline void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, void *ds,
u32 vmf)
{
ath9k_hw_ops(ah)->set11n_virtualmorefrag(ah, ds, vmf);
}
/* Private hardware call ops */
/* PHY ops */
static inline int ath9k_hw_rf_set_freq(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->rf_set_freq(ah, chan);
}
static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah,
struct ath9k_channel *chan)
{
ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan);
}
static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah)
{
if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks)
return 0;
return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah);
}
static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah)
{
if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks)
return;
ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah);
}
static inline bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 modesIndex)
{
if (!ath9k_hw_private_ops(ah)->set_rf_regs)
return true;
return ath9k_hw_private_ops(ah)->set_rf_regs(ah, chan, modesIndex);
}
static inline void ath9k_hw_init_bb(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->init_bb(ah, chan);
}
static inline void ath9k_hw_set_channel_regs(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->set_channel_regs(ah, chan);
}
static inline int ath9k_hw_process_ini(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->process_ini(ah, chan);
}
static inline void ath9k_olc_init(struct ath_hw *ah)
{
if (!ath9k_hw_private_ops(ah)->olc_init)
return;
return ath9k_hw_private_ops(ah)->olc_init(ah);
}
static inline void ath9k_hw_set_rfmode(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->set_rfmode(ah, chan);
}
static inline void ath9k_hw_mark_phy_inactive(struct ath_hw *ah)
{
return ath9k_hw_private_ops(ah)->mark_phy_inactive(ah);
}
static inline void ath9k_hw_set_delta_slope(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->set_delta_slope(ah, chan);
}
static inline bool ath9k_hw_rfbus_req(struct ath_hw *ah)
{
return ath9k_hw_private_ops(ah)->rfbus_req(ah);
}
static inline void ath9k_hw_rfbus_done(struct ath_hw *ah)
{
return ath9k_hw_private_ops(ah)->rfbus_done(ah);
}
static inline void ath9k_enable_rfkill(struct ath_hw *ah)
{
return ath9k_hw_private_ops(ah)->enable_rfkill(ah);
}
static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
{
if (!ath9k_hw_private_ops(ah)->restore_chainmask)
return;
return ath9k_hw_private_ops(ah)->restore_chainmask(ah);
}
static inline void ath9k_hw_set_diversity(struct ath_hw *ah, bool value)
{
return ath9k_hw_private_ops(ah)->set_diversity(ah, value);
}
static inline bool ath9k_hw_ani_control(struct ath_hw *ah,
enum ath9k_ani_cmd cmd, int param)
{
return ath9k_hw_private_ops(ah)->ani_control(ah, cmd, param);
}
static inline void ath9k_hw_do_getnf(struct ath_hw *ah,
int16_t nfarray[NUM_NF_READINGS])
{
ath9k_hw_private_ops(ah)->do_getnf(ah, nfarray);
}
static inline void ath9k_hw_loadnf(struct ath_hw *ah,
struct ath9k_channel *chan)
{
ath9k_hw_private_ops(ah)->loadnf(ah, chan);
}
static inline bool ath9k_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->init_cal(ah, chan);
}
static inline void ath9k_hw_setup_calibration(struct ath_hw *ah,
struct ath9k_cal_list *currCal)
{
ath9k_hw_private_ops(ah)->setup_calibration(ah, currCal);
}
static inline bool ath9k_hw_iscal_supported(struct ath_hw *ah,
enum ath9k_cal_types calType)
{
return ath9k_hw_private_ops(ah)->iscal_supported(ah, calType);
}
#endif /* ATH9K_HW_OPS_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008-2009 Atheros Communications Inc.
* Copyright (c) 2008-2010 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@ -41,6 +41,9 @@
#define AR9280_DEVID_PCIE 0x002a
#define AR9285_DEVID_PCIE 0x002b
#define AR2427_DEVID_PCIE 0x002c
#define AR9287_DEVID_PCI 0x002d
#define AR9287_DEVID_PCIE 0x002e
#define AR9300_DEVID_PCIE 0x0030
#define AR5416_AR9100_DEVID 0x000b
@ -48,9 +51,6 @@
#define AR_SUBVENDOR_ID_NEW_A 0x7065
#define AR5416_MAGIC 0x19641014
#define AR5416_DEVID_AR9287_PCI 0x002D
#define AR5416_DEVID_AR9287_PCIE 0x002E
#define AR9280_COEX2WIRE_SUBSYSID 0x309b
#define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa
#define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab
@ -68,6 +68,24 @@
#define REG_READ(_ah, _reg) \
ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
#define ENABLE_REGWRITE_BUFFER(_ah) \
do { \
if (AR_SREV_9271(_ah)) \
ath9k_hw_common(_ah)->ops->enable_write_buffer((_ah)); \
} while (0)
#define DISABLE_REGWRITE_BUFFER(_ah) \
do { \
if (AR_SREV_9271(_ah)) \
ath9k_hw_common(_ah)->ops->disable_write_buffer((_ah)); \
} while (0)
#define REGWRITE_BUFFER_FLUSH(_ah) \
do { \
if (AR_SREV_9271(_ah)) \
ath9k_hw_common(_ah)->ops->write_flush((_ah)); \
} while (0)
#define SM(_v, _f) (((_v) << _f##_S) & _f)
#define MS(_v, _f) (((_v) & _f) >> _f##_S)
#define REG_RMW(_a, _r, _set, _clr) \
@ -75,6 +93,8 @@
#define REG_RMW_FIELD(_a, _r, _f, _v) \
REG_WRITE(_a, _r, \
(REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f))
#define REG_READ_FIELD(_a, _r, _f) \
(((REG_READ(_a, _r) & _f) >> _f##_S))
#define REG_SET_BIT(_a, _r, _f) \
REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
#define REG_CLR_BIT(_a, _r, _f) \
@ -135,6 +155,16 @@
#define TU_TO_USEC(_tu) ((_tu) << 10)
#define ATH9K_HW_RX_HP_QDEPTH 16
#define ATH9K_HW_RX_LP_QDEPTH 128
enum ath_ini_subsys {
ATH_INI_PRE = 0,
ATH_INI_CORE,
ATH_INI_POST,
ATH_INI_NUM_SPLIT,
};
enum wireless_mode {
ATH9K_MODE_11A = 0,
ATH9K_MODE_11G,
@ -165,13 +195,15 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_ENHANCEDPM = BIT(14),
ATH9K_HW_CAP_AUTOSLEEP = BIT(15),
ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16),
ATH9K_HW_CAP_EDMA = BIT(17),
ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18),
ATH9K_HW_CAP_LDPC = BIT(19),
};
enum ath9k_capability_type {
ATH9K_CAP_CIPHER = 0,
ATH9K_CAP_TKIP_MIC,
ATH9K_CAP_TKIP_SPLIT,
ATH9K_CAP_DIVERSITY,
ATH9K_CAP_TXPOW,
ATH9K_CAP_MCAST_KEYSRCH,
ATH9K_CAP_DS
@ -192,6 +224,11 @@ struct ath9k_hw_capabilities {
u8 num_gpio_pins;
u8 num_antcfg_2ghz;
u8 num_antcfg_5ghz;
u8 rx_hp_qdepth;
u8 rx_lp_qdepth;
u8 rx_status_len;
u8 tx_desc_len;
u8 txs_len;
};
struct ath9k_ops_config {
@ -212,6 +249,7 @@ struct ath9k_ops_config {
u32 enable_ani;
int serialize_regmode;
bool rx_intr_mitigation;
bool tx_intr_mitigation;
#define SPUR_DISABLE 0
#define SPUR_ENABLE_IOCTL 1
#define SPUR_ENABLE_EEPROM 2
@ -231,6 +269,8 @@ struct ath9k_ops_config {
enum ath9k_int {
ATH9K_INT_RX = 0x00000001,
ATH9K_INT_RXDESC = 0x00000002,
ATH9K_INT_RXHP = 0x00000001,
ATH9K_INT_RXLP = 0x00000002,
ATH9K_INT_RXNOFRM = 0x00000008,
ATH9K_INT_RXEOL = 0x00000010,
ATH9K_INT_RXORN = 0x00000020,
@ -363,6 +403,12 @@ enum ser_reg_mode {
SER_REG_MODE_AUTO = 2,
};
enum ath9k_rx_qtype {
ATH9K_RX_QUEUE_HP,
ATH9K_RX_QUEUE_LP,
ATH9K_RX_QUEUE_MAX,
};
struct ath9k_beacon_state {
u32 bs_nexttbtt;
u32 bs_nextdtim;
@ -440,6 +486,124 @@ struct ath_gen_timer_table {
} timer_mask;
};
/**
* struct ath_hw_private_ops - callbacks used internally by hardware code
*
* This structure contains private callbacks designed to only be used internally
* by the hardware core.
*
* @init_cal_settings: setup types of calibrations supported
* @init_cal: starts actual calibration
*
* @init_mode_regs: Initializes mode registers
* @init_mode_gain_regs: Initialize TX/RX gain registers
* @macversion_supported: If this specific mac revision is supported
*
* @rf_set_freq: change frequency
* @spur_mitigate_freq: spur mitigation
* @rf_alloc_ext_banks:
* @rf_free_ext_banks:
* @set_rf_regs:
* @compute_pll_control: compute the PLL control value to use for
* AR_RTC_PLL_CONTROL for a given channel
* @setup_calibration: set up calibration
* @iscal_supported: used to query if a type of calibration is supported
* @loadnf: load noise floor read from each chain on the CCA registers
*/
struct ath_hw_private_ops {
/* Calibration ops */
void (*init_cal_settings)(struct ath_hw *ah);
bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);
void (*init_mode_regs)(struct ath_hw *ah);
void (*init_mode_gain_regs)(struct ath_hw *ah);
bool (*macversion_supported)(u32 macversion);
void (*setup_calibration)(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
bool (*iscal_supported)(struct ath_hw *ah,
enum ath9k_cal_types calType);
/* PHY ops */
int (*rf_set_freq)(struct ath_hw *ah,
struct ath9k_channel *chan);
void (*spur_mitigate_freq)(struct ath_hw *ah,
struct ath9k_channel *chan);
int (*rf_alloc_ext_banks)(struct ath_hw *ah);
void (*rf_free_ext_banks)(struct ath_hw *ah);
bool (*set_rf_regs)(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 modesIndex);
void (*set_channel_regs)(struct ath_hw *ah, struct ath9k_channel *chan);
void (*init_bb)(struct ath_hw *ah,
struct ath9k_channel *chan);
int (*process_ini)(struct ath_hw *ah, struct ath9k_channel *chan);
void (*olc_init)(struct ath_hw *ah);
void (*set_rfmode)(struct ath_hw *ah, struct ath9k_channel *chan);
void (*mark_phy_inactive)(struct ath_hw *ah);
void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan);
bool (*rfbus_req)(struct ath_hw *ah);
void (*rfbus_done)(struct ath_hw *ah);
void (*enable_rfkill)(struct ath_hw *ah);
void (*restore_chainmask)(struct ath_hw *ah);
void (*set_diversity)(struct ath_hw *ah, bool value);
u32 (*compute_pll_control)(struct ath_hw *ah,
struct ath9k_channel *chan);
bool (*ani_control)(struct ath_hw *ah, enum ath9k_ani_cmd cmd,
int param);
void (*do_getnf)(struct ath_hw *ah, int16_t nfarray[NUM_NF_READINGS]);
void (*loadnf)(struct ath_hw *ah, struct ath9k_channel *chan);
};
/**
* struct ath_hw_ops - callbacks used by hardware code and driver code
*
* This structure contains callbacks designed to to be used internally by
* hardware code and also by the lower level driver.
*
* @config_pci_powersave:
* @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
*/
struct ath_hw_ops {
void (*config_pci_powersave)(struct ath_hw *ah,
int restore,
int power_off);
void (*rx_enable)(struct ath_hw *ah);
void (*set_desc_link)(void *ds, u32 link);
void (*get_desc_link)(void *ds, u32 **link);
bool (*calibrate)(struct ath_hw *ah,
struct ath9k_channel *chan,
u8 rxchainmask,
bool longcal);
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked);
void (*fill_txdesc)(struct ath_hw *ah, void *ds, u32 seglen,
bool is_firstseg, bool is_is_lastseg,
const void *ds0, dma_addr_t buf_addr,
unsigned int qcu);
int (*proc_txdesc)(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts);
void (*set11n_txdesc)(struct ath_hw *ah, void *ds,
u32 pktLen, enum ath9k_pkt_type type,
u32 txPower, u32 keyIx,
enum ath9k_key_type keyType,
u32 flags);
void (*set11n_ratescenario)(struct ath_hw *ah, void *ds,
void *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags);
void (*set11n_aggr_first)(struct ath_hw *ah, void *ds,
u32 aggrLen);
void (*set11n_aggr_middle)(struct ath_hw *ah, void *ds,
u32 numDelims);
void (*set11n_aggr_last)(struct ath_hw *ah, void *ds);
void (*clr11n_aggr)(struct ath_hw *ah, void *ds);
void (*set11n_burstduration)(struct ath_hw *ah, void *ds,
u32 burstDuration);
void (*set11n_virtualmorefrag)(struct ath_hw *ah, void *ds,
u32 vmf);
};
struct ath_hw {
struct ieee80211_hw *hw;
struct ath_common common;
@ -453,14 +617,18 @@ struct ath_hw {
struct ar5416_eeprom_def def;
struct ar5416_eeprom_4k map4k;
struct ar9287_eeprom map9287;
struct ar9300_eeprom ar9300_eep;
} eeprom;
const struct eeprom_ops *eep_ops;
enum ath9k_eep_map eep_map;
bool sw_mgmt_crypto;
bool is_pciexpress;
bool need_an_top2_fixup;
u16 tx_trig_level;
s16 nf_2g_max;
s16 nf_2g_min;
s16 nf_5g_max;
s16 nf_5g_min;
u16 rfsilent;
u32 rfkill_gpio;
u32 rfkill_polarity;
@ -493,6 +661,7 @@ struct ath_hw {
struct ath9k_cal_list adcgain_caldata;
struct ath9k_cal_list adcdc_calinitdata;
struct ath9k_cal_list adcdc_caldata;
struct ath9k_cal_list tempCompCalData;
struct ath9k_cal_list *cal_list;
struct ath9k_cal_list *cal_list_last;
struct ath9k_cal_list *cal_list_curr;
@ -533,12 +702,10 @@ struct ath_hw {
DONT_USE_32KHZ,
} enable_32kHz_clock;
/* Callback for radio frequency change */
int (*ath9k_hw_rf_set_freq)(struct ath_hw *ah, struct ath9k_channel *chan);
/* Callback for baseband spur frequency */
void (*ath9k_hw_spur_mitigate_freq)(struct ath_hw *ah,
struct ath9k_channel *chan);
/* Private to hardware code */
struct ath_hw_private_ops private_ops;
/* Accessed by the lower level driver */
struct ath_hw_ops ops;
/* Used to program the radio on non single-chip devices */
u32 *analogBank0Data;
@ -592,6 +759,7 @@ struct ath_hw {
struct ar5416IniArray iniBank7;
struct ar5416IniArray iniAddac;
struct ar5416IniArray iniPcieSerdes;
struct ar5416IniArray iniPcieSerdesLowPower;
struct ar5416IniArray iniModesAdditional;
struct ar5416IniArray iniModesRxGain;
struct ar5416IniArray iniModesTxGain;
@ -604,9 +772,21 @@ struct ath_hw {
struct ar5416IniArray iniModes_high_power_tx_gain_9271;
struct ar5416IniArray iniModes_normal_power_tx_gain_9271;
struct ar5416IniArray iniMac[ATH_INI_NUM_SPLIT];
struct ar5416IniArray iniBB[ATH_INI_NUM_SPLIT];
struct ar5416IniArray iniRadio[ATH_INI_NUM_SPLIT];
struct ar5416IniArray iniSOC[ATH_INI_NUM_SPLIT];
u32 intr_gen_timer_trigger;
u32 intr_gen_timer_thresh;
struct ath_gen_timer_table hw_gen_timers;
struct ar9003_txs *ts_ring;
void *ts_start;
u32 ts_paddr_start;
u32 ts_paddr_end;
u16 ts_tail;
u8 ts_size;
};
static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@ -619,6 +799,16 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
return &(ath9k_hw_common(ah)->regulatory);
}
static inline struct ath_hw_private_ops *ath9k_hw_private_ops(struct ath_hw *ah)
{
return &ah->private_ops;
}
static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
{
return &ah->ops;
}
/* Initialization, Detach, Reset */
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_deinit(struct ath_hw *ah);
@ -630,6 +820,7 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
u32 capability, u32 *result);
bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
u32 capability, u32 setting, int *status);
u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
/* Key Cache Management */
bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
@ -678,16 +869,10 @@ void ath9k_hw_set11nmac2040(struct ath_hw *ah);
void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
const struct ath9k_beacon_state *bs);
bool ath9k_hw_check_alive(struct ath_hw *ah);
bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode);
void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah);
bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
/* Generic hw timer primitives */
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *),
@ -709,6 +894,36 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
/* HTC */
void ath9k_hw_htc_resetinit(struct ath_hw *ah);
/* PHY */
void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, u32 coef_scaled,
u32 *coef_mantissa, u32 *coef_exponent);
/*
* Code Specific to AR5008, AR9001 or AR9002,
* we stuff these here to avoid callbacks for AR9003.
*/
void ar9002_hw_cck_chan14_spread(struct ath_hw *ah);
int ar9002_hw_rf_claim(struct ath_hw *ah);
void ar9002_hw_enable_async_fifo(struct ath_hw *ah);
void ar9002_hw_enable_wep_aggregation(struct ath_hw *ah);
/*
* Code specifric to AR9003, we stuff these here to avoid callbacks
* for older families
*/
void ar9003_hw_set_nf_limits(struct ath_hw *ah);
/* Hardware family op attach helpers */
void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
void ar9002_hw_attach_phy_ops(struct ath_hw *ah);
void ar9003_hw_attach_phy_ops(struct ath_hw *ah);
void ar9002_hw_attach_calib_ops(struct ath_hw *ah);
void ar9003_hw_attach_calib_ops(struct ath_hw *ah);
void ar9002_hw_attach_ops(struct ath_hw *ah);
void ar9003_hw_attach_ops(struct ath_hw *ah);
#define ATH_PCIE_CAP_LINK_CTRL 0x70
#define ATH_PCIE_CAP_LINK_L0S 1
#define ATH_PCIE_CAP_LINK_L1 2

View File

@ -175,6 +175,18 @@ static const struct ath_ops ath9k_common_ops = {
.write = ath9k_iowrite32,
};
static int count_streams(unsigned int chainmask, int max)
{
int streams = 0;
do {
if (++streams == max)
break;
} while ((chainmask = chainmask & (chainmask - 1)));
return streams;
}
/**************************/
/* Initialization */
/**************************/
@ -182,8 +194,10 @@ static const struct ath_ops ath9k_common_ops = {
static void setup_ht_cap(struct ath_softc *sc,
struct ieee80211_sta_ht_cap *ht_info)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
u8 tx_streams, rx_streams;
int i, max_streams;
ht_info->ht_supported = true;
ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
@ -191,28 +205,40 @@ static void setup_ht_cap(struct ath_softc *sc,
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_LDPC)
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
if (AR_SREV_9300_20_OR_LATER(ah))
max_streams = 3;
else
max_streams = 2;
if (AR_SREV_9280_10_OR_LATER(ah)) {
if (max_streams >= 2)
ht_info->cap |= IEEE80211_HT_CAP_TX_STBC;
ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
}
/* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
tx_streams = !(common->tx_chainmask & (common->tx_chainmask - 1)) ?
1 : 2;
rx_streams = !(common->rx_chainmask & (common->rx_chainmask - 1)) ?
1 : 2;
tx_streams = count_streams(common->tx_chainmask, max_streams);
rx_streams = count_streams(common->rx_chainmask, max_streams);
ath_print(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
tx_streams, rx_streams);
if (tx_streams != rx_streams) {
ath_print(common, ATH_DBG_CONFIG,
"TX streams %d, RX streams: %d\n",
tx_streams, rx_streams);
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
ht_info->mcs.tx_params |= ((tx_streams - 1) <<
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
}
ht_info->mcs.rx_mask[0] = 0xff;
if (rx_streams >= 2)
ht_info->mcs.rx_mask[1] = 0xff;
for (i = 0; i < rx_streams; i++)
ht_info->mcs.rx_mask[i] = 0xff;
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
}
@ -235,31 +261,37 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
*/
int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
struct list_head *head, const char *name,
int nbuf, int ndesc)
int nbuf, int ndesc, bool is_tx)
{
#define DS2PHYS(_dd, _ds) \
((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_desc *ds;
u8 *ds;
struct ath_buf *bf;
int i, bsize, error;
int i, bsize, error, desc_len;
ath_print(common, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
name, nbuf, ndesc);
INIT_LIST_HEAD(head);
if (is_tx)
desc_len = sc->sc_ah->caps.tx_desc_len;
else
desc_len = sizeof(struct ath_desc);
/* ath_desc must be a multiple of DWORDs */
if ((sizeof(struct ath_desc) % 4) != 0) {
if ((desc_len % 4) != 0) {
ath_print(common, ATH_DBG_FATAL,
"ath_desc not DWORD aligned\n");
BUG_ON((sizeof(struct ath_desc) % 4) != 0);
BUG_ON((desc_len % 4) != 0);
error = -ENOMEM;
goto fail;
}
dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
dd->dd_desc_len = desc_len * nbuf * ndesc;
/*
* Need additional DMA memory because we can't use
@ -272,7 +304,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
u32 dma_len;
while (ndesc_skipped) {
dma_len = ndesc_skipped * sizeof(struct ath_desc);
dma_len = ndesc_skipped * desc_len;
dd->dd_desc_len += dma_len;
ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
@ -286,7 +318,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
error = -ENOMEM;
goto fail;
}
ds = dd->dd_desc;
ds = (u8 *) dd->dd_desc;
ath_print(common, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
name, ds, (u32) dd->dd_desc_len,
ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
@ -300,7 +332,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
}
dd->dd_bufptr = bf;
for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
bf->bf_desc = ds;
bf->bf_daddr = DS2PHYS(dd, ds);
@ -316,7 +348,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
((caddr_t) dd->dd_desc +
dd->dd_desc_len));
ds += ndesc;
ds += (desc_len * ndesc);
bf->bf_desc = ds;
bf->bf_daddr = DS2PHYS(dd, ds);
}
@ -514,7 +546,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
common->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
common->rx_chainmask = sc->sc_ah->caps.rx_chainmask;
ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
ath9k_hw_set_diversity(sc->sc_ah, true);
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK)
@ -568,13 +600,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
ath_read_cachesize(common, &csz);
common->cachelsz = csz << 2; /* convert to bytes */
/* Initializes the hardware for all supported chipsets */
ret = ath9k_hw_init(ah);
if (ret) {
ath_print(common, ATH_DBG_FATAL,
"Unable to initialize hardware; "
"initialization status: %d\n", ret);
if (ret)
goto err_hw;
}
ret = ath9k_init_debug(ah);
if (ret) {

View File

@ -25,6 +25,8 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask,
ah->txurn_interrupt_mask);
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_IMR_S0,
SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK)
| SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC));
@ -35,6 +37,9 @@ static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah,
ah->imrs2_reg &= ~AR_IMR_S2_QCU_TXURN;
ah->imrs2_reg |= (ah->txurn_interrupt_mask & AR_IMR_S2_QCU_TXURN);
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
}
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
@ -57,6 +62,18 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
}
EXPORT_SYMBOL(ath9k_hw_txstart);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
}
EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
{
u32 npend;
@ -207,281 +224,6 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
}
EXPORT_SYMBOL(ath9k_hw_stoptxdma);
void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 segLen, bool firstSeg,
bool lastSeg, const struct ath_desc *ds0)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if (firstSeg) {
ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
} else if (lastSeg) {
ads->ds_ctl0 = 0;
ads->ds_ctl1 = segLen;
ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
} else {
ads->ds_ctl0 = 0;
ads->ds_ctl1 = segLen | AR_TxMore;
ads->ds_ctl2 = 0;
ads->ds_ctl3 = 0;
}
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
}
EXPORT_SYMBOL(ath9k_hw_filltxdesc);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
}
EXPORT_SYMBOL(ath9k_hw_cleartxdesc);
int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
struct ath_tx_status *ts)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if ((ads->ds_txstatus9 & AR_TxDone) == 0)
return -EINPROGRESS;
ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
ts->ts_tstamp = ads->AR_SendTimestamp;
ts->ts_status = 0;
ts->ts_flags = 0;
if (ads->ds_txstatus1 & AR_FrmXmitOK)
ts->ts_status |= ATH9K_TX_ACKED;
if (ads->ds_txstatus1 & AR_ExcessiveRetries)
ts->ts_status |= ATH9K_TXERR_XRETRY;
if (ads->ds_txstatus1 & AR_Filtered)
ts->ts_status |= ATH9K_TXERR_FILT;
if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
ts->ts_status |= ATH9K_TXERR_FIFO;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus9 & AR_TxOpExceeded)
ts->ts_status |= ATH9K_TXERR_XTXOP;
if (ads->ds_txstatus1 & AR_TxTimerExpired)
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
if (ads->ds_txstatus1 & AR_DescCfgErr)
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
ath9k_hw_updatetxtriglevel(ah, true);
}
if (ads->ds_txstatus0 & AR_TxBaStatus) {
ts->ts_flags |= ATH9K_TX_BA;
ts->ba_low = ads->AR_BaBitmapLow;
ts->ba_high = ads->AR_BaBitmapHigh;
}
ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
switch (ts->ts_rateindex) {
case 0:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
break;
case 1:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
break;
case 2:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
break;
case 3:
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
break;
}
ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
ts->evm0 = ads->AR_TxEVM0;
ts->evm1 = ads->AR_TxEVM1;
ts->evm2 = ads->AR_TxEVM2;
ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
ts->ts_antenna = 0;
return 0;
}
EXPORT_SYMBOL(ath9k_hw_txprocdesc);
void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
txPower += ah->txpower_indexoffset;
if (txPower > 63)
txPower = 63;
ads->ds_ctl0 = (pktLen & AR_FrameLen)
| (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(txPower, AR_XmitPower)
| (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
| (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
ads->ds_ctl1 =
(keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
| SM(type, AR_FrameType)
| (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
| (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
| (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
ads->ds_ctl6 = SM(keyType, AR_EncrType);
if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
ads->ds_ctl8 = 0;
ads->ds_ctl9 = 0;
ads->ds_ctl10 = 0;
ads->ds_ctl11 = 0;
}
}
EXPORT_SYMBOL(ath9k_hw_set11n_txdesc);
void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
struct ath_desc *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
struct ar5416_desc *last_ads = AR5416DESC(lastds);
u32 ds_ctl0;
if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
ds_ctl0 = ads->ds_ctl0;
if (flags & ATH9K_TXDESC_RTSENA) {
ds_ctl0 &= ~AR_CTSEnable;
ds_ctl0 |= AR_RTSEnable;
} else {
ds_ctl0 &= ~AR_RTSEnable;
ds_ctl0 |= AR_CTSEnable;
}
ads->ds_ctl0 = ds_ctl0;
} else {
ads->ds_ctl0 =
(ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
}
ads->ds_ctl2 = set11nTries(series, 0)
| set11nTries(series, 1)
| set11nTries(series, 2)
| set11nTries(series, 3)
| (durUpdateEn ? AR_DurUpdateEna : 0)
| SM(0, AR_BurstDur);
ads->ds_ctl3 = set11nRate(series, 0)
| set11nRate(series, 1)
| set11nRate(series, 2)
| set11nRate(series, 3);
ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
| set11nPktDurRTSCTS(series, 1);
ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
| set11nPktDurRTSCTS(series, 3);
ads->ds_ctl7 = set11nRateFlags(series, 0)
| set11nRateFlags(series, 1)
| set11nRateFlags(series, 2)
| set11nRateFlags(series, 3)
| SM(rtsctsRate, AR_RTSCTSRate);
last_ads->ds_ctl2 = ads->ds_ctl2;
last_ads->ds_ctl3 = ads->ds_ctl3;
}
EXPORT_SYMBOL(ath9k_hw_set11n_ratescenario);
void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
u32 aggrLen)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
ads->ds_ctl6 &= ~AR_AggrLen;
ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
}
EXPORT_SYMBOL(ath9k_hw_set11n_aggr_first);
void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
u32 numDelims)
{
struct ar5416_desc *ads = AR5416DESC(ds);
unsigned int ctl6;
ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
ctl6 = ads->ds_ctl6;
ctl6 &= ~AR_PadDelim;
ctl6 |= SM(numDelims, AR_PadDelim);
ads->ds_ctl6 = ctl6;
}
EXPORT_SYMBOL(ath9k_hw_set11n_aggr_middle);
void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 |= AR_IsAggr;
ads->ds_ctl1 &= ~AR_MoreAggr;
ads->ds_ctl6 &= ~AR_PadDelim;
}
EXPORT_SYMBOL(ath9k_hw_set11n_aggr_last);
void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
}
EXPORT_SYMBOL(ath9k_hw_clr11n_aggr);
void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
u32 burstDuration)
{
struct ar5416_desc *ads = AR5416DESC(ds);
ads->ds_ctl2 &= ~AR_BurstDur;
ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
}
EXPORT_SYMBOL(ath9k_hw_set11n_burstduration);
void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
u32 vmf)
{
struct ar5416_desc *ads = AR5416DESC(ds);
if (vmf)
ads->ds_ctl0 |= AR_VirtMoreFrag;
else
ads->ds_ctl0 &= ~AR_VirtMoreFrag;
}
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
{
*txqs &= ah->intr_txqs;
@ -733,6 +475,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
} else
cwMin = qi->tqi_cwmin;
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_DLCL_IFS(q),
SM(cwMin, AR_D_LCL_IFS_CWMIN) |
SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
@ -747,6 +491,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
REG_WRITE(ah, AR_DMISC(q),
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
REGWRITE_BUFFER_FLUSH(ah);
if (qi->tqi_cbrPeriod) {
REG_WRITE(ah, AR_QCBRCFG(q),
SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
@ -762,6 +508,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
AR_Q_RDYTIMECFG_EN);
}
REGWRITE_BUFFER_FLUSH(ah);
REG_WRITE(ah, AR_DCHNTIME(q),
SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
(qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
@ -779,6 +527,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
REG_READ(ah, AR_DMISC(q)) |
AR_D_MISC_POST_FR_BKOFF_DIS);
}
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
REG_WRITE(ah, AR_DMISC(q),
REG_READ(ah, AR_DMISC(q)) |
@ -786,6 +538,8 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
}
switch (qi->tqi_type) {
case ATH9K_TX_QUEUE_BEACON:
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
| AR_Q_MISC_FSP_DBA_GATED
| AR_Q_MISC_BEACON_USE
@ -796,8 +550,20 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
| AR_D_MISC_BEACON_USE
| AR_D_MISC_POST_FR_BKOFF_DIS);
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
/* cwmin and cwmax should be 0 for beacon queue */
if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_DLCL_IFS(q), SM(0, AR_D_LCL_IFS_CWMIN)
| SM(0, AR_D_LCL_IFS_CWMAX)
| SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
}
break;
case ATH9K_TX_QUEUE_CAB:
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
| AR_Q_MISC_FSP_DBA_GATED
| AR_Q_MISC_CBR_INCR_DIS1
@ -811,6 +577,10 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
| (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
REGWRITE_BUFFER_FLUSH(ah);
DISABLE_REGWRITE_BUFFER(ah);
break;
case ATH9K_TX_QUEUE_PSPOLL:
REG_WRITE(ah, AR_QMISC(q),
@ -832,6 +602,9 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
AR_D_MISC_POST_FR_BKOFF_DIS);
}
if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_Q_DESC_CRCCHK, AR_Q_DESC_CRCCHK_EN);
if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
ah->txok_interrupt_mask |= 1 << q;
else
@ -940,22 +713,6 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
}
EXPORT_SYMBOL(ath9k_hw_rxprocdesc);
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags)
{
struct ar5416_desc *ads = AR5416DESC(ds);
struct ath9k_hw_capabilities *pCap = &ah->caps;
ads->ds_ctl1 = size & AR_BufLen;
if (flags & ATH9K_RXDESC_INTREQ)
ads->ds_ctl1 |= AR_RxIntrReq;
ads->ds_rxstatus8 &= ~AR_RxDone;
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
memset(&(ads->u), 0, sizeof(ads->u));
}
EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
/*
* This can stop or re-enables RX.
*
@ -999,12 +756,6 @@ void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp)
}
EXPORT_SYMBOL(ath9k_hw_putrxbuf);
void ath9k_hw_rxena(struct ath_hw *ah)
{
REG_WRITE(ah, AR_CR, AR_CR_RXE);
}
EXPORT_SYMBOL(ath9k_hw_rxena);
void ath9k_hw_startpcureceive(struct ath_hw *ah)
{
ath9k_enable_mib_counters(ah);
@ -1023,6 +774,14 @@ void ath9k_hw_stoppcurecv(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_stoppcurecv);
void ath9k_hw_abortpcurecv(struct ath_hw *ah)
{
REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_ABORT | AR_DIAG_RX_DIS);
ath9k_hw_disable_mib_counters(ah);
}
EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
{
#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
@ -1068,3 +827,140 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah)
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
}
EXPORT_SYMBOL(ath9k_hw_beaconq_setup);
bool ath9k_hw_intrpend(struct ath_hw *ah)
{
u32 host_isr;
if (AR_SREV_9100(ah))
return true;
host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE);
if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS))
return true;
host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE);
if ((host_isr & AR_INTR_SYNC_DEFAULT)
&& (host_isr != AR_INTR_SPURIOUS))
return true;
return false;
}
EXPORT_SYMBOL(ath9k_hw_intrpend);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
enum ath9k_int ints)
{
enum ath9k_int omask = ah->imask;
u32 mask, mask2;
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
if (omask & ATH9K_INT_GLOBAL) {
ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
(void) REG_READ(ah, AR_IER);
if (!AR_SREV_9100(ah)) {
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
}
}
/* TODO: global int Ref count */
mask = ints & ATH9K_INT_COMMON;
mask2 = 0;
if (ints & ATH9K_INT_TX) {
if (ah->config.tx_intr_mitigation)
mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
if (ah->txok_interrupt_mask)
mask |= AR_IMR_TXOK;
if (ah->txdesc_interrupt_mask)
mask |= AR_IMR_TXDESC;
if (ah->txerr_interrupt_mask)
mask |= AR_IMR_TXERR;
if (ah->txeol_interrupt_mask)
mask |= AR_IMR_TXEOL;
}
if (ints & ATH9K_INT_RX) {
if (AR_SREV_9300_20_OR_LATER(ah)) {
mask |= AR_IMR_RXERR | AR_IMR_RXOK_HP;
if (ah->config.rx_intr_mitigation) {
mask &= ~AR_IMR_RXOK_LP;
mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
} else {
mask |= AR_IMR_RXOK_LP;
}
} else {
if (ah->config.rx_intr_mitigation)
mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
else
mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
}
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
mask |= AR_IMR_GENTMR;
}
if (ints & (ATH9K_INT_BMISC)) {
mask |= AR_IMR_BCNMISC;
if (ints & ATH9K_INT_TIM)
mask2 |= AR_IMR_S2_TIM;
if (ints & ATH9K_INT_DTIM)
mask2 |= AR_IMR_S2_DTIM;
if (ints & ATH9K_INT_DTIMSYNC)
mask2 |= AR_IMR_S2_DTIMSYNC;
if (ints & ATH9K_INT_CABEND)
mask2 |= AR_IMR_S2_CABEND;
if (ints & ATH9K_INT_TSFOOR)
mask2 |= AR_IMR_S2_TSFOOR;
}
if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) {
mask |= AR_IMR_BCNMISC;
if (ints & ATH9K_INT_GTT)
mask2 |= AR_IMR_S2_GTT;
if (ints & ATH9K_INT_CST)
mask2 |= AR_IMR_S2_CST;
}
ath_print(common, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
REG_WRITE(ah, AR_IMR, mask);
ah->imrs2_reg &= ~(AR_IMR_S2_TIM | AR_IMR_S2_DTIM | AR_IMR_S2_DTIMSYNC |
AR_IMR_S2_CABEND | AR_IMR_S2_CABTO |
AR_IMR_S2_TSFOOR | AR_IMR_S2_GTT | AR_IMR_S2_CST);
ah->imrs2_reg |= mask2;
REG_WRITE(ah, AR_IMR_S2, ah->imrs2_reg);
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
if (ints & ATH9K_INT_TIM_TIMER)
REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
else
REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
}
if (ints & ATH9K_INT_GLOBAL) {
ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
if (!AR_SREV_9100(ah)) {
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
AR_INTR_MAC_IRQ);
REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
AR_INTR_SYNC_DEFAULT);
REG_WRITE(ah, AR_INTR_SYNC_MASK,
AR_INTR_SYNC_DEFAULT);
}
ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
}
return omask;
}
EXPORT_SYMBOL(ath9k_hw_set_interrupts);

View File

@ -37,6 +37,8 @@
AR_2040_##_index : 0) \
|((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \
AR_GI##_index : 0) \
|((_series)[_index].RateFlags & ATH9K_RATESERIES_STBC ? \
AR_STBC##_index : 0) \
|SM((_series)[_index].ChSel, AR_ChainSel##_index))
#define CCK_SIFS_TIME 10
@ -86,7 +88,6 @@
#define ATH9K_TX_DESC_CFG_ERR 0x04
#define ATH9K_TX_DATA_UNDERRUN 0x08
#define ATH9K_TX_DELIM_UNDERRUN 0x10
#define ATH9K_TX_SW_ABORTED 0x40
#define ATH9K_TX_SW_FILTERED 0x80
/* 64 bytes */
@ -117,7 +118,10 @@ struct ath_tx_status {
int8_t ts_rssi_ext0;
int8_t ts_rssi_ext1;
int8_t ts_rssi_ext2;
u8 pad[3];
u8 qid;
u16 desc_id;
u8 tid;
u8 pad[2];
u32 ba_low;
u32 ba_high;
u32 evm0;
@ -148,11 +152,13 @@ struct ath_rx_status {
u32 evm0;
u32 evm1;
u32 evm2;
u32 evm3;
u32 evm4;
};
struct ath_htc_rx_status {
u64 rs_tstamp;
u16 rs_datalen;
__be64 rs_tstamp;
__be16 rs_datalen;
u8 rs_status;
u8 rs_phyerr;
int8_t rs_rssi;
@ -171,9 +177,9 @@ struct ath_htc_rx_status {
u8 rs_num_delims;
u8 rs_flags;
u8 rs_dummy;
u32 evm0;
u32 evm1;
u32 evm2;
__be32 evm0;
__be32 evm1;
__be32 evm2;
};
#define ATH9K_RXERR_CRC 0x01
@ -259,7 +265,8 @@ struct ath_desc {
#define ATH9K_TXDESC_EXT_AND_CTL 0x0080
#define ATH9K_TXDESC_VMF 0x0100
#define ATH9K_TXDESC_FRAG_IS_ON 0x0200
#define ATH9K_TXDESC_CAB 0x0400
#define ATH9K_TXDESC_LOWRXCHAIN 0x0400
#define ATH9K_TXDESC_LDPC 0x00010000
#define ATH9K_RXDESC_INTREQ 0x0020
@ -353,7 +360,6 @@ struct ar5416_desc {
#define AR_DestIdxValid 0x40000000
#define AR_CTSEnable 0x80000000
#define AR_BufLen 0x00000fff
#define AR_TxMore 0x00001000
#define AR_DestIdx 0x000fe000
#define AR_DestIdx_S 13
@ -410,6 +416,7 @@ struct ar5416_desc {
#define AR_EncrType 0x0c000000
#define AR_EncrType_S 26
#define AR_TxCtlRsvd61 0xf0000000
#define AR_LDPC 0x80000000
#define AR_2040_0 0x00000001
#define AR_GI0 0x00000002
@ -429,7 +436,10 @@ struct ar5416_desc {
#define AR_ChainSel3_S 17
#define AR_RTSCTSRate 0x0ff00000
#define AR_RTSCTSRate_S 20
#define AR_TxCtlRsvd70 0xf0000000
#define AR_STBC0 0x10000000
#define AR_STBC1 0x20000000
#define AR_STBC2 0x40000000
#define AR_STBC3 0x80000000
#define AR_TxRSSIAnt00 0x000000ff
#define AR_TxRSSIAnt00_S 0
@ -493,7 +503,6 @@ struct ar5416_desc {
#define AR_RxCTLRsvd00 0xffffffff
#define AR_BufLen 0x00000fff
#define AR_RxCtlRsvd00 0x00001000
#define AR_RxIntrReq 0x00002000
#define AR_RxCtlRsvd01 0xffffc000
@ -643,6 +652,7 @@ enum ath9k_rx_filter {
#define ATH9K_RATESERIES_RTS_CTS 0x0001
#define ATH9K_RATESERIES_2040 0x0002
#define ATH9K_RATESERIES_HALFGI 0x0004
#define ATH9K_RATESERIES_STBC 0x0008
struct ath9k_11n_rate_series {
u32 Tries;
@ -686,34 +696,10 @@ struct ath9k_channel;
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 segLen, bool firstSeg,
bool lastSeg, const struct ath_desc *ds0);
void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds,
struct ath_tx_status *ts);
void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
u32 keyIx, enum ath9k_key_type keyType, u32 flags);
void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds,
struct ath_desc *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags);
void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds,
u32 aggrLen);
void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds,
u32 numDelims);
void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds);
void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds);
void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds,
u32 burstDuration);
void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds,
u32 vmf);
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
const struct ath9k_tx_queue_info *qinfo);
@ -729,10 +715,17 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
void ath9k_hw_rxena(struct ath_hw *ah);
void ath9k_hw_startpcureceive(struct ath_hw *ah);
void ath9k_hw_stoppcurecv(struct ath_hw *ah);
void ath9k_hw_abortpcurecv(struct ath_hw *ah);
bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
int ath9k_hw_beaconq_setup(struct ath_hw *ah);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah);
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
enum ath9k_int ints);
void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
#endif /* MAC_H */

View File

@ -401,23 +401,41 @@ void ath9k_tasklet(unsigned long data)
struct ath_common *common = ath9k_hw_common(ah);
u32 status = sc->intrstatus;
u32 rxmask;
ath9k_ps_wakeup(sc);
if (status & ATH9K_INT_FATAL) {
if ((status & ATH9K_INT_FATAL) ||
!ath9k_hw_check_alive(ah)) {
ath_reset(sc, false);
ath9k_ps_restore(sc);
return;
}
if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL |
ATH9K_INT_RXORN);
else
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
if (status & rxmask) {
spin_lock_bh(&sc->rx.rxflushlock);
ath_rx_tasklet(sc, 0);
/* Check for high priority Rx first */
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
(status & ATH9K_INT_RXHP))
ath_rx_tasklet(sc, 0, true);
ath_rx_tasklet(sc, 0, false);
spin_unlock_bh(&sc->rx.rxflushlock);
}
if (status & ATH9K_INT_TX)
ath_tx_tasklet(sc);
if (status & ATH9K_INT_TX) {
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ath_tx_edma_tasklet(sc);
else
ath_tx_tasklet(sc);
}
if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) {
/*
@ -445,6 +463,8 @@ irqreturn_t ath_isr(int irq, void *dev)
ATH9K_INT_RXORN | \
ATH9K_INT_RXEOL | \
ATH9K_INT_RX | \
ATH9K_INT_RXLP | \
ATH9K_INT_RXHP | \
ATH9K_INT_TX | \
ATH9K_INT_BMISS | \
ATH9K_INT_CST | \
@ -496,7 +516,8 @@ irqreturn_t ath_isr(int irq, void *dev)
* If a FATAL or RXORN interrupt is received, we have to reset the
* chip immediately.
*/
if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN))
if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
goto chip_reset;
if (status & ATH9K_INT_SWBA)
@ -505,6 +526,13 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & ATH9K_INT_TXURN)
ath9k_hw_updatetxtriglevel(ah, true);
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
if (status & ATH9K_INT_RXEOL) {
ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
ath9k_hw_set_interrupts(ah, ah->imask);
}
}
if (status & ATH9K_INT_MIB) {
/*
* Disable interrupts until we service the MIB
@ -724,6 +752,7 @@ static int ath_key_config(struct ath_common *common,
struct ath_hw *ah = common->ah;
struct ath9k_keyval hk;
const u8 *mac = NULL;
u8 gmac[ETH_ALEN];
int ret = 0;
int idx;
@ -747,9 +776,30 @@ static int ath_key_config(struct ath_common *common,
memcpy(hk.kv_val, key->key, key->keylen);
if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
/* For now, use the default keys for broadcast keys. This may
* need to change with virtual interfaces. */
idx = key->keyidx;
if (key->ap_addr) {
/*
* Group keys on hardware that supports multicast frame
* key search use a mac that is the sender's address with
* the high bit set instead of the app-specified address.
*/
memcpy(gmac, key->ap_addr, ETH_ALEN);
gmac[0] |= 0x80;
mac = gmac;
if (key->alg == ALG_TKIP)
idx = ath_reserve_key_cache_slot_tkip(common);
else
idx = ath_reserve_key_cache_slot(common);
if (idx < 0)
mac = NULL; /* no free key cache entries */
}
if (!mac) {
/* For now, use the default keys for broadcast keys. This may
* need to change with virtual interfaces. */
idx = key->keyidx;
}
} else if (key->keyidx) {
if (WARN_ON(!sta))
return -EOPNOTSUPP;
@ -1162,9 +1212,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
}
/* Setup our intr mask. */
ah->imask = ATH9K_INT_RX | ATH9K_INT_TX
| ATH9K_INT_RXEOL | ATH9K_INT_RXORN
| ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
ATH9K_INT_RXORN | ATH9K_INT_FATAL |
ATH9K_INT_GLOBAL;
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ah->imask |= ATH9K_INT_RXHP | ATH9K_INT_RXLP;
else
ah->imask |= ATH9K_INT_RX;
if (ah->caps.hw_caps & ATH9K_HW_CAP_GTT)
ah->imask |= ATH9K_INT_GTT;
@ -1436,7 +1491,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
if ((vif->type == NL80211_IFTYPE_STATION) ||
(vif->type == NL80211_IFTYPE_ADHOC) ||
(vif->type == NL80211_IFTYPE_MESH_POINT)) {
ah->imask |= ATH9K_INT_MIB;
if (ah->config.enable_ani)
ah->imask |= ATH9K_INT_MIB;
ah->imask |= ATH9K_INT_TSFOOR;
}

View File

@ -28,6 +28,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
{ PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
{ 0 }
};

View File

@ -1,978 +0,0 @@
/*
* Copyright (c) 2008-2009 Atheros Communications Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: Programming Atheros 802.11n analog front end radios
*
* AR5416 MAC based PCI devices and AR518 MAC based PCI-Express
* devices have either an external AR2133 analog front end radio for single
* band 2.4 GHz communication or an AR5133 analog front end radio for dual
* band 2.4 GHz / 5 GHz communication.
*
* All devices after the AR5416 and AR5418 family starting with the AR9280
* have their analog front radios, MAC/BB and host PCIe/USB interface embedded
* into a single-chip and require less programming.
*
* The following single-chips exist with a respective embedded radio:
*
* AR9280 - 11n dual-band 2x2 MIMO for PCIe
* AR9281 - 11n single-band 1x2 MIMO for PCIe
* AR9285 - 11n single-band 1x1 for PCIe
* AR9287 - 11n single-band 2x2 MIMO for PCIe
*
* AR9220 - 11n dual-band 2x2 MIMO for PCI
* AR9223 - 11n single-band 2x2 MIMO for PCI
*
* AR9287 - 11n single-band 1x1 MIMO for USB
*/
#include <linux/slab.h>
#include "hw.h"
/**
* ath9k_hw_write_regs - ??
*
* @ah: atheros hardware structure
* @freqIndex:
* @regWrites:
*
* Used for both the chipsets with an external AR2133/AR5133 radios and
* single-chip devices.
*/
void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites)
{
REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
}
/**
* ath9k_hw_ar9280_set_channel - set channel on single-chip device
* @ah: atheros hardware structure
* @chan:
*
* This is the function to change channel on single-chip devices, that is
* all devices after ar9280.
*
* This function takes the channel value in MHz and sets
* hardware channel value. Assumes writes have been enabled to analog bus.
*
* Actual Expression,
*
* For 2GHz channel,
* Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
* (freq_ref = 40MHz)
*
* For 5GHz channel,
* Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
* (freq_ref = 40MHz/(24>>amodeRefSel))
*/
int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
{
u16 bMode, fracMode, aModeRefSel = 0;
u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
struct chan_centers centers;
u32 refDivA = 24;
ath9k_hw_get_channel_centers(ah, chan, &centers);
freq = centers.synth_center;
reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
reg32 &= 0xc0000000;
if (freq < 4800) { /* 2 GHz, fractional mode */
u32 txctl;
int regWrites = 0;
bMode = 1;
fracMode = 1;
aModeRefSel = 0;
channelSel = (freq * 0x10000) / 15;
if (AR_SREV_9287_11_OR_LATER(ah)) {
if (freq == 2484) {
/* Enable channel spreading for channel 14 */
REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
1, regWrites);
} else {
REG_WRITE_ARRAY(&ah->iniCckfirNormal,
1, regWrites);
}
} else {
txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
if (freq == 2484) {
/* Enable channel spreading for channel 14 */
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
} else {
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
}
}
} else {
bMode = 0;
fracMode = 0;
switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) {
case 0:
if ((freq % 20) == 0) {
aModeRefSel = 3;
} else if ((freq % 10) == 0) {
aModeRefSel = 2;
}
if (aModeRefSel)
break;
case 1:
default:
aModeRefSel = 0;
/*
* Enable 2G (fractional) mode for channels
* which are 5MHz spaced.
*/
fracMode = 1;
refDivA = 1;
channelSel = (freq * 0x8000) / 15;
/* RefDivA setting */
REG_RMW_FIELD(ah, AR_AN_SYNTH9,
AR_AN_SYNTH9_REFDIVA, refDivA);
}
if (!fracMode) {
ndiv = (freq * (refDivA >> aModeRefSel)) / 60;
channelSel = ndiv & 0x1ff;
channelFrac = (ndiv & 0xfffffe00) * 2;
channelSel = (channelSel << 17) | channelFrac;
}
}
reg32 = reg32 |
(bMode << 29) |
(fracMode << 28) | (aModeRefSel << 26) | (channelSel);
REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
ah->curchan = chan;
ah->curchan_rad_index = -1;
return 0;
}
/**
* ath9k_hw_9280_spur_mitigate - convert baseband spur frequency
* @ah: atheros hardware structure
* @chan:
*
* For single-chip solutions. Converts to baseband spur frequency given the
* input channel frequency and compute register settings below.
*/
void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
{
int bb_spur = AR_NO_SPUR;
int freq;
int bin, cur_bin;
int bb_spur_off, spur_subchannel_sd;
int spur_freq_sd;
int spur_delta_phase;
int denominator;
int upper, lower, cur_vit_mask;
int tmp, newVal;
int i;
int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
};
int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
};
int inc[4] = { 0, 100, 0, 0 };
struct chan_centers centers;
int8_t mask_m[123];
int8_t mask_p[123];
int8_t mask_amt;
int tmp_mask;
int cur_bb_spur;
bool is2GHz = IS_CHAN_2GHZ(chan);
memset(&mask_m, 0, sizeof(int8_t) * 123);
memset(&mask_p, 0, sizeof(int8_t) * 123);
ath9k_hw_get_channel_centers(ah, chan, &centers);
freq = centers.synth_center;
ah->config.spurmode = SPUR_ENABLE_EEPROM;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
if (is2GHz)
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
else
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
if (AR_NO_SPUR == cur_bb_spur)
break;
cur_bb_spur = cur_bb_spur - freq;
if (IS_CHAN_HT40(chan)) {
if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
bb_spur = cur_bb_spur;
break;
}
} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
bb_spur = cur_bb_spur;
break;
}
}
if (AR_NO_SPUR == bb_spur) {
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
return;
} else {
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
}
bin = bb_spur * 320;
tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
if (IS_CHAN_HT40(chan)) {
if (bb_spur < 0) {
spur_subchannel_sd = 1;
bb_spur_off = bb_spur + 10;
} else {
spur_subchannel_sd = 0;
bb_spur_off = bb_spur - 10;
}
} else {
spur_subchannel_sd = 0;
bb_spur_off = bb_spur;
}
if (IS_CHAN_HT40(chan))
spur_delta_phase =
((bb_spur * 262144) /
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
else
spur_delta_phase =
((bb_spur * 524288) /
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
REG_WRITE(ah, AR_PHY_TIMING11, newVal);
newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
cur_bin = -6000;
upper = bin + 100;
lower = bin - 100;
for (i = 0; i < 4; i++) {
int pilot_mask = 0;
int chan_mask = 0;
int bp = 0;
for (bp = 0; bp < 30; bp++) {
if ((cur_bin > lower) && (cur_bin < upper)) {
pilot_mask = pilot_mask | 0x1 << bp;
chan_mask = chan_mask | 0x1 << bp;
}
cur_bin += 100;
}
cur_bin += inc[i];
REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
REG_WRITE(ah, chan_mask_reg[i], chan_mask);
}
cur_vit_mask = 6100;
upper = bin + 120;
lower = bin - 120;
for (i = 0; i < 123; i++) {
if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
/* workaround for gcc bug #37014 */
volatile int tmp_v = abs(cur_vit_mask - bin);
if (tmp_v < 75)
mask_amt = 1;
else
mask_amt = 0;
if (cur_vit_mask < 0)
mask_m[abs(cur_vit_mask / 100)] = mask_amt;
else
mask_p[cur_vit_mask / 100] = mask_amt;
}
cur_vit_mask -= 100;
}
tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
| (mask_m[48] << 26) | (mask_m[49] << 24)
| (mask_m[50] << 22) | (mask_m[51] << 20)
| (mask_m[52] << 18) | (mask_m[53] << 16)
| (mask_m[54] << 14) | (mask_m[55] << 12)
| (mask_m[56] << 10) | (mask_m[57] << 8)
| (mask_m[58] << 6) | (mask_m[59] << 4)
| (mask_m[60] << 2) | (mask_m[61] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
tmp_mask = (mask_m[31] << 28)
| (mask_m[32] << 26) | (mask_m[33] << 24)
| (mask_m[34] << 22) | (mask_m[35] << 20)
| (mask_m[36] << 18) | (mask_m[37] << 16)
| (mask_m[48] << 14) | (mask_m[39] << 12)
| (mask_m[40] << 10) | (mask_m[41] << 8)
| (mask_m[42] << 6) | (mask_m[43] << 4)
| (mask_m[44] << 2) | (mask_m[45] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
| (mask_m[18] << 26) | (mask_m[18] << 24)
| (mask_m[20] << 22) | (mask_m[20] << 20)
| (mask_m[22] << 18) | (mask_m[22] << 16)
| (mask_m[24] << 14) | (mask_m[24] << 12)
| (mask_m[25] << 10) | (mask_m[26] << 8)
| (mask_m[27] << 6) | (mask_m[28] << 4)
| (mask_m[29] << 2) | (mask_m[30] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
| (mask_m[2] << 26) | (mask_m[3] << 24)
| (mask_m[4] << 22) | (mask_m[5] << 20)
| (mask_m[6] << 18) | (mask_m[7] << 16)
| (mask_m[8] << 14) | (mask_m[9] << 12)
| (mask_m[10] << 10) | (mask_m[11] << 8)
| (mask_m[12] << 6) | (mask_m[13] << 4)
| (mask_m[14] << 2) | (mask_m[15] << 0);
REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
tmp_mask = (mask_p[15] << 28)
| (mask_p[14] << 26) | (mask_p[13] << 24)
| (mask_p[12] << 22) | (mask_p[11] << 20)
| (mask_p[10] << 18) | (mask_p[9] << 16)
| (mask_p[8] << 14) | (mask_p[7] << 12)
| (mask_p[6] << 10) | (mask_p[5] << 8)
| (mask_p[4] << 6) | (mask_p[3] << 4)
| (mask_p[2] << 2) | (mask_p[1] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
tmp_mask = (mask_p[30] << 28)
| (mask_p[29] << 26) | (mask_p[28] << 24)
| (mask_p[27] << 22) | (mask_p[26] << 20)
| (mask_p[25] << 18) | (mask_p[24] << 16)
| (mask_p[23] << 14) | (mask_p[22] << 12)
| (mask_p[21] << 10) | (mask_p[20] << 8)
| (mask_p[19] << 6) | (mask_p[18] << 4)
| (mask_p[17] << 2) | (mask_p[16] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
tmp_mask = (mask_p[45] << 28)
| (mask_p[44] << 26) | (mask_p[43] << 24)
| (mask_p[42] << 22) | (mask_p[41] << 20)
| (mask_p[40] << 18) | (mask_p[39] << 16)
| (mask_p[38] << 14) | (mask_p[37] << 12)
| (mask_p[36] << 10) | (mask_p[35] << 8)
| (mask_p[34] << 6) | (mask_p[33] << 4)
| (mask_p[32] << 2) | (mask_p[31] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
| (mask_p[59] << 26) | (mask_p[58] << 24)
| (mask_p[57] << 22) | (mask_p[56] << 20)
| (mask_p[55] << 18) | (mask_p[54] << 16)
| (mask_p[53] << 14) | (mask_p[52] << 12)
| (mask_p[51] << 10) | (mask_p[50] << 8)
| (mask_p[49] << 6) | (mask_p[48] << 4)
| (mask_p[47] << 2) | (mask_p[46] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
/* All code below is for non single-chip solutions */
/**
* ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters
* @rfbuf:
* @reg32:
* @numBits:
* @firstBit:
* @column:
*
* Performs analog "swizzling" of parameters into their location.
* Used on external AR2133/AR5133 radios.
*/
static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
u32 numBits, u32 firstBit,
u32 column)
{
u32 tmp32, mask, arrayEntry, lastBit;
int32_t bitPosition, bitsLeft;
tmp32 = ath9k_hw_reverse_bits(reg32, numBits);
arrayEntry = (firstBit - 1) / 8;
bitPosition = (firstBit - 1) % 8;
bitsLeft = numBits;
while (bitsLeft > 0) {
lastBit = (bitPosition + bitsLeft > 8) ?
8 : bitPosition + bitsLeft;
mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) <<
(column * 8);
rfBuf[arrayEntry] &= ~mask;
rfBuf[arrayEntry] |= ((tmp32 << bitPosition) <<
(column * 8)) & mask;
bitsLeft -= 8 - bitPosition;
tmp32 = tmp32 >> (8 - bitPosition);
bitPosition = 0;
arrayEntry++;
}
}
/*
* Fix on 2.4 GHz band for orientation sensitivity issue by increasing
* rf_pwd_icsyndiv.
*
* Theoretical Rules:
* if 2 GHz band
* if forceBiasAuto
* if synth_freq < 2412
* bias = 0
* else if 2412 <= synth_freq <= 2422
* bias = 1
* else // synth_freq > 2422
* bias = 2
* else if forceBias > 0
* bias = forceBias & 7
* else
* no change, use value from ini file
* else
* no change, invalid band
*
* 1st Mod:
* 2422 also uses value of 2
* <approved>
*
* 2nd Mod:
* Less than 2412 uses value of 0, 2412 and above uses value of 2
*/
static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
{
struct ath_common *common = ath9k_hw_common(ah);
u32 tmp_reg;
int reg_writes = 0;
u32 new_bias = 0;
if (!AR_SREV_5416(ah) || synth_freq >= 3000) {
return;
}
BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
if (synth_freq < 2412)
new_bias = 0;
else if (synth_freq < 2422)
new_bias = 1;
else
new_bias = 2;
/* pre-reverse this field */
tmp_reg = ath9k_hw_reverse_bits(new_bias, 3);
ath_print(common, ATH_DBG_CONFIG,
"Force rf_pwd_icsyndiv to %1d on %4d\n",
new_bias, synth_freq);
/* swizzle rf_pwd_icsyndiv */
ath9k_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
/* write Bank 6 with new params */
REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
}
/**
* ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios
* @ah: atheros hardware stucture
* @chan:
*
* For the external AR2133/AR5133 radios, takes the MHz channel value and set
* the channel value. Assumes writes enabled to analog bus and bank6 register
* cache in ah->analogBank6Data.
*/
int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
u32 channelSel = 0;
u32 bModeSynth = 0;
u32 aModeRefSel = 0;
u32 reg32 = 0;
u16 freq;
struct chan_centers centers;
ath9k_hw_get_channel_centers(ah, chan, &centers);
freq = centers.synth_center;
if (freq < 4800) {
u32 txctl;
if (((freq - 2192) % 5) == 0) {
channelSel = ((freq - 672) * 2 - 3040) / 10;
bModeSynth = 0;
} else if (((freq - 2224) % 5) == 0) {
channelSel = ((freq - 704) * 2 - 3040) / 10;
bModeSynth = 1;
} else {
ath_print(common, ATH_DBG_FATAL,
"Invalid channel %u MHz\n", freq);
return -EINVAL;
}
channelSel = (channelSel << 2) & 0xff;
channelSel = ath9k_hw_reverse_bits(channelSel, 8);
txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
if (freq == 2484) {
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
} else {
REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
}
} else if ((freq % 20) == 0 && freq >= 5120) {
channelSel =
ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
aModeRefSel = ath9k_hw_reverse_bits(1, 2);
} else if ((freq % 10) == 0) {
channelSel =
ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
aModeRefSel = ath9k_hw_reverse_bits(2, 2);
else
aModeRefSel = ath9k_hw_reverse_bits(1, 2);
} else if ((freq % 5) == 0) {
channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
aModeRefSel = ath9k_hw_reverse_bits(1, 2);
} else {
ath_print(common, ATH_DBG_FATAL,
"Invalid channel %u MHz\n", freq);
return -EINVAL;
}
ath9k_hw_force_bias(ah, freq);
reg32 =
(channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
(1 << 5) | 0x1;
REG_WRITE(ah, AR_PHY(0x37), reg32);
ah->curchan = chan;
ah->curchan_rad_index = -1;
return 0;
}
/**
* ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios
* @ah: atheros hardware structure
* @chan:
*
* For non single-chip solutions. Converts to baseband spur frequency given the
* input channel frequency and compute register settings below.
*/
void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
{
int bb_spur = AR_NO_SPUR;
int bin, cur_bin;
int spur_freq_sd;
int spur_delta_phase;
int denominator;
int upper, lower, cur_vit_mask;
int tmp, new;
int i;
int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
};
int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
};
int inc[4] = { 0, 100, 0, 0 };
int8_t mask_m[123];
int8_t mask_p[123];
int8_t mask_amt;
int tmp_mask;
int cur_bb_spur;
bool is2GHz = IS_CHAN_2GHZ(chan);
memset(&mask_m, 0, sizeof(int8_t) * 123);
memset(&mask_p, 0, sizeof(int8_t) * 123);
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
if (AR_NO_SPUR == cur_bb_spur)
break;
cur_bb_spur = cur_bb_spur - (chan->channel * 10);
if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
bb_spur = cur_bb_spur;
break;
}
}
if (AR_NO_SPUR == bb_spur)
return;
bin = bb_spur * 32;
tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
REG_WRITE(ah, AR_PHY_SPUR_REG, new);
spur_delta_phase = ((bb_spur * 524288) / 100) &
AR_PHY_TIMING11_SPUR_DELTA_PHASE;
denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
REG_WRITE(ah, AR_PHY_TIMING11, new);
cur_bin = -6000;
upper = bin + 100;
lower = bin - 100;
for (i = 0; i < 4; i++) {
int pilot_mask = 0;
int chan_mask = 0;
int bp = 0;
for (bp = 0; bp < 30; bp++) {
if ((cur_bin > lower) && (cur_bin < upper)) {
pilot_mask = pilot_mask | 0x1 << bp;
chan_mask = chan_mask | 0x1 << bp;
}
cur_bin += 100;
}
cur_bin += inc[i];
REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
REG_WRITE(ah, chan_mask_reg[i], chan_mask);
}
cur_vit_mask = 6100;
upper = bin + 120;
lower = bin - 120;
for (i = 0; i < 123; i++) {
if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
/* workaround for gcc bug #37014 */
volatile int tmp_v = abs(cur_vit_mask - bin);
if (tmp_v < 75)
mask_amt = 1;
else
mask_amt = 0;
if (cur_vit_mask < 0)
mask_m[abs(cur_vit_mask / 100)] = mask_amt;
else
mask_p[cur_vit_mask / 100] = mask_amt;
}
cur_vit_mask -= 100;
}
tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
| (mask_m[48] << 26) | (mask_m[49] << 24)
| (mask_m[50] << 22) | (mask_m[51] << 20)
| (mask_m[52] << 18) | (mask_m[53] << 16)
| (mask_m[54] << 14) | (mask_m[55] << 12)
| (mask_m[56] << 10) | (mask_m[57] << 8)
| (mask_m[58] << 6) | (mask_m[59] << 4)
| (mask_m[60] << 2) | (mask_m[61] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
tmp_mask = (mask_m[31] << 28)
| (mask_m[32] << 26) | (mask_m[33] << 24)
| (mask_m[34] << 22) | (mask_m[35] << 20)
| (mask_m[36] << 18) | (mask_m[37] << 16)
| (mask_m[48] << 14) | (mask_m[39] << 12)
| (mask_m[40] << 10) | (mask_m[41] << 8)
| (mask_m[42] << 6) | (mask_m[43] << 4)
| (mask_m[44] << 2) | (mask_m[45] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
| (mask_m[18] << 26) | (mask_m[18] << 24)
| (mask_m[20] << 22) | (mask_m[20] << 20)
| (mask_m[22] << 18) | (mask_m[22] << 16)
| (mask_m[24] << 14) | (mask_m[24] << 12)
| (mask_m[25] << 10) | (mask_m[26] << 8)
| (mask_m[27] << 6) | (mask_m[28] << 4)
| (mask_m[29] << 2) | (mask_m[30] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
| (mask_m[2] << 26) | (mask_m[3] << 24)
| (mask_m[4] << 22) | (mask_m[5] << 20)
| (mask_m[6] << 18) | (mask_m[7] << 16)
| (mask_m[8] << 14) | (mask_m[9] << 12)
| (mask_m[10] << 10) | (mask_m[11] << 8)
| (mask_m[12] << 6) | (mask_m[13] << 4)
| (mask_m[14] << 2) | (mask_m[15] << 0);
REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
tmp_mask = (mask_p[15] << 28)
| (mask_p[14] << 26) | (mask_p[13] << 24)
| (mask_p[12] << 22) | (mask_p[11] << 20)
| (mask_p[10] << 18) | (mask_p[9] << 16)
| (mask_p[8] << 14) | (mask_p[7] << 12)
| (mask_p[6] << 10) | (mask_p[5] << 8)
| (mask_p[4] << 6) | (mask_p[3] << 4)
| (mask_p[2] << 2) | (mask_p[1] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
tmp_mask = (mask_p[30] << 28)
| (mask_p[29] << 26) | (mask_p[28] << 24)
| (mask_p[27] << 22) | (mask_p[26] << 20)
| (mask_p[25] << 18) | (mask_p[24] << 16)
| (mask_p[23] << 14) | (mask_p[22] << 12)
| (mask_p[21] << 10) | (mask_p[20] << 8)
| (mask_p[19] << 6) | (mask_p[18] << 4)
| (mask_p[17] << 2) | (mask_p[16] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
tmp_mask = (mask_p[45] << 28)
| (mask_p[44] << 26) | (mask_p[43] << 24)
| (mask_p[42] << 22) | (mask_p[41] << 20)
| (mask_p[40] << 18) | (mask_p[39] << 16)
| (mask_p[38] << 14) | (mask_p[37] << 12)
| (mask_p[36] << 10) | (mask_p[35] << 8)
| (mask_p[34] << 6) | (mask_p[33] << 4)
| (mask_p[32] << 2) | (mask_p[31] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
| (mask_p[59] << 26) | (mask_p[58] << 24)
| (mask_p[57] << 22) | (mask_p[56] << 20)
| (mask_p[55] << 18) | (mask_p[54] << 16)
| (mask_p[53] << 14) | (mask_p[52] << 12)
| (mask_p[51] << 10) | (mask_p[50] << 8)
| (mask_p[49] << 6) | (mask_p[48] << 4)
| (mask_p[47] << 2) | (mask_p[46] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
/**
* ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming
* @ah: atheros hardware structure
*
* Only required for older devices with external AR2133/AR5133 radios.
*/
int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah)
{
#define ATH_ALLOC_BANK(bank, size) do { \
bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \
if (!bank) { \
ath_print(common, ATH_DBG_FATAL, \
"Cannot allocate RF banks\n"); \
return -ENOMEM; \
} \
} while (0);
struct ath_common *common = ath9k_hw_common(ah);
BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
ATH_ALLOC_BANK(ah->addac5416_21,
ah->iniAddac.ia_rows * ah->iniAddac.ia_columns);
ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
return 0;
#undef ATH_ALLOC_BANK
}
/**
* ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers
* @ah: atheros hardware struture
* For the external AR2133/AR5133 radios banks.
*/
void
ath9k_hw_rf_free_ext_banks(struct ath_hw *ah)
{
#define ATH_FREE_BANK(bank) do { \
kfree(bank); \
bank = NULL; \
} while (0);
BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
ATH_FREE_BANK(ah->analogBank0Data);
ATH_FREE_BANK(ah->analogBank1Data);
ATH_FREE_BANK(ah->analogBank2Data);
ATH_FREE_BANK(ah->analogBank3Data);
ATH_FREE_BANK(ah->analogBank6Data);
ATH_FREE_BANK(ah->analogBank6TPCData);
ATH_FREE_BANK(ah->analogBank7Data);
ATH_FREE_BANK(ah->addac5416_21);
ATH_FREE_BANK(ah->bank6Temp);
#undef ATH_FREE_BANK
}
/* *
* ath9k_hw_set_rf_regs - programs rf registers based on EEPROM
* @ah: atheros hardware structure
* @chan:
* @modesIndex:
*
* Used for the external AR2133/AR5133 radios.
*
* Reads the EEPROM header info from the device structure and programs
* all rf registers. This routine requires access to the analog
* rf device. This is not required for single-chip devices.
*/
bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
u16 modesIndex)
{
u32 eepMinorRev;
u32 ob5GHz = 0, db5GHz = 0;
u32 ob2GHz = 0, db2GHz = 0;
int regWrites = 0;
/*
* Software does not need to program bank data
* for single chip devices, that is AR9280 or anything
* after that.
*/
if (AR_SREV_9280_10_OR_LATER(ah))
return true;
/* Setup rf parameters */
eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
/* Setup Bank 0 Write */
RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1);
/* Setup Bank 1 Write */
RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1);
/* Setup Bank 2 Write */
RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1);
/* Setup Bank 6 Write */
RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3,
modesIndex);
{
int i;
for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) {
ah->analogBank6Data[i] =
INI_RA(&ah->iniBank6TPC, i, modesIndex);
}
}
/* Only the 5 or 2 GHz OB/DB need to be set for a mode */
if (eepMinorRev >= 2) {
if (IS_CHAN_2GHZ(chan)) {
ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);
db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2);
ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
ob2GHz, 3, 197, 0);
ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
db2GHz, 3, 194, 0);
} else {
ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5);
db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5);
ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
ob5GHz, 3, 203, 0);
ath9k_phy_modify_rx_buffer(ah->analogBank6Data,
db5GHz, 3, 200, 0);
}
}
/* Setup Bank 7 Setup */
RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1);
/* Write Analog registers */
REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
regWrites);
REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
regWrites);
REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data,
regWrites);
REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data,
regWrites);
REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data,
regWrites);
REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data,
regWrites);
return true;
}

View File

@ -17,504 +17,15 @@
#ifndef PHY_H
#define PHY_H
/* Common between single chip and non single-chip solutions */
void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites);
/* Single chip radio settings */
int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
/* Routines below are for non single-chip solutions */
int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah);
void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah);
bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 modesIndex);
#define CHANSEL_DIV 15
#define CHANSEL_2G(_freq) (((_freq) * 0x10000) / CHANSEL_DIV)
#define CHANSEL_5G(_freq) (((_freq) * 0x8000) / CHANSEL_DIV)
#define AR_PHY_BASE 0x9800
#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
#define AR_PHY_TEST 0x9800
#define PHY_AGC_CLR 0x10000000
#define RFSILENT_BB 0x00002000
#define AR_PHY_TURBO 0x9804
#define AR_PHY_FC_TURBO_MODE 0x00000001
#define AR_PHY_FC_TURBO_SHORT 0x00000002
#define AR_PHY_FC_DYN2040_EN 0x00000004
#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008
#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010
/* For 25 MHz channel spacing -- not used but supported by hw */
#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020
#define AR_PHY_FC_HT_EN 0x00000040
#define AR_PHY_FC_SHORT_GI_40 0x00000080
#define AR_PHY_FC_WALSH 0x00000100
#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
#define AR_PHY_TEST2 0x9808
#define AR_PHY_TIMING2 0x9810
#define AR_PHY_TIMING3 0x9814
#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000
#define AR_PHY_TIMING3_DSC_MAN_S 17
#define AR_PHY_TIMING3_DSC_EXP 0x0001E000
#define AR_PHY_TIMING3_DSC_EXP_S 13
#define AR_PHY_CHIP_ID 0x9818
#define AR_PHY_CHIP_ID_REV_0 0x80
#define AR_PHY_CHIP_ID_REV_1 0x81
#define AR_PHY_CHIP_ID_9160_REV_0 0xb0
#define AR_PHY_ACTIVE 0x981C
#define AR_PHY_ACTIVE_EN 0x00000001
#define AR_PHY_ACTIVE_DIS 0x00000000
#define AR_PHY_RF_CTL2 0x9824
#define AR_PHY_TX_END_DATA_START 0x000000FF
#define AR_PHY_TX_END_DATA_START_S 0
#define AR_PHY_TX_END_PA_ON 0x0000FF00
#define AR_PHY_TX_END_PA_ON_S 8
#define AR_PHY_RF_CTL3 0x9828
#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000
#define AR_PHY_TX_END_TO_A2_RX_ON_S 16
#define AR_PHY_ADC_CTL 0x982C
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003
#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0
#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000
#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000
#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000
#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000
#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16
#define AR_PHY_ADC_SERIAL_CTL 0x9830
#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000
#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001
#define AR_PHY_RF_CTL4 0x9834
#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000
#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24
#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000
#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16
#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00
#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
#define AR_PHY_TSTDAC_CONST 0x983c
#define AR_PHY_SETTLING 0x9844
#define AR_PHY_SETTLING_SWITCH 0x00003F80
#define AR_PHY_SETTLING_SWITCH_S 7
#define AR_PHY_RXGAIN 0x9848
#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000
#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12
#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000
#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18
#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80
#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7
#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000
#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14
#define AR_PHY_DESIRED_SZ 0x9850
#define AR_PHY_DESIRED_SZ_ADC 0x000000FF
#define AR_PHY_DESIRED_SZ_ADC_S 0
#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00
#define AR_PHY_DESIRED_SZ_PGA_S 8
#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000
#define AR_PHY_DESIRED_SZ_TOT_DES_S 20
#define AR_PHY_FIND_SIG 0x9858
#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000
#define AR_PHY_FIND_SIG_FIRSTEP_S 12
#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000
#define AR_PHY_FIND_SIG_FIRPWR_S 18
#define AR_PHY_AGC_CTL1 0x985C
#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80
#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7
#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000
#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15
#define AR_PHY_AGC_CONTROL 0x9860
#define AR_PHY_AGC_CONTROL_CAL 0x00000001
#define AR_PHY_AGC_CONTROL_NF 0x00000002
#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000
#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000
#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
#define AR_PHY_CCA 0x9864
#define AR_PHY_MINCCA_PWR 0x0FF80000
#define AR_PHY_MINCCA_PWR_S 19
#define AR_PHY_CCA_THRESH62 0x0007F000
#define AR_PHY_CCA_THRESH62_S 12
#define AR9280_PHY_MINCCA_PWR 0x1FF00000
#define AR9280_PHY_MINCCA_PWR_S 20
#define AR9280_PHY_CCA_THRESH62 0x000FF000
#define AR9280_PHY_CCA_THRESH62_S 12
#define AR_PHY_SFCORR_LOW 0x986C
#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00
#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000
#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000
#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21
#define AR_PHY_SFCORR 0x9868
#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F
#define AR_PHY_SFCORR_M2COUNT_THR_S 0
#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000
#define AR_PHY_SFCORR_M1_THRESH_S 17
#define AR_PHY_SFCORR_M2_THRESH 0x7F000000
#define AR_PHY_SFCORR_M2_THRESH_S 24
#define AR_PHY_SLEEP_CTR_CONTROL 0x9870
#define AR_PHY_SLEEP_CTR_LIMIT 0x9874
#define AR_PHY_SYNTH_CONTROL 0x9874
#define AR_PHY_SLEEP_SCAL 0x9878
#define AR_PHY_PLL_CTL 0x987c
#define AR_PHY_PLL_CTL_40 0xaa
#define AR_PHY_PLL_CTL_40_5413 0x04
#define AR_PHY_PLL_CTL_44 0xab
#define AR_PHY_PLL_CTL_44_2133 0xeb
#define AR_PHY_PLL_CTL_40_2133 0xea
#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */
#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */
#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */
#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/
#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/
#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/
#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/
#define AR_PHY_RX_DELAY 0x9914
#define AR_PHY_SEARCH_START_DELAY 0x9918
#define AR_PHY_RX_DELAY_DELAY 0x00003FFF
#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12))
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0
#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5
#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000
#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12
#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000
#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000
#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000
#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000
#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000
#define AR_PHY_TIMING5 0x9924
#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE
#define AR_PHY_TIMING5_CYCPWR_THR1_S 1
#define AR_PHY_POWER_TX_RATE1 0x9934
#define AR_PHY_POWER_TX_RATE2 0x9938
#define AR_PHY_POWER_TX_RATE_MAX 0x993c
#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040
#define AR_PHY_FRAME_CTL 0x9944
#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038
#define AR_PHY_FRAME_CTL_TX_CLIP_S 3
#define AR_PHY_TXPWRADJ 0x994C
#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0
#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6
#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000
#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18
#define AR_PHY_RADAR_EXT 0x9940
#define AR_PHY_RADAR_EXT_ENA 0x00004000
#define AR_PHY_RADAR_0 0x9954
#define AR_PHY_RADAR_0_ENA 0x00000001
#define AR_PHY_RADAR_0_FFT_ENA 0x80000000
#define AR_PHY_RADAR_0_INBAND 0x0000003e
#define AR_PHY_RADAR_0_INBAND_S 1
#define AR_PHY_RADAR_0_PRSSI 0x00000FC0
#define AR_PHY_RADAR_0_PRSSI_S 6
#define AR_PHY_RADAR_0_HEIGHT 0x0003F000
#define AR_PHY_RADAR_0_HEIGHT_S 12
#define AR_PHY_RADAR_0_RRSSI 0x00FC0000
#define AR_PHY_RADAR_0_RRSSI_S 18
#define AR_PHY_RADAR_0_FIRPWR 0x7F000000
#define AR_PHY_RADAR_0_FIRPWR_S 24
#define AR_PHY_RADAR_1 0x9958
#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000
#define AR_PHY_RADAR_1_USE_FIR128 0x00400000
#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000
#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16
#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000
#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000
#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000
#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00
#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8
#define AR_PHY_RADAR_1_MAXLEN 0x000000FF
#define AR_PHY_RADAR_1_MAXLEN_S 0
#define AR_PHY_SWITCH_CHAIN_0 0x9960
#define AR_PHY_SWITCH_COM 0x9964
#define AR_PHY_SIGMA_DELTA 0x996C
#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003
#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0
#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8
#define AR_PHY_SIGMA_DELTA_FILT2_S 3
#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00
#define AR_PHY_SIGMA_DELTA_FILT1_S 8
#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000
#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13
#define AR_PHY_RESTART 0x9970
#define AR_PHY_RESTART_DIV_GC 0x001C0000
#define AR_PHY_RESTART_DIV_GC_S 18
#define AR_PHY_RFBUS_REQ 0x997C
#define AR_PHY_RFBUS_REQ_EN 0x00000001
#define AR_PHY_TIMING7 0x9980
#define AR_PHY_TIMING8 0x9984
#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF
#define AR_PHY_TIMING8_PILOT_MASK_2_S 0
#define AR_PHY_BIN_MASK2_1 0x9988
#define AR_PHY_BIN_MASK2_2 0x998c
#define AR_PHY_BIN_MASK2_3 0x9990
#define AR_PHY_BIN_MASK2_4 0x9994
#define AR_PHY_BIN_MASK_1 0x9900
#define AR_PHY_BIN_MASK_2 0x9904
#define AR_PHY_BIN_MASK_3 0x9908
#define AR_PHY_MASK_CTL 0x990c
#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF
#define AR_PHY_BIN_MASK2_4_MASK_4_S 0
#define AR_PHY_TIMING9 0x9998
#define AR_PHY_TIMING10 0x999c
#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF
#define AR_PHY_TIMING10_PILOT_MASK_2_S 0
#define AR_PHY_TIMING11 0x99a0
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF
#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000
#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000
#define AR_PHY_RX_CHAINMASK 0x99a4
#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
#define AR_PHY_9285_ANT_DIV_CTL 0x01000000
#define AR_PHY_9285_ANT_DIV_CTL_S 24
#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
#define AR_PHY_9285_ANT_DIV_LNA1 2
#define AR_PHY_9285_ANT_DIV_LNA2 1
#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
#define AR_PHY_9285_ANT_DIV_GAINTB_0 0
#define AR_PHY_9285_ANT_DIV_GAINTB_1 1
#define AR_PHY_EXT_CCA0 0x99b8
#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
#define AR_PHY_EXT_CCA0_THRESH62_S 0
#define AR_PHY_EXT_CCA 0x99bc
#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00
#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9
#define AR_PHY_EXT_CCA_THRESH62 0x007F0000
#define AR_PHY_EXT_CCA_THRESH62_S 16
#define AR_PHY_EXT_MINCCA_PWR 0xFF800000
#define AR_PHY_EXT_MINCCA_PWR_S 23
#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000
#define AR9280_PHY_EXT_MINCCA_PWR_S 16
#define AR_PHY_SFCORR_EXT 0x99c0
#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F
#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0
#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80
#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000
#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000
#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21
#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28
#define AR_PHY_HALFGI 0x99D0
#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0
#define AR_PHY_HALFGI_DSC_MAN_S 4
#define AR_PHY_HALFGI_DSC_EXP 0x0000000F
#define AR_PHY_HALFGI_DSC_EXP_S 0
#define AR_PHY_CHAN_INFO_MEMORY 0x99DC
#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001
#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0
#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC
#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000
#define AR_PHY_M_SLEEP 0x99f0
#define AR_PHY_REFCLKDLY 0x99f4
#define AR_PHY_REFCLKPD 0x99f8
#define AR_PHY_CALMODE 0x99f0
#define AR_PHY_CALMODE_IQ 0x00000000
#define AR_PHY_CALMODE_ADC_GAIN 0x00000001
#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002
#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003
#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12))
#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12))
#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12))
#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12))
#define AR_PHY_CURRENT_RSSI 0x9c1c
#define AR9280_PHY_CURRENT_RSSI 0x9c3c
#define AR_PHY_RFBUS_GRANT 0x9C20
#define AR_PHY_RFBUS_GRANT_EN 0x00000001
#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4
#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320
#define AR_PHY_CHAN_INFO_GAIN 0x9CFC
#define AR_PHY_MODE 0xA200
#define AR_PHY_MODE_ASYNCFIFO 0x80
#define AR_PHY_MODE_AR2133 0x08
#define AR_PHY_MODE_AR5111 0x00
#define AR_PHY_MODE_AR5112 0x08
#define AR_PHY_MODE_DYNAMIC 0x04
#define AR_PHY_MODE_RF2GHZ 0x02
#define AR_PHY_MODE_RF5GHZ 0x00
#define AR_PHY_MODE_CCK 0x01
#define AR_PHY_MODE_OFDM 0x00
#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100
#define AR_PHY_CCK_TX_CTRL 0xA204
#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C
#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2
#define AR_PHY_CCK_DETECT 0xA208
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F
#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0
/* [12:6] settling time for antenna switch */
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
#define AR_PHY_GAIN_2GHZ 0xA20C
#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18
#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00
#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10
#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F
#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0
#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000
#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17
#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000
#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12
#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0
#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6
#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F
#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0
#define AR_PHY_CCK_RXCTRL4 0xA21C
#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000
#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19
#define AR_PHY_DAG_CTRLCCK 0xA228
#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200
#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00
#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10
#define AR_PHY_FORCE_CLKEN_CCK 0xA22C
#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040
#define AR_PHY_POWER_TX_RATE3 0xA234
#define AR_PHY_POWER_TX_RATE4 0xA238
#define AR_PHY_SCRM_SEQ_XR 0xA23C
#define AR_PHY_HEADER_DETECT_XR 0xA240
#define AR_PHY_CHIRP_DETECTED_XR 0xA244
#define AR_PHY_BLUETOOTH 0xA254
#define AR_PHY_TPCRG1 0xA258
#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000
#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14
#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000
#define AR_PHY_TPCRG1_PD_GAIN_1_S 16
#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000
#define AR_PHY_TPCRG1_PD_GAIN_2_S 18
#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000
#define AR_PHY_TPCRG1_PD_GAIN_3_S 20
#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000
#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22
#define AR_PHY_TX_PWRCTRL4 0xa264
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001
#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE
#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1
#define AR_PHY_TX_PWRCTRL6_0 0xa270
#define AR_PHY_TX_PWRCTRL6_1 0xb270
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000
#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24
#define AR_PHY_TX_PWRCTRL7 0xa274
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX 0x0007E000
#define AR_PHY_TX_PWRCTRL_TX_GAIN_TAB_MAX_S 13
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000
#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19
#define AR_PHY_TX_PWRCTRL9 0xa27C
#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00
#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000
#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31
#define AR_PHY_TX_GAIN_TBL1 0xa300
#define AR_PHY_TX_GAIN_CLC 0x0000001E
#define AR_PHY_TX_GAIN_CLC_S 1
#define AR_PHY_TX_GAIN 0x0007F000
@ -526,91 +37,6 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
#define AR_PHY_CLC_Q0 0x0000ffd0
#define AR_PHY_CLC_Q0_S 5
#define AR_PHY_CH0_TX_PWRCTRL11 0xa398
#define AR_PHY_CH1_TX_PWRCTRL11 0xb398
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00
#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10
#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0
#define AR_PHY_MASK2_M_31_45 0xa3a4
#define AR_PHY_MASK2_M_16_30 0xa3a8
#define AR_PHY_MASK2_M_00_15 0xa3ac
#define AR_PHY_MASK2_P_15_01 0xa3b8
#define AR_PHY_MASK2_P_30_16 0xa3bc
#define AR_PHY_MASK2_P_45_31 0xa3c0
#define AR_PHY_MASK2_P_61_45 0xa3c4
#define AR_PHY_SPUR_REG 0x994c
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18)
#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18
#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000
#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9)
#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9
#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F
#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0
#define AR_PHY_PILOT_MASK_01_30 0xa3b0
#define AR_PHY_PILOT_MASK_31_60 0xa3b4
#define AR_PHY_CHANNEL_MASK_01_30 0x99d4
#define AR_PHY_CHANNEL_MASK_31_60 0x99d8
#define AR_PHY_ANALOG_SWAP 0xa268
#define AR_PHY_SWAP_ALT_CHAIN 0x00000040
#define AR_PHY_TPCRG5 0xA26C
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F
#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000
#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22
/* Carrier leak calibration control, do it after AGC calibration */
#define AR_PHY_CL_CAL_CTL 0xA358
#define AR_PHY_CL_CAL_ENABLE 0x00000002
#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001
#define AR_PHY_POWER_TX_RATE5 0xA38C
#define AR_PHY_POWER_TX_RATE6 0xA390
#define AR_PHY_CAL_CHAINMASK 0xA39C
#define AR_PHY_POWER_TX_SUB 0xA3C8
#define AR_PHY_POWER_TX_RATE7 0xA3CC
#define AR_PHY_POWER_TX_RATE8 0xA3D0
#define AR_PHY_POWER_TX_RATE9 0xA3D4
#define AR_PHY_XPA_CFG 0xA3D8
#define AR_PHY_FORCE_XPA_CFG 0x000000001
#define AR_PHY_FORCE_XPA_CFG_S 0
#define AR_PHY_CH1_CCA 0xa864
#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000
#define AR_PHY_CH1_MINCCA_PWR_S 19
#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000
#define AR9280_PHY_CH1_MINCCA_PWR_S 20
#define AR_PHY_CH2_CCA 0xb864
#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000
#define AR_PHY_CH2_MINCCA_PWR_S 19
#define AR_PHY_CH1_EXT_CCA 0xa9bc
#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000
#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23
#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000
#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16
#define AR_PHY_CH2_EXT_CCA 0xb9bc
#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000
#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23
#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \
int r; \
for (r = 0; r < ((iniarray)->ia_rows); r++) { \
@ -625,6 +51,7 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
#define ANTSWAP_AB 0x0001
#define REDUCE_CHAIN_0 0x00000050
#define REDUCE_CHAIN_1 0x00000051
#define AR_PHY_CHIP_ID 0x9818
#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \
int i; \
@ -632,4 +59,7 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
(_bank)[i] = INI_RA((_iniarray), i, _col);; \
} while (0)
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
#endif

View File

@ -691,6 +691,19 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
rate_table = sc->cur_rate_table;
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
/*
* If we're in HT mode and both us and our peer supports LDPC.
* We don't need to check our own device's capabilities as our own
* ht capabilities would have already been intersected with our peer's.
*/
if (conf_is_ht(&sc->hw->conf) &&
(sta->ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING))
tx_info->flags |= IEEE80211_TX_CTL_LDPC;
if (conf_is_ht(&sc->hw->conf) &&
(sta->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
tx_info->flags |= (1 << IEEE80211_TX_CTL_STBC_SHIFT);
if (is_probe) {
/* set one try for probe rates. For the
* probes don't enable rts */

View File

@ -15,6 +15,9 @@
*/
#include "ath9k.h"
#include "ar9003_mac.h"
#define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb))
static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
struct ieee80211_hdr *hdr)
@ -115,6 +118,190 @@ static void ath_opmode_init(struct ath_softc *sc)
ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
}
static bool ath_rx_edma_buf_link(struct ath_softc *sc,
enum ath9k_rx_qtype qtype)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_rx_edma *rx_edma;
struct sk_buff *skb;
struct ath_buf *bf;
rx_edma = &sc->rx.rx_edma[qtype];
if (skb_queue_len(&rx_edma->rx_fifo) >= rx_edma->rx_fifo_hwsize)
return false;
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
list_del_init(&bf->list);
skb = bf->bf_mpdu;
ATH_RXBUF_RESET(bf);
memset(skb->data, 0, ah->caps.rx_status_len);
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
ah->caps.rx_status_len, DMA_TO_DEVICE);
SKB_CB_ATHBUF(skb) = bf;
ath9k_hw_addrxbuf_edma(ah, bf->bf_buf_addr, qtype);
skb_queue_tail(&rx_edma->rx_fifo, skb);
return true;
}
static void ath_rx_addbuffer_edma(struct ath_softc *sc,
enum ath9k_rx_qtype qtype, int size)
{
struct ath_rx_edma *rx_edma;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
u32 nbuf = 0;
rx_edma = &sc->rx.rx_edma[qtype];
if (list_empty(&sc->rx.rxbuf)) {
ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n");
return;
}
while (!list_empty(&sc->rx.rxbuf)) {
nbuf++;
if (!ath_rx_edma_buf_link(sc, qtype))
break;
if (nbuf >= size)
break;
}
}
static void ath_rx_remove_buffer(struct ath_softc *sc,
enum ath9k_rx_qtype qtype)
{
struct ath_buf *bf;
struct ath_rx_edma *rx_edma;
struct sk_buff *skb;
rx_edma = &sc->rx.rx_edma[qtype];
while ((skb = skb_dequeue(&rx_edma->rx_fifo)) != NULL) {
bf = SKB_CB_ATHBUF(skb);
BUG_ON(!bf);
list_add_tail(&bf->list, &sc->rx.rxbuf);
}
}
static void ath_rx_edma_cleanup(struct ath_softc *sc)
{
struct ath_buf *bf;
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
if (bf->bf_mpdu)
dev_kfree_skb_any(bf->bf_mpdu);
}
INIT_LIST_HEAD(&sc->rx.rxbuf);
kfree(sc->rx.rx_bufptr);
sc->rx.rx_bufptr = NULL;
}
static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
{
skb_queue_head_init(&rx_edma->rx_fifo);
skb_queue_head_init(&rx_edma->rx_buffers);
rx_edma->rx_fifo_hwsize = size;
}
static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct sk_buff *skb;
struct ath_buf *bf;
int error = 0, i;
u32 size;
common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN +
ah->caps.rx_status_len,
min(common->cachelsz, (u16)64));
ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
ah->caps.rx_status_len);
ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_LP],
ah->caps.rx_lp_qdepth);
ath_rx_edma_init_queue(&sc->rx.rx_edma[ATH9K_RX_QUEUE_HP],
ah->caps.rx_hp_qdepth);
size = sizeof(struct ath_buf) * nbufs;
bf = kzalloc(size, GFP_KERNEL);
if (!bf)
return -ENOMEM;
INIT_LIST_HEAD(&sc->rx.rxbuf);
sc->rx.rx_bufptr = bf;
for (i = 0; i < nbufs; i++, bf++) {
skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL);
if (!skb) {
error = -ENOMEM;
goto rx_init_fail;
}
memset(skb->data, 0, common->rx_bufsize);
bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
common->rx_bufsize,
DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(sc->dev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
goto rx_init_fail;
}
list_add_tail(&bf->list, &sc->rx.rxbuf);
}
return 0;
rx_init_fail:
ath_rx_edma_cleanup(sc);
return error;
}
static void ath_edma_start_recv(struct ath_softc *sc)
{
spin_lock_bh(&sc->rx.rxbuflock);
ath9k_hw_rxena(sc->sc_ah);
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
sc->rx.rx_edma[ATH9K_RX_QUEUE_HP].rx_fifo_hwsize);
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
spin_unlock_bh(&sc->rx.rxbuflock);
ath_opmode_init(sc);
ath9k_hw_startpcureceive(sc->sc_ah);
}
static void ath_edma_stop_recv(struct ath_softc *sc)
{
spin_lock_bh(&sc->rx.rxbuflock);
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
spin_unlock_bh(&sc->rx.rxbuflock);
}
int ath_rx_init(struct ath_softc *sc, int nbufs)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@ -126,45 +313,51 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_lock_init(&sc->rx.rxbuflock);
common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
min(common->cachelsz, (u16)64));
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
return ath_rx_edma_init(sc, nbufs);
} else {
common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
min(common->cachelsz, (u16)64));
ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
common->cachelsz, common->rx_bufsize);
ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
common->cachelsz, common->rx_bufsize);
/* Initialize rx descriptors */
/* Initialize rx descriptors */
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
"rx", nbufs, 1);
if (error != 0) {
ath_print(common, ATH_DBG_FATAL,
"failed to allocate rx descriptors: %d\n", error);
goto err;
}
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL);
if (skb == NULL) {
error = -ENOMEM;
goto err;
}
bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
common->rx_bufsize,
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(sc->dev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
"rx", nbufs, 1, 0);
if (error != 0) {
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
"failed to allocate rx descriptors: %d\n",
error);
goto err;
}
bf->bf_dmacontext = bf->bf_buf_addr;
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = ath_rxbuf_alloc(common, common->rx_bufsize,
GFP_KERNEL);
if (skb == NULL) {
error = -ENOMEM;
goto err;
}
bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
common->rx_bufsize,
DMA_FROM_DEVICE);
if (unlikely(dma_mapping_error(sc->dev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX init\n");
error = -ENOMEM;
goto err;
}
bf->bf_dmacontext = bf->bf_buf_addr;
}
sc->rx.rxlink = NULL;
}
sc->rx.rxlink = NULL;
err:
if (error)
@ -180,17 +373,23 @@ void ath_rx_cleanup(struct ath_softc *sc)
struct sk_buff *skb;
struct ath_buf *bf;
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = bf->bf_mpdu;
if (skb) {
dma_unmap_single(sc->dev, bf->bf_buf_addr,
common->rx_bufsize, DMA_FROM_DEVICE);
dev_kfree_skb(skb);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
ath_rx_edma_cleanup(sc);
return;
} else {
list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = bf->bf_mpdu;
if (skb) {
dma_unmap_single(sc->dev, bf->bf_buf_addr,
common->rx_bufsize,
DMA_FROM_DEVICE);
dev_kfree_skb(skb);
}
}
}
if (sc->rx.rxdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
if (sc->rx.rxdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
}
}
/*
@ -273,6 +472,11 @@ int ath_startrecv(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
struct ath_buf *bf, *tbf;
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
ath_edma_start_recv(sc);
return 0;
}
spin_lock_bh(&sc->rx.rxbuflock);
if (list_empty(&sc->rx.rxbuf))
goto start_recv;
@ -306,7 +510,11 @@ bool ath_stoprecv(struct ath_softc *sc)
ath9k_hw_stoppcurecv(ah);
ath9k_hw_setrxfilter(ah, 0);
stopped = ath9k_hw_stopdmarecv(ah);
sc->rx.rxlink = NULL;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ath_edma_stop_recv(sc);
else
sc->rx.rxlink = NULL;
return stopped;
}
@ -315,7 +523,9 @@ void ath_flushrecv(struct ath_softc *sc)
{
spin_lock_bh(&sc->rx.rxflushlock);
sc->sc_flags |= SC_OP_RXFLUSH;
ath_rx_tasklet(sc, 1);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ath_rx_tasklet(sc, 1, true);
ath_rx_tasklet(sc, 1, false);
sc->sc_flags &= ~SC_OP_RXFLUSH;
spin_unlock_bh(&sc->rx.rxflushlock);
}
@ -469,14 +679,147 @@ static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
ieee80211_rx(hw, skb);
}
int ath_rx_tasklet(struct ath_softc *sc, int flush)
static bool ath_edma_get_buffers(struct ath_softc *sc,
enum ath9k_rx_qtype qtype)
{
#define PA2DESC(_sc, _pa) \
((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \
((_pa) - (_sc)->rx.rxdma.dd_desc_paddr)))
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct sk_buff *skb;
struct ath_buf *bf;
int ret;
skb = skb_peek(&rx_edma->rx_fifo);
if (!skb)
return false;
bf = SKB_CB_ATHBUF(skb);
BUG_ON(!bf);
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
common->rx_bufsize, DMA_FROM_DEVICE);
ret = ath9k_hw_process_rxdesc_edma(ah, NULL, skb->data);
if (ret == -EINPROGRESS)
return false;
__skb_unlink(skb, &rx_edma->rx_fifo);
if (ret == -EINVAL) {
/* corrupt descriptor, skip this one and the following one */
list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype);
skb = skb_peek(&rx_edma->rx_fifo);
if (!skb)
return true;
bf = SKB_CB_ATHBUF(skb);
BUG_ON(!bf);
__skb_unlink(skb, &rx_edma->rx_fifo);
list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype);
}
skb_queue_tail(&rx_edma->rx_buffers, skb);
return true;
}
static struct ath_buf *ath_edma_get_next_rx_buf(struct ath_softc *sc,
struct ath_rx_status *rs,
enum ath9k_rx_qtype qtype)
{
struct ath_rx_edma *rx_edma = &sc->rx.rx_edma[qtype];
struct sk_buff *skb;
struct ath_buf *bf;
while (ath_edma_get_buffers(sc, qtype));
skb = __skb_dequeue(&rx_edma->rx_buffers);
if (!skb)
return NULL;
bf = SKB_CB_ATHBUF(skb);
ath9k_hw_process_rxdesc_edma(sc->sc_ah, rs, skb->data);
return bf;
}
static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
struct ath_rx_status *rs)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath_desc *ds;
struct ath_buf *bf;
int ret;
if (list_empty(&sc->rx.rxbuf)) {
sc->rx.rxlink = NULL;
return NULL;
}
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
ds = bf->bf_desc;
/*
* Must provide the virtual address of the current
* descriptor, the physical address, and the virtual
* address of the next descriptor in the h/w chain.
* This allows the HAL to look ahead to see if the
* hardware is done with a descriptor by checking the
* done bit in the following descriptor and the address
* of the current descriptor the DMA engine is working
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);
if (ret == -EINPROGRESS) {
struct ath_rx_status trs;
struct ath_buf *tbf;
struct ath_desc *tds;
memset(&trs, 0, sizeof(trs));
if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
sc->rx.rxlink = NULL;
return NULL;
}
tbf = list_entry(bf->list.next, struct ath_buf, list);
/*
* On some hardware the descriptor status words could
* get corrupted, including the done bit. Because of
* this, check if the next descriptor's done bit is
* set or not.
*
* If the next descriptor's done bit is set, the current
* descriptor has been corrupted. Force s/w to discard
* this descriptor and continue...
*/
tds = tbf->bf_desc;
ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
if (ret == -EINPROGRESS)
return NULL;
}
if (!bf->bf_mpdu)
return bf;
/*
* Synchronize the DMA transfer with CPU before
* 1. accessing the frame
* 2. requeueing the same buffer to h/w
*/
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
common->rx_bufsize,
DMA_FROM_DEVICE);
return bf;
}
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
{
struct ath_buf *bf;
struct sk_buff *skb = NULL, *requeue_skb;
struct ieee80211_rx_status *rxs;
struct ath_hw *ah = sc->sc_ah;
@ -491,7 +834,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
int retval;
bool decrypt_error = false;
struct ath_rx_status rs;
enum ath9k_rx_qtype qtype;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int dma_type;
if (edma)
dma_type = DMA_FROM_DEVICE;
else
dma_type = DMA_BIDIRECTIONAL;
qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
spin_lock_bh(&sc->rx.rxbuflock);
do {
@ -499,71 +851,19 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
break;
if (list_empty(&sc->rx.rxbuf)) {
sc->rx.rxlink = NULL;
break;
}
bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
ds = bf->bf_desc;
/*
* Must provide the virtual address of the current
* descriptor, the physical address, and the virtual
* address of the next descriptor in the h/w chain.
* This allows the HAL to look ahead to see if the
* hardware is done with a descriptor by checking the
* done bit in the following descriptor and the address
* of the current descriptor the DMA engine is working
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
memset(&rs, 0, sizeof(rs));
retval = ath9k_hw_rxprocdesc(ah, ds, &rs, 0);
if (retval == -EINPROGRESS) {
struct ath_rx_status trs;
struct ath_buf *tbf;
struct ath_desc *tds;
if (edma)
bf = ath_edma_get_next_rx_buf(sc, &rs, qtype);
else
bf = ath_get_next_rx_buf(sc, &rs);
memset(&trs, 0, sizeof(trs));
if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
sc->rx.rxlink = NULL;
break;
}
tbf = list_entry(bf->list.next, struct ath_buf, list);
/*
* On some hardware the descriptor status words could
* get corrupted, including the done bit. Because of
* this, check if the next descriptor's done bit is
* set or not.
*
* If the next descriptor's done bit is set, the current
* descriptor has been corrupted. Force s/w to discard
* this descriptor and continue...
*/
tds = tbf->bf_desc;
retval = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
if (retval == -EINPROGRESS) {
break;
}
}
if (!bf)
break;
skb = bf->bf_mpdu;
if (!skb)
continue;
/*
* Synchronize the DMA transfer with CPU before
* 1. accessing the frame
* 2. requeueing the same buffer to h/w
*/
dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
common->rx_bufsize,
DMA_FROM_DEVICE);
hdr = (struct ieee80211_hdr *) skb->data;
rxs = IEEE80211_SKB_RXCB(skb);
@ -597,9 +897,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
/* Unmap the frame */
dma_unmap_single(sc->dev, bf->bf_buf_addr,
common->rx_bufsize,
DMA_FROM_DEVICE);
dma_type);
skb_put(skb, rs.rs_datalen);
skb_put(skb, rs.rs_datalen + ah->caps.rx_status_len);
if (ah->caps.rx_status_len)
skb_pull(skb, ah->caps.rx_status_len);
ath9k_cmn_rx_skb_postprocess(common, skb, &rs,
rxs, decrypt_error);
@ -608,7 +910,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
bf->bf_mpdu = requeue_skb;
bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
common->rx_bufsize,
DMA_FROM_DEVICE);
dma_type);
if (unlikely(dma_mapping_error(sc->dev,
bf->bf_buf_addr))) {
dev_kfree_skb_any(requeue_skb);
@ -639,12 +941,16 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
ath_rx_send_to_mac80211(hw, sc, skb, rxs);
requeue:
list_move_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_buf_link(sc, bf);
if (edma) {
list_add_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_edma_buf_link(sc, qtype);
} else {
list_move_tail(&bf->list, &sc->rx.rxbuf);
ath_rx_buf_link(sc, bf);
}
} while (1);
spin_unlock_bh(&sc->rx.rxbuflock);
return 0;
#undef PA2DESC
}

View File

@ -20,7 +20,7 @@
#include "../reg.h"
#define AR_CR 0x0008
#define AR_CR_RXE 0x00000004
#define AR_CR_RXE (AR_SREV_9300_20_OR_LATER(ah) ? 0x0000000c : 0x00000004)
#define AR_CR_RXD 0x00000020
#define AR_CR_SWI 0x00000040
@ -39,6 +39,12 @@
#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000
#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17
#define AR_RXBP_THRESH 0x0018
#define AR_RXBP_THRESH_HP 0x0000000f
#define AR_RXBP_THRESH_HP_S 0
#define AR_RXBP_THRESH_LP 0x00003f00
#define AR_RXBP_THRESH_LP_S 8
#define AR_MIRT 0x0020
#define AR_MIRT_VAL 0x0000ffff
#define AR_MIRT_VAL_S 16
@ -144,6 +150,9 @@
#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15
#define AR_MACMISC_MISC_OBS_BUS_1 1
#define AR_DATABUF_SIZE 0x0060
#define AR_DATABUF_SIZE_MASK 0x00000FFF
#define AR_GTXTO 0x0064
#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF
#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000
@ -160,9 +169,14 @@
#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000
#define AR_CST_TIMEOUT_LIMIT_S 16
#define AR_HP_RXDP 0x0074
#define AR_LP_RXDP 0x0078
#define AR_ISR 0x0080
#define AR_ISR_RXOK 0x00000001
#define AR_ISR_RXDESC 0x00000002
#define AR_ISR_HP_RXOK 0x00000001
#define AR_ISR_LP_RXOK 0x00000002
#define AR_ISR_RXERR 0x00000004
#define AR_ISR_RXNOPKT 0x00000008
#define AR_ISR_RXEOL 0x00000010
@ -232,7 +246,6 @@
#define AR_ISR_S5_TIMER_THRESH 0x0007FE00
#define AR_ISR_S5_TIM_TIMER 0x00000010
#define AR_ISR_S5_DTIM_TIMER 0x00000020
#define AR_ISR_S5_S 0x00d8
#define AR_IMR_S5 0x00b8
#define AR_IMR_S5_TIM_TIMER 0x00000010
#define AR_IMR_S5_DTIM_TIMER 0x00000020
@ -240,7 +253,6 @@
#define AR_ISR_S5_GENTIMER_TRIG_S 0
#define AR_ISR_S5_GENTIMER_THRESH 0xFF800000
#define AR_ISR_S5_GENTIMER_THRESH_S 16
#define AR_ISR_S5_S 0x00d8
#define AR_IMR_S5_GENTIMER_TRIG 0x0000FF80
#define AR_IMR_S5_GENTIMER_TRIG_S 0
#define AR_IMR_S5_GENTIMER_THRESH 0xFF800000
@ -249,6 +261,8 @@
#define AR_IMR 0x00a0
#define AR_IMR_RXOK 0x00000001
#define AR_IMR_RXDESC 0x00000002
#define AR_IMR_RXOK_HP 0x00000001
#define AR_IMR_RXOK_LP 0x00000002
#define AR_IMR_RXERR 0x00000004
#define AR_IMR_RXNOPKT 0x00000008
#define AR_IMR_RXEOL 0x00000010
@ -332,10 +346,10 @@
#define AR_ISR_S1_QCU_TXEOL 0x03FF0000
#define AR_ISR_S1_QCU_TXEOL_S 16
#define AR_ISR_S2_S 0x00cc
#define AR_ISR_S3_S 0x00d0
#define AR_ISR_S4_S 0x00d4
#define AR_ISR_S5_S 0x00d8
#define AR_ISR_S2_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d0 : 0x00cc)
#define AR_ISR_S3_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d4 : 0x00d0)
#define AR_ISR_S4_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00d8 : 0x00d4)
#define AR_ISR_S5_S (AR_SREV_9300_20_OR_LATER(ah) ? 0x00dc : 0x00d8)
#define AR_DMADBG_0 0x00e0
#define AR_DMADBG_1 0x00e4
#define AR_DMADBG_2 0x00e8
@ -369,6 +383,9 @@
#define AR_Q9_TXDP 0x0824
#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2))
#define AR_Q_STATUS_RING_START 0x830
#define AR_Q_STATUS_RING_END 0x834
#define AR_Q_TXE 0x0840
#define AR_Q_TXE_M 0x000003FF
@ -461,6 +478,10 @@
#define AR_Q_RDYTIMESHDN 0x0a40
#define AR_Q_RDYTIMESHDN_M 0x000003FF
/* MAC Descriptor CRC check */
#define AR_Q_DESC_CRCCHK 0xa44
/* Enable CRC check on the descriptor fetched from host */
#define AR_Q_DESC_CRCCHK_EN 1
#define AR_NUM_DCU 10
#define AR_DCU_0 0x0001
@ -759,6 +780,8 @@
#define AR_SREV_VERSION_9271 0x140
#define AR_SREV_REVISION_9271_10 0
#define AR_SREV_REVISION_9271_11 1
#define AR_SREV_VERSION_9300 0x1c0
#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@ -844,6 +867,15 @@
#define AR_SREV_9271_11(_ah) \
(AR_SREV_9271(_ah) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
#define AR_SREV_9300(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
#define AR_SREV_9300_20(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20))
#define AR_SREV_9300_20_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9300_20)))
#define AR_SREV_9285E_20(_ah) \
(AR_SREV_9285_12_OR_LATER(_ah) && \
@ -945,6 +977,7 @@ enum {
#define AR9285_NUM_GPIO 12
#define AR9287_NUM_GPIO 11
#define AR9271_NUM_GPIO 16
#define AR9300_NUM_GPIO 17
#define AR_GPIO_IN_OUT 0x4048
#define AR_GPIO_IN_VAL 0x0FFFC000
@ -957,19 +990,21 @@ enum {
#define AR9287_GPIO_IN_VAL_S 11
#define AR9271_GPIO_IN_VAL 0xFFFF0000
#define AR9271_GPIO_IN_VAL_S 16
#define AR9300_GPIO_IN_VAL 0x0001FFFF
#define AR9300_GPIO_IN_VAL_S 0
#define AR_GPIO_OE_OUT 0x404c
#define AR_GPIO_OE_OUT (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)
#define AR_GPIO_OE_OUT_DRV 0x3
#define AR_GPIO_OE_OUT_DRV_NO 0x0
#define AR_GPIO_OE_OUT_DRV_LOW 0x1
#define AR_GPIO_OE_OUT_DRV_HI 0x2
#define AR_GPIO_OE_OUT_DRV_ALL 0x3
#define AR_GPIO_INTR_POL 0x4050
#define AR_GPIO_INTR_POL_VAL 0x00001FFF
#define AR_GPIO_INTR_POL (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)
#define AR_GPIO_INTR_POL_VAL 0x0001FFFF
#define AR_GPIO_INTR_POL_VAL_S 0
#define AR_GPIO_INPUT_EN_VAL 0x4054
#define AR_GPIO_INPUT_EN_VAL (AR_SREV_9300_20_OR_LATER(ah) ? 0x405c : 0x4054)
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004
#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2
#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008
@ -987,13 +1022,13 @@ enum {
#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000
#define AR_GPIO_JTAG_DISABLE 0x00020000
#define AR_GPIO_INPUT_MUX1 0x4058
#define AR_GPIO_INPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4060 : 0x4058)
#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000
#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16
#define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00
#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8
#define AR_GPIO_INPUT_MUX2 0x405c
#define AR_GPIO_INPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4064 : 0x405c)
#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f
#define AR_GPIO_INPUT_MUX2_CLK25_S 0
#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0
@ -1001,13 +1036,13 @@ enum {
#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00
#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8
#define AR_GPIO_OUTPUT_MUX1 0x4060
#define AR_GPIO_OUTPUT_MUX2 0x4064
#define AR_GPIO_OUTPUT_MUX3 0x4068
#define AR_GPIO_OUTPUT_MUX1 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4068 : 0x4060)
#define AR_GPIO_OUTPUT_MUX2 (AR_SREV_9300_20_OR_LATER(ah) ? 0x406c : 0x4064)
#define AR_GPIO_OUTPUT_MUX3 (AR_SREV_9300_20_OR_LATER(ah) ? 0x4070 : 0x4068)
#define AR_INPUT_STATE 0x406c
#define AR_INPUT_STATE (AR_SREV_9300_20_OR_LATER(ah) ? 0x4074 : 0x406c)
#define AR_EEPROM_STATUS_DATA 0x407c
#define AR_EEPROM_STATUS_DATA (AR_SREV_9300_20_OR_LATER(ah) ? 0x4084 : 0x407c)
#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff
#define AR_EEPROM_STATUS_DATA_VAL_S 0
#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000
@ -1015,13 +1050,24 @@ enum {
#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000
#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000
#define AR_OBS 0x4080
#define AR_OBS (AR_SREV_9300_20_OR_LATER(ah) ? 0x4088 : 0x4080)
#define AR_GPIO_PDPU 0x4088
#define AR_GPIO_PDPU (AR_SREV_9300_20_OR_LATER(ah) ? 0x4090 : 0x4088)
#define AR_PCIE_MSI 0x4094
#define AR_PCIE_MSI (AR_SREV_9300_20_OR_LATER(ah) ? 0x40a4 : 0x4094)
#define AR_PCIE_MSI_ENABLE 0x00000001
#define AR_INTR_PRIO_SYNC_ENABLE 0x40c4
#define AR_INTR_PRIO_ASYNC_MASK 0x40c8
#define AR_INTR_PRIO_SYNC_MASK 0x40cc
#define AR_INTR_PRIO_ASYNC_ENABLE 0x40d4
#define AR_RTC_9300_PLL_DIV 0x000003ff
#define AR_RTC_9300_PLL_DIV_S 0
#define AR_RTC_9300_PLL_REFDIV 0x00003C00
#define AR_RTC_9300_PLL_REFDIV_S 10
#define AR_RTC_9300_PLL_CLKSEL 0x0000C000
#define AR_RTC_9300_PLL_CLKSEL_S 14
#define AR_RTC_9160_PLL_DIV 0x000003ff
#define AR_RTC_9160_PLL_DIV_S 0
@ -1039,6 +1085,16 @@ enum {
#define AR_RTC_RC_COLD_RESET 0x00000004
#define AR_RTC_RC_WARM_RESET 0x00000008
/* Crystal Control */
#define AR_RTC_XTAL_CONTROL 0x7004
/* Reg Control 0 */
#define AR_RTC_REG_CONTROL0 0x7008
/* Reg Control 1 */
#define AR_RTC_REG_CONTROL1 0x700c
#define AR_RTC_REG_CONTROL1_SWREG_PROGRAM 0x00000001
#define AR_RTC_PLL_CONTROL \
((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014)
@ -1069,6 +1125,7 @@ enum {
#define AR_RTC_SLEEP_CLK \
((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048)
#define AR_RTC_FORCE_DERIVED_CLK 0x2
#define AR_RTC_FORCE_SWREG_PRD 0x00000004
#define AR_RTC_FORCE_WAKE \
((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c)
@ -1533,7 +1590,7 @@ enum {
#define AR_TSFOOR_THRESHOLD 0x813c
#define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF
#define AR_PHY_ERR_EIFS_MASK 8144
#define AR_PHY_ERR_EIFS_MASK 0x8144
#define AR_PHY_ERR_3 0x8168
#define AR_PHY_ERR_3_COUNT 0x00FFFFFF
@ -1599,24 +1656,26 @@ enum {
#define AR_FIRST_NDP_TIMER 7
#define AR_NDP2_PERIOD 0x81a0
#define AR_NDP2_TIMER_MODE 0x81c0
#define AR_NEXT_TBTT_TIMER 0x8200
#define AR_NEXT_DMA_BEACON_ALERT 0x8204
#define AR_NEXT_SWBA 0x8208
#define AR_NEXT_CFP 0x8208
#define AR_NEXT_HCF 0x820C
#define AR_NEXT_TIM 0x8210
#define AR_NEXT_DTIM 0x8214
#define AR_NEXT_QUIET_TIMER 0x8218
#define AR_NEXT_NDP_TIMER 0x821C
#define AR_BEACON_PERIOD 0x8220
#define AR_DMA_BEACON_PERIOD 0x8224
#define AR_SWBA_PERIOD 0x8228
#define AR_HCF_PERIOD 0x822C
#define AR_TIM_PERIOD 0x8230
#define AR_DTIM_PERIOD 0x8234
#define AR_QUIET_PERIOD 0x8238
#define AR_NDP_PERIOD 0x823C
#define AR_GEN_TIMERS(_i) (0x8200 + ((_i) << 2))
#define AR_NEXT_TBTT_TIMER AR_GEN_TIMERS(0)
#define AR_NEXT_DMA_BEACON_ALERT AR_GEN_TIMERS(1)
#define AR_NEXT_SWBA AR_GEN_TIMERS(2)
#define AR_NEXT_CFP AR_GEN_TIMERS(2)
#define AR_NEXT_HCF AR_GEN_TIMERS(3)
#define AR_NEXT_TIM AR_GEN_TIMERS(4)
#define AR_NEXT_DTIM AR_GEN_TIMERS(5)
#define AR_NEXT_QUIET_TIMER AR_GEN_TIMERS(6)
#define AR_NEXT_NDP_TIMER AR_GEN_TIMERS(7)
#define AR_BEACON_PERIOD AR_GEN_TIMERS(8)
#define AR_DMA_BEACON_PERIOD AR_GEN_TIMERS(9)
#define AR_SWBA_PERIOD AR_GEN_TIMERS(10)
#define AR_HCF_PERIOD AR_GEN_TIMERS(11)
#define AR_TIM_PERIOD AR_GEN_TIMERS(12)
#define AR_DTIM_PERIOD AR_GEN_TIMERS(13)
#define AR_QUIET_PERIOD AR_GEN_TIMERS(14)
#define AR_NDP_PERIOD AR_GEN_TIMERS(15)
#define AR_TIMER_MODE 0x8240
#define AR_TBTT_TIMER_EN 0x00000001
@ -1730,4 +1789,32 @@ enum {
#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */
#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */
#define AR_AGG_WEP_ENABLE_FIX 0x00000008 /* This allows the use of AR_AGG_WEP_ENABLE */
#define AR_ADHOC_MCAST_KEYID_ENABLE 0x00000040 /* This bit enables the Multicast search
* based on both MAC Address and Key ID.
* If bit is 0, then Multicast search is
* based on MAC address only.
* For Merlin and above only.
*/
#define AR_AGG_WEP_ENABLE 0x00020000 /* This field enables AGG_WEP feature,
* when it is enable, AGG_WEP would takes
* charge of the encryption interface of
* pcu_txsm.
*/
#define AR9300_SM_BASE 0xa200
#define AR9002_PHY_AGC_CONTROL 0x9860
#define AR9003_PHY_AGC_CONTROL AR9300_SM_BASE + 0xc4
#define AR_PHY_AGC_CONTROL (AR_SREV_9300_20_OR_LATER(ah) ? AR9003_PHY_AGC_CONTROL : AR9002_PHY_AGC_CONTROL)
#define AR_PHY_AGC_CONTROL_CAL 0x00000001 /* do internal calibration */
#define AR_PHY_AGC_CONTROL_NF 0x00000002 /* do noise-floor calibration */
#define AR_PHY_AGC_CONTROL_OFFSET_CAL 0x00000800 /* allow offset calibration */
#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 /* enable noise floor calibration to happen */
#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 /* allow tx filter calibration */
#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 /* don't update noise floor automatically */
#define AR_PHY_AGC_CONTROL_EXT_NF_PWR_MEAS 0x00040000 /* extend noise floor power measurement */
#define AR_PHY_AGC_CONTROL_CLC_SUCCESS 0x00080000 /* carrier leak calibration done */
#define AR_PHY_AGC_CONTROL_YCOK_MAX 0x000003c0
#define AR_PHY_AGC_CONTROL_YCOK_MAX_S 6
#endif

View File

@ -101,6 +101,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)
wmi->drv_priv = priv;
wmi->stopped = false;
mutex_init(&wmi->op_mutex);
mutex_init(&wmi->multi_write_mutex);
init_completion(&wmi->cmd_wait);
return wmi;
@ -128,7 +129,7 @@ void ath9k_wmi_tasklet(unsigned long data)
void *wmi_event;
unsigned long flags;
#ifdef CONFIG_ATH9K_HTC_DEBUGFS
u32 txrate;
__be32 txrate;
#endif
spin_lock_irqsave(&priv->wmi->wmi_lock, flags);
@ -203,6 +204,14 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb,
return;
}
/* Check if there has been a timeout. */
spin_lock(&wmi->wmi_lock);
if (cmd_id != wmi->last_cmd_id) {
spin_unlock(&wmi->wmi_lock);
goto free_skb;
}
spin_unlock(&wmi->wmi_lock);
/* WMI command response */
ath9k_wmi_rsp_callback(wmi, skb);
@ -265,6 +274,7 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
struct sk_buff *skb;
u8 *data;
int time_left, ret = 0;
unsigned long flags;
if (!wmi)
return -EINVAL;
@ -296,6 +306,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
if (ret)
goto out;
spin_lock_irqsave(&wmi->wmi_lock, flags);
wmi->last_cmd_id = cmd_id;
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
if (!time_left) {
ath_print(common, ATH_DBG_WMI,

View File

@ -19,7 +19,7 @@
struct wmi_event_txrate {
u32 txrate;
__be32 txrate;
struct {
u8 rssi_thresh;
u8 per;
@ -27,8 +27,8 @@ struct wmi_event_txrate {
} __packed;
struct wmi_cmd_hdr {
u16 command_id;
u16 seq_no;
__be16 command_id;
__be16 seq_no;
} __packed;
struct wmi_swba {
@ -84,12 +84,20 @@ enum wmi_event_id {
WMI_TXRATE_EVENTID,
};
#define MAX_CMD_NUMBER 62
struct register_write {
__be32 reg;
__be32 val;
};
struct wmi {
struct ath9k_htc_priv *drv_priv;
struct htc_target *htc;
enum htc_endpoint_id ctrl_epid;
struct mutex op_mutex;
struct completion cmd_wait;
enum wmi_cmd_id last_cmd_id;
u16 tx_seq_id;
u8 *cmd_rsp_buf;
u32 cmd_rsp_len;
@ -97,6 +105,11 @@ struct wmi {
struct sk_buff *wmi_skb;
spinlock_t wmi_lock;
atomic_t mwrite_cnt;
struct register_write multi_write[MAX_CMD_NUMBER];
u32 multi_write_idx;
struct mutex multi_write_mutex;
};
struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv);

View File

@ -15,10 +15,11 @@
*/
#include "ath9k.h"
#include "ar9003_mac.h"
#define BITS_PER_BYTE 8
#define OFDM_PLCP_BITS 22
#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f)
#define HT_RC_2_MCS(_rc) ((_rc) & 0x1f)
#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
#define L_STF 8
#define L_LTF 8
@ -33,7 +34,7 @@
#define OFDM_SIFS_TIME 16
static u32 bits_per_symbol[][2] = {
static u16 bits_per_symbol[][2] = {
/* 20MHz 40MHz */
{ 26, 54 }, /* 0: BPSK */
{ 52, 108 }, /* 1: QPSK 1/2 */
@ -43,14 +44,6 @@ static u32 bits_per_symbol[][2] = {
{ 208, 432 }, /* 5: 64-QAM 2/3 */
{ 234, 486 }, /* 6: 64-QAM 3/4 */
{ 260, 540 }, /* 7: 64-QAM 5/6 */
{ 52, 108 }, /* 8: BPSK */
{ 104, 216 }, /* 9: QPSK 1/2 */
{ 156, 324 }, /* 10: QPSK 3/4 */
{ 208, 432 }, /* 11: 16-QAM 1/2 */
{ 312, 648 }, /* 12: 16-QAM 3/4 */
{ 416, 864 }, /* 13: 64-QAM 2/3 */
{ 468, 972 }, /* 14: 64-QAM 3/4 */
{ 520, 1080 }, /* 15: 64-QAM 5/6 */
};
#define IS_HT_RATE(_rate) ((_rate) & 0x80)
@ -70,28 +63,39 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
int nbad, int txok, bool update_rc);
enum {
MCS_DEFAULT,
MCS_HT20,
MCS_HT20_SGI,
MCS_HT40,
MCS_HT40_SGI,
};
static int ath_max_4ms_framelen[3][16] = {
[MCS_DEFAULT] = {
3216, 6434, 9650, 12868, 19304, 25740, 28956, 32180,
6430, 12860, 19300, 25736, 38600, 51472, 57890, 64320,
static int ath_max_4ms_framelen[4][32] = {
[MCS_HT20] = {
3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172,
6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280,
9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532,
12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532,
},
[MCS_HT20_SGI] = {
3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744,
7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532,
10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532,
14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532,
},
[MCS_HT40] = {
6684, 13368, 20052, 26738, 40104, 53476, 60156, 66840,
13360, 26720, 40080, 53440, 80160, 106880, 120240, 133600,
6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532,
13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532,
20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532,
26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532,
},
[MCS_HT40_SGI] = {
/* TODO: Only MCS 7 and 15 updated, recalculate the rest */
6684, 13368, 20052, 26738, 40104, 53476, 60156, 74200,
13360, 26720, 40080, 53440, 80160, 106880, 120240, 148400,
7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532,
14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532,
22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532,
29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532,
}
};
/*********************/
/* Aggregation logic */
/*********************/
@ -261,25 +265,46 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
}
static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
{
struct ath_buf *bf = NULL;
spin_lock_bh(&sc->tx.txbuflock);
if (unlikely(list_empty(&sc->tx.txbuf))) {
spin_unlock_bh(&sc->tx.txbuflock);
return NULL;
}
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
list_del(&bf->list);
spin_unlock_bh(&sc->tx.txbuflock);
return bf;
}
static void ath_tx_return_buffer(struct ath_softc *sc, struct ath_buf *bf)
{
spin_lock_bh(&sc->tx.txbuflock);
list_add_tail(&bf->list, &sc->tx.txbuf);
spin_unlock_bh(&sc->tx.txbuflock);
}
static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
{
struct ath_buf *tbf;
spin_lock_bh(&sc->tx.txbuflock);
if (WARN_ON(list_empty(&sc->tx.txbuf))) {
spin_unlock_bh(&sc->tx.txbuflock);
tbf = ath_tx_get_buffer(sc);
if (WARN_ON(!tbf))
return NULL;
}
tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
list_del(&tbf->list);
spin_unlock_bh(&sc->tx.txbuflock);
ATH_TXBUF_RESET(tbf);
tbf->aphy = bf->aphy;
tbf->bf_mpdu = bf->bf_mpdu;
tbf->bf_buf_addr = bf->bf_buf_addr;
*(tbf->bf_desc) = *(bf->bf_desc);
memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
tbf->bf_state = bf->bf_state;
tbf->bf_dmacontext = bf->bf_dmacontext;
@ -359,7 +384,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
acked_cnt++;
} else {
if (!(tid->state & AGGR_CLEANUP) &&
ts->ts_flags != ATH9K_TX_SW_ABORTED) {
!bf_last->bf_tx_aborted) {
if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
ath_tx_set_retry(sc, txq, bf);
txpending = 1;
@ -378,7 +403,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
}
}
if (bf_next == NULL) {
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
bf_next == NULL) {
/*
* Make sure the last desc is reclaimed if it
* not a holding desc.
@ -412,36 +438,43 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
!txfail, sendbar);
} else {
/* retry the un-acked ones */
if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
if (bf->bf_next == NULL && bf_last->bf_stale) {
struct ath_buf *tbf;
tbf = ath_clone_txbuf(sc, bf_last);
/*
* Update tx baw and complete the frame with
* failed status if we run out of tx buf
*/
if (!tbf) {
spin_lock_bh(&txq->axq_lock);
ath_tx_update_baw(sc, tid,
bf->bf_seqno);
spin_unlock_bh(&txq->axq_lock);
tbf = ath_clone_txbuf(sc, bf_last);
/*
* Update tx baw and complete the
* frame with failed status if we
* run out of tx buf.
*/
if (!tbf) {
spin_lock_bh(&txq->axq_lock);
ath_tx_update_baw(sc, tid,
bf->bf_seqno);
spin_unlock_bh(&txq->axq_lock);
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, ts, nbad,
0, false);
ath_tx_complete_buf(sc, bf, txq,
&bf_head, ts, 0, 0);
break;
bf->bf_state.bf_type |=
BUF_XRETRY;
ath_tx_rc_status(bf, ts, nbad,
0, false);
ath_tx_complete_buf(sc, bf, txq,
&bf_head,
ts, 0, 0);
break;
}
ath9k_hw_cleartxdesc(sc->sc_ah,
tbf->bf_desc);
list_add_tail(&tbf->list, &bf_head);
} else {
/*
* Clear descriptor status words for
* software retry
*/
ath9k_hw_cleartxdesc(sc->sc_ah,
bf->bf_desc);
}
ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc);
list_add_tail(&tbf->list, &bf_head);
} else {
/*
* Clear descriptor status words for
* software retry
*/
ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc);
}
/*
@ -509,12 +542,13 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
break;
}
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
modeidx = MCS_HT40_SGI;
else if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
modeidx = MCS_HT40;
else
modeidx = MCS_DEFAULT;
modeidx = MCS_HT20;
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
modeidx++;
frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
max_4ms_framelen = min(max_4ms_framelen, frmlen);
@ -559,7 +593,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
u32 nsymbits, nsymbols;
u16 minlen;
u8 flags, rix;
int width, half_gi, ndelim, mindelim;
int width, streams, half_gi, ndelim, mindelim;
/* Select standard number of delimiters based on frame length alone */
ndelim = ATH_AGGR_GET_NDELIM(frmlen);
@ -599,7 +633,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
if (nsymbols == 0)
nsymbols = 1;
nsymbits = bits_per_symbol[rix][width];
streams = HT_RC_2_STREAMS(rix);
nsymbits = bits_per_symbol[rix % 8][width] * streams;
minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
if (frmlen < minlen) {
@ -665,7 +700,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bpad = PADBYTES(al_delta) + (ndelim << 2);
bf->bf_next = NULL;
bf->bf_desc->ds_link = 0;
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
/* link buffers of this frame to the aggregate */
ath_tx_addto_baw(sc, tid, bf);
@ -673,7 +708,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
list_move_tail(&bf->list, bf_q);
if (bf_prev) {
bf_prev->bf_next = bf;
bf_prev->bf_desc->ds_link = bf->bf_daddr;
ath9k_hw_set_desc_link(sc->sc_ah, bf_prev->bf_desc,
bf->bf_daddr);
}
bf_prev = bf;
@ -853,7 +889,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_tx_queue_info qi;
int qnum;
int qnum, i;
memset(&qi, 0, sizeof(qi));
qi.tqi_subtype = subtype;
@ -877,11 +913,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
* The UAPSD queue is an exception, since we take a desc-
* based intr on the EOSP frames.
*/
if (qtype == ATH9K_TX_QUEUE_UAPSD)
qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
else
qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
TXQ_FLAG_TXDESCINT_ENABLE;
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
qi.tqi_qflags = TXQ_FLAG_TXOKINT_ENABLE |
TXQ_FLAG_TXERRINT_ENABLE;
} else {
if (qtype == ATH9K_TX_QUEUE_UAPSD)
qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE;
else
qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
TXQ_FLAG_TXDESCINT_ENABLE;
}
qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
if (qnum == -1) {
/*
@ -908,6 +949,11 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
txq->axq_depth = 0;
txq->axq_tx_inprogress = false;
sc->tx.txqsetup |= 1<<qnum;
txq->txq_headidx = txq->txq_tailidx = 0;
for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
INIT_LIST_HEAD(&txq->txq_fifo[i]);
INIT_LIST_HEAD(&txq->txq_fifo_pending);
}
return &sc->tx.txq[qnum];
}
@ -1035,36 +1081,52 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
struct ath_tx_status ts;
memset(&ts, 0, sizeof(ts));
if (!retry_tx)
ts.ts_flags = ATH9K_TX_SW_ABORTED;
INIT_LIST_HEAD(&bf_head);
for (;;) {
spin_lock_bh(&txq->axq_lock);
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
spin_unlock_bh(&txq->axq_lock);
break;
}
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
txq->txq_headidx = txq->txq_tailidx = 0;
spin_unlock_bh(&txq->axq_lock);
break;
} else {
bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
struct ath_buf, list);
}
} else {
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
spin_unlock_bh(&txq->axq_lock);
break;
}
bf = list_first_entry(&txq->axq_q, struct ath_buf,
list);
bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
if (bf->bf_stale) {
list_del(&bf->list);
spin_unlock_bh(&txq->axq_lock);
if (bf->bf_stale) {
list_del(&bf->list);
spin_unlock_bh(&txq->axq_lock);
spin_lock_bh(&sc->tx.txbuflock);
list_add_tail(&bf->list, &sc->tx.txbuf);
spin_unlock_bh(&sc->tx.txbuflock);
continue;
ath_tx_return_buffer(sc, bf);
continue;
}
}
lastbf = bf->bf_lastbf;
if (!retry_tx)
lastbf->bf_tx_aborted = true;
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
list_cut_position(&bf_head,
&txq->txq_fifo[txq->txq_tailidx],
&lastbf->list);
INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
} else {
/* remove ath_buf's of the same mpdu from txq */
list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
}
/* remove ath_buf's of the same mpdu from txq */
list_cut_position(&bf_head, &txq->axq_q, &lastbf->list);
txq->axq_depth--;
spin_unlock_bh(&txq->axq_lock);
@ -1087,6 +1149,27 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
spin_unlock_bh(&txq->axq_lock);
}
}
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
spin_lock_bh(&txq->axq_lock);
while (!list_empty(&txq->txq_fifo_pending)) {
bf = list_first_entry(&txq->txq_fifo_pending,
struct ath_buf, list);
list_cut_position(&bf_head,
&txq->txq_fifo_pending,
&bf->bf_lastbf->list);
spin_unlock_bh(&txq->axq_lock);
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head,
&ts, 0);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head,
&ts, 0, 0);
spin_lock_bh(&txq->axq_lock);
}
spin_unlock_bh(&txq->axq_lock);
}
}
void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
@ -1224,44 +1307,47 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
bf = list_first_entry(head, struct ath_buf, list);
list_splice_tail_init(head, &txq->axq_q);
txq->axq_depth++;
ath_print(common, ATH_DBG_QUEUE,
"qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
if (txq->axq_link == NULL) {
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
if (txq->axq_depth >= ATH_TXFIFO_DEPTH) {
list_splice_tail_init(head, &txq->txq_fifo_pending);
return;
}
if (!list_empty(&txq->txq_fifo[txq->txq_headidx]))
ath_print(common, ATH_DBG_XMIT,
"Initializing tx fifo %d which "
"is non-empty\n",
txq->txq_headidx);
INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
ath_print(common, ATH_DBG_XMIT,
"TXDP[%u] = %llx (%p)\n",
txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
} else {
*txq->axq_link = bf->bf_daddr;
ath_print(common, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n",
txq->axq_qnum, txq->axq_link,
ito64(bf->bf_daddr), bf->bf_desc);
list_splice_tail_init(head, &txq->axq_q);
if (txq->axq_link == NULL) {
ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
ath_print(common, ATH_DBG_XMIT,
"TXDP[%u] = %llx (%p)\n",
txq->axq_qnum, ito64(bf->bf_daddr),
bf->bf_desc);
} else {
*txq->axq_link = bf->bf_daddr;
ath_print(common, ATH_DBG_XMIT,
"link[%u] (%p)=%llx (%p)\n",
txq->axq_qnum, txq->axq_link,
ito64(bf->bf_daddr), bf->bf_desc);
}
ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
&txq->axq_link);
ath9k_hw_txstart(ah, txq->axq_qnum);
}
txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link);
ath9k_hw_txstart(ah, txq->axq_qnum);
}
static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
{
struct ath_buf *bf = NULL;
spin_lock_bh(&sc->tx.txbuflock);
if (unlikely(list_empty(&sc->tx.txbuf))) {
spin_unlock_bh(&sc->tx.txbuflock);
return NULL;
}
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
list_del(&bf->list);
spin_unlock_bh(&sc->tx.txbuflock);
return bf;
txq->axq_depth++;
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
@ -1408,8 +1494,7 @@ static void assign_aggr_tid_seqno(struct sk_buff *skb,
INCR(tid->seq_next, IEEE80211_SEQ_MAX);
}
static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
struct ath_txq *txq)
static int setup_tx_flags(struct sk_buff *skb, bool use_ldpc)
{
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
int flags = 0;
@ -1420,6 +1505,9 @@ static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
flags |= ATH9K_TXDESC_NOACK;
if (use_ldpc)
flags |= ATH9K_TXDESC_LDPC;
return flags;
}
@ -1438,8 +1526,9 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
/* find number of symbols: PLCP + data */
streams = HT_RC_2_STREAMS(rix);
nbits = (pktlen << 3) + OFDM_PLCP_BITS;
nsymbits = bits_per_symbol[rix][width];
nsymbits = bits_per_symbol[rix % 8][width] * streams;
nsymbols = (nbits + nsymbits - 1) / nsymbits;
if (!half_gi)
@ -1448,7 +1537,6 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
duration = SYMBOL_TIME_HALFGI(nsymbols);
/* addup duration for legacy/ht training and signal fields */
streams = HT_RC_2_STREAMS(rix);
duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
return duration;
@ -1519,6 +1607,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
series[i].Rate = rix | 0x80;
series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
series[i].RateFlags |= ATH9K_RATESERIES_STBC;
continue;
}
@ -1571,6 +1661,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
int hdrlen;
__le16 fc;
int padpos, padsize;
bool use_ldpc = false;
tx_info->pad[0] = 0;
switch (txctl->frame_type) {
@ -1597,10 +1688,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
bf->bf_frmlen -= padsize;
}
if (conf_is_ht(&hw->conf))
if (conf_is_ht(&hw->conf)) {
bf->bf_state.bf_type |= BUF_HT;
if (tx_info->flags & IEEE80211_TX_CTL_LDPC)
use_ldpc = true;
}
bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
bf->bf_flags = setup_tx_flags(skb, use_ldpc);
bf->bf_keytype = get_hw_crypto_keytype(skb);
if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
@ -1659,8 +1753,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
list_add_tail(&bf->list, &bf_head);
ds = bf->bf_desc;
ds->ds_link = 0;
ds->ds_data = bf->bf_buf_addr;
ath9k_hw_set_desc_link(ah, ds, 0);
ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
@ -1669,7 +1762,9 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
skb->len, /* segment length */
true, /* first segment */
true, /* last segment */
ds); /* first descriptor */
ds, /* first descriptor */
bf->bf_buf_addr,
txctl->txq->axq_qnum);
spin_lock_bh(&txctl->txq->axq_lock);
@ -1738,9 +1833,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
}
spin_unlock_bh(&txq->axq_lock);
spin_lock_bh(&sc->tx.txbuflock);
list_add_tail(&bf->list, &sc->tx.txbuf);
spin_unlock_bh(&sc->tx.txbuflock);
ath_tx_return_buffer(sc, bf);
return r;
}
@ -1896,7 +1989,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
int nbad = 0;
int isaggr = 0;
if (ts->ts_flags == ATH9K_TX_SW_ABORTED)
if (bf->bf_tx_aborted)
return 0;
isaggr = bf_isaggr(bf);
@ -2054,13 +2147,12 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
txq->axq_depth--;
txok = !(ts.ts_status & ATH9K_TXERR_MASK);
txq->axq_tx_inprogress = false;
if (bf_held)
list_del(&bf_held->list);
spin_unlock_bh(&txq->axq_lock);
if (bf_held) {
spin_lock_bh(&sc->tx.txbuflock);
list_move_tail(&bf_held->list, &sc->tx.txbuf);
spin_unlock_bh(&sc->tx.txbuflock);
}
if (bf_held)
ath_tx_return_buffer(sc, bf_held);
if (!bf_isampdu(bf)) {
/*
@ -2138,10 +2230,119 @@ void ath_tx_tasklet(struct ath_softc *sc)
}
}
void ath_tx_edma_tasklet(struct ath_softc *sc)
{
struct ath_tx_status txs;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
struct ath_txq *txq;
struct ath_buf *bf, *lastbf;
struct list_head bf_head;
int status;
int txok;
for (;;) {
status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
if (status == -EINPROGRESS)
break;
if (status == -EIO) {
ath_print(common, ATH_DBG_XMIT,
"Error processing tx status\n");
break;
}
/* Skip beacon completions */
if (txs.qid == sc->beacon.beaconq)
continue;
txq = &sc->tx.txq[txs.qid];
spin_lock_bh(&txq->axq_lock);
if (list_empty(&txq->txq_fifo[txq->txq_tailidx])) {
spin_unlock_bh(&txq->axq_lock);
return;
}
bf = list_first_entry(&txq->txq_fifo[txq->txq_tailidx],
struct ath_buf, list);
lastbf = bf->bf_lastbf;
INIT_LIST_HEAD(&bf_head);
list_cut_position(&bf_head, &txq->txq_fifo[txq->txq_tailidx],
&lastbf->list);
INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
txq->axq_depth--;
txq->axq_tx_inprogress = false;
spin_unlock_bh(&txq->axq_lock);
txok = !(txs.ts_status & ATH9K_TXERR_MASK);
if (!bf_isampdu(bf)) {
bf->bf_retries = txs.ts_longretry;
if (txs.ts_status & ATH9K_TXERR_XRETRY)
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, &txs, 0, txok, true);
}
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
else
ath_tx_complete_buf(sc, bf, txq, &bf_head,
&txs, txok, 0);
spin_lock_bh(&txq->axq_lock);
if (!list_empty(&txq->txq_fifo_pending)) {
INIT_LIST_HEAD(&bf_head);
bf = list_first_entry(&txq->txq_fifo_pending,
struct ath_buf, list);
list_cut_position(&bf_head, &txq->txq_fifo_pending,
&bf->bf_lastbf->list);
ath_tx_txqaddbuf(sc, txq, &bf_head);
} else if (sc->sc_flags & SC_OP_TXAGGR)
ath_txq_schedule(sc, txq);
spin_unlock_bh(&txq->axq_lock);
}
}
/*****************/
/* Init, Cleanup */
/*****************/
static int ath_txstatus_setup(struct ath_softc *sc, int size)
{
struct ath_descdma *dd = &sc->txsdma;
u8 txs_len = sc->sc_ah->caps.txs_len;
dd->dd_desc_len = size * txs_len;
dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
&dd->dd_desc_paddr, GFP_KERNEL);
if (!dd->dd_desc)
return -ENOMEM;
return 0;
}
static int ath_tx_edma_init(struct ath_softc *sc)
{
int err;
err = ath_txstatus_setup(sc, ATH_TXSTATUS_RING_SIZE);
if (!err)
ath9k_hw_setup_statusring(sc->sc_ah, sc->txsdma.dd_desc,
sc->txsdma.dd_desc_paddr,
ATH_TXSTATUS_RING_SIZE);
return err;
}
static void ath_tx_edma_cleanup(struct ath_softc *sc)
{
struct ath_descdma *dd = &sc->txsdma;
dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
dd->dd_desc_paddr);
}
int ath_tx_init(struct ath_softc *sc, int nbufs)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@ -2150,7 +2351,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
spin_lock_init(&sc->tx.txbuflock);
error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
"tx", nbufs, 1);
"tx", nbufs, 1, 1);
if (error != 0) {
ath_print(common, ATH_DBG_FATAL,
"Failed to allocate tx descriptors: %d\n", error);
@ -2158,7 +2359,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
}
error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
"beacon", ATH_BCBUF, 1);
"beacon", ATH_BCBUF, 1, 1);
if (error != 0) {
ath_print(common, ATH_DBG_FATAL,
"Failed to allocate beacon descriptors: %d\n", error);
@ -2167,6 +2368,12 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
error = ath_tx_edma_init(sc);
if (error)
goto err;
}
err:
if (error != 0)
ath_tx_cleanup(sc);
@ -2181,6 +2388,9 @@ void ath_tx_cleanup(struct ath_softc *sc)
if (sc->tx.txdma.dd_desc_len != 0)
ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
ath_tx_edma_cleanup(sc);
}
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)

View File

@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
iwlagn-objs += iwl-agn-lib.o
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o

View File

@ -46,6 +46,7 @@
#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-agn-led.h"
#include "iwl-agn-debugfs.h"
/* Highest firmware API version supported */
#define IWL1000_UCODE_API_MAX 3
@ -212,6 +213,11 @@ static struct iwl_lib_ops iwl1000_lib = {
.set_ct_kill = iwl1000_set_ct_threshold,
},
.add_bcast_station = iwl_add_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,

View File

@ -2688,6 +2688,7 @@ IWL3945_UCODE_GET(boot_size);
static struct iwl_hcmd_ops iwl3945_hcmd = {
.rxon_assoc = iwl3945_send_rxon_assoc,
.commit_rxon = iwl3945_commit_rxon,
.send_bt_config = iwl_send_bt_config,
};
static struct iwl_ucode_ops iwl3945_ucode = {
@ -2741,6 +2742,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
.get_hcmd_size = iwl3945_get_hcmd_size,
.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
.request_scan = iwl3945_request_scan,
};
static const struct iwl_ops iwl3945_ops = {

View File

@ -294,6 +294,9 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info(
extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
/* scanning */
void iwl3945_request_scan(struct iwl_priv *priv);
/* Requires full declaration of iwl_priv before including */
#include "iwl-io.h"

View File

@ -47,6 +47,7 @@
#include "iwl-sta.h"
#include "iwl-agn-led.h"
#include "iwl-agn.h"
#include "iwl-agn-debugfs.h"
static int iwl4965_send_tx_power(struct iwl_priv *priv);
static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
@ -2143,6 +2144,7 @@ static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
.send_bt_config = iwl_send_bt_config,
};
static struct iwl_ucode_ops iwl4965_ucode = {
@ -2162,6 +2164,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.gain_computation = iwl4965_gain_computation,
.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
.calc_rssi = iwl4965_calc_rssi,
.request_scan = iwlagn_request_scan,
};
static struct iwl_lib_ops iwl4965_lib = {
@ -2216,6 +2219,11 @@ static struct iwl_lib_ops iwl4965_lib = {
.set_ct_kill = iwl4965_set_ct_threshold,
},
.add_bcast_station = iwl_add_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
},
.check_plcp_health = iwl_good_plcp_health,
};
@ -2253,8 +2261,13 @@ struct iwl_cfg iwl4965_agn_cfg = {
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
.monitor_recover_period = IWL_MONITORING_PERIOD,
.temperature_kelvin = true,
.off_channel_workaround = true,
.max_event_log_size = 512,
/*
* Force use of chains B and C for scan RX on 5 GHz band
* because the device has off-channel reception on chain A.
*/
.scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
};
/* Module firmware */

View File

@ -48,6 +48,7 @@
#include "iwl-agn-led.h"
#include "iwl-agn-hw.h"
#include "iwl-5000-hw.h"
#include "iwl-agn-debugfs.h"
/* Highest firmware API version supported */
#define IWL5000_UCODE_API_MAX 2
@ -320,6 +321,11 @@ static struct iwl_lib_ops iwl5000_lib = {
.set_ct_kill = iwl5000_set_ct_threshold,
},
.add_bcast_station = iwl_add_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
@ -377,6 +383,11 @@ static struct iwl_lib_ops iwl5150_lib = {
.set_ct_kill = iwl5150_set_ct_threshold,
},
.add_bcast_station = iwl_add_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,

View File

@ -47,17 +47,19 @@
#include "iwl-agn-hw.h"
#include "iwl-6000-hw.h"
#include "iwl-agn-led.h"
#include "iwl-agn-debugfs.h"
/* Highest firmware API version supported */
#define IWL6000_UCODE_API_MAX 4
#define IWL6050_UCODE_API_MAX 4
#define IWL6000G2_UCODE_API_MAX 4
/* Lowest firmware API version supported */
#define IWL6000_UCODE_API_MIN 4
#define IWL6050_UCODE_API_MIN 4
#define IWL6000G2_UCODE_API_MIN 4
#define IWL6000_FW_PRE "iwlwifi-6000-"
#define IWL6000_G2_FW_PRE "iwlwifi-6005-"
#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api)
@ -65,6 +67,10 @@
#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
#define IWL6000G2_FW_PRE "iwlwifi-6005-"
#define _IWL6000G2_MODULE_FIRMWARE(api) IWL6000G2_FW_PRE #api ".ucode"
#define IWL6000G2_MODULE_FIRMWARE(api) _IWL6000G2_MODULE_FIRMWARE(api)
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
{
/* want Celsius */
@ -261,7 +267,6 @@ static struct iwl_lib_ops iwl6000_lib = {
EEPROM_REG_BAND_3_CHANNELS,
EEPROM_REG_BAND_4_CHANNELS,
EEPROM_REG_BAND_5_CHANNELS,
EEPROM_REG_BAND_24_HT40_CHANNELS,
EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
EEPROM_REG_BAND_52_HT40_CHANNELS
},
@ -280,6 +285,11 @@ static struct iwl_lib_ops iwl6000_lib = {
.set_ct_kill = iwl6000_set_ct_threshold,
},
.add_bcast_station = iwl_add_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
@ -348,6 +358,11 @@ static struct iwl_lib_ops iwl6050_lib = {
.set_calib_version = iwl6050_set_calib_version,
},
.add_bcast_station = iwl_add_bcast_station,
.debugfs_ops = {
.rx_stats_read = iwl_ucode_rx_stats_read,
.tx_stats_read = iwl_ucode_tx_stats_read,
.general_stats_read = iwl_ucode_general_stats_read,
},
.recover_from_tx_stall = iwl_bg_monitor_recover,
.check_plcp_health = iwl_good_plcp_health,
.check_ack_health = iwl_good_ack_health,
@ -364,16 +379,16 @@ static const struct iwl_ops iwl6050_ops = {
/*
* "i": Internal configuration, use internal Power Amplifier
*/
struct iwl_cfg iwl6000i_g2_2agn_cfg = {
struct iwl_cfg iwl6000g2_2agn_cfg = {
.name = "6000 Series 2x2 AGN Gen2",
.fw_name_pre = IWL6000_G2_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.fw_name_pre = IWL6000G2_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl6000_ops,
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
.mod_params = &iwlagn_mod_params,
@ -382,7 +397,7 @@ struct iwl_cfg iwl6000i_g2_2agn_cfg = {
.pll_cfg_val = 0,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_INTERNAL,
.pa_type = IWL_PA_SYSTEM,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
.shadow_ram_support = true,
.ht_greenfield_support = true,
@ -601,3 +616,4 @@ struct iwl_cfg iwl6000_3agn_cfg = {
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6000G2_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));

View File

@ -0,0 +1,834 @@
/******************************************************************************
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#include "iwl-agn-debugfs.h"
ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = sizeof(struct statistics_rx_phy) * 40 +
sizeof(struct statistics_rx_non_phy) * 40 +
sizeof(struct statistics_rx_ht_phy) * 40 + 400;
ssize_t ret;
struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
struct statistics_rx_non_phy *general, *accum_general;
struct statistics_rx_non_phy *delta_general, *max_general;
struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/*
* the statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
ofdm = &priv->statistics.rx.ofdm;
cck = &priv->statistics.rx.cck;
general = &priv->statistics.rx.general;
ht = &priv->statistics.rx.ofdm_ht;
accum_ofdm = &priv->accum_statistics.rx.ofdm;
accum_cck = &priv->accum_statistics.rx.cck;
accum_general = &priv->accum_statistics.rx.general;
accum_ht = &priv->accum_statistics.rx.ofdm_ht;
delta_ofdm = &priv->delta_statistics.rx.ofdm;
delta_cck = &priv->delta_statistics.rx.cck;
delta_general = &priv->delta_statistics.rx.general;
delta_ht = &priv->delta_statistics.rx.ofdm_ht;
max_ofdm = &priv->max_delta.rx.ofdm;
max_cck = &priv->max_delta.rx.cck;
max_general = &priv->max_delta.rx.general;
max_ht = &priv->max_delta.rx.ofdm_ht;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
"Statistics_Rx - OFDM:");
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
accum_ofdm->ina_cnt,
delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"fina_cnt:",
le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"plcp_err:",
le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
delta_ofdm->plcp_err, max_ofdm->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "crc32_err:",
le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
delta_ofdm->crc32_err, max_ofdm->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "overrun_err:",
le32_to_cpu(ofdm->overrun_err),
accum_ofdm->overrun_err, delta_ofdm->overrun_err,
max_ofdm->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"early_overrun_err:",
le32_to_cpu(ofdm->early_overrun_err),
accum_ofdm->early_overrun_err,
delta_ofdm->early_overrun_err,
max_ofdm->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"crc32_good:", le32_to_cpu(ofdm->crc32_good),
accum_ofdm->crc32_good, delta_ofdm->crc32_good,
max_ofdm->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:",
le32_to_cpu(ofdm->false_alarm_cnt),
accum_ofdm->false_alarm_cnt,
delta_ofdm->false_alarm_cnt,
max_ofdm->false_alarm_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"fina_sync_err_cnt:",
le32_to_cpu(ofdm->fina_sync_err_cnt),
accum_ofdm->fina_sync_err_cnt,
delta_ofdm->fina_sync_err_cnt,
max_ofdm->fina_sync_err_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "sfd_timeout:",
le32_to_cpu(ofdm->sfd_timeout),
accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,
max_ofdm->sfd_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "fina_timeout:",
le32_to_cpu(ofdm->fina_timeout),
accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,
max_ofdm->fina_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"unresponded_rts:",
le32_to_cpu(ofdm->unresponded_rts),
accum_ofdm->unresponded_rts,
delta_ofdm->unresponded_rts,
max_ofdm->unresponded_rts);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"rxe_frame_lmt_ovrun:",
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
accum_ofdm->rxe_frame_limit_overrun,
delta_ofdm->rxe_frame_limit_overrun,
max_ofdm->rxe_frame_limit_overrun);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:",
le32_to_cpu(ofdm->sent_ack_cnt),
accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,
max_ofdm->sent_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:",
le32_to_cpu(ofdm->sent_cts_cnt),
accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,
max_ofdm->sent_cts_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"sent_ba_rsp_cnt:",
le32_to_cpu(ofdm->sent_ba_rsp_cnt),
accum_ofdm->sent_ba_rsp_cnt,
delta_ofdm->sent_ba_rsp_cnt,
max_ofdm->sent_ba_rsp_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "dsp_self_kill:",
le32_to_cpu(ofdm->dsp_self_kill),
accum_ofdm->dsp_self_kill,
delta_ofdm->dsp_self_kill,
max_ofdm->dsp_self_kill);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"mh_format_err:",
le32_to_cpu(ofdm->mh_format_err),
accum_ofdm->mh_format_err,
delta_ofdm->mh_format_err,
max_ofdm->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"re_acq_main_rssi_sum:",
le32_to_cpu(ofdm->re_acq_main_rssi_sum),
accum_ofdm->re_acq_main_rssi_sum,
delta_ofdm->re_acq_main_rssi_sum,
max_ofdm->re_acq_main_rssi_sum);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
"Statistics_Rx - CCK:");
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"ina_cnt:",
le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
delta_cck->ina_cnt, max_cck->ina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"fina_cnt:",
le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
delta_cck->fina_cnt, max_cck->fina_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"plcp_err:",
le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
delta_cck->plcp_err, max_cck->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"crc32_err:",
le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
delta_cck->crc32_err, max_cck->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"overrun_err:",
le32_to_cpu(cck->overrun_err),
accum_cck->overrun_err, delta_cck->overrun_err,
max_cck->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"early_overrun_err:",
le32_to_cpu(cck->early_overrun_err),
accum_cck->early_overrun_err,
delta_cck->early_overrun_err,
max_cck->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"crc32_good:",
le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
delta_cck->crc32_good, max_cck->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"false_alarm_cnt:",
le32_to_cpu(cck->false_alarm_cnt),
accum_cck->false_alarm_cnt,
delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"fina_sync_err_cnt:",
le32_to_cpu(cck->fina_sync_err_cnt),
accum_cck->fina_sync_err_cnt,
delta_cck->fina_sync_err_cnt,
max_cck->fina_sync_err_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"sfd_timeout:",
le32_to_cpu(cck->sfd_timeout),
accum_cck->sfd_timeout, delta_cck->sfd_timeout,
max_cck->sfd_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "fina_timeout:",
le32_to_cpu(cck->fina_timeout),
accum_cck->fina_timeout, delta_cck->fina_timeout,
max_cck->fina_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"unresponded_rts:",
le32_to_cpu(cck->unresponded_rts),
accum_cck->unresponded_rts, delta_cck->unresponded_rts,
max_cck->unresponded_rts);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"rxe_frame_lmt_ovrun:",
le32_to_cpu(cck->rxe_frame_limit_overrun),
accum_cck->rxe_frame_limit_overrun,
delta_cck->rxe_frame_limit_overrun,
max_cck->rxe_frame_limit_overrun);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "sent_ack_cnt:",
le32_to_cpu(cck->sent_ack_cnt),
accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,
max_cck->sent_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "sent_cts_cnt:",
le32_to_cpu(cck->sent_cts_cnt),
accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,
max_cck->sent_cts_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "sent_ba_rsp_cnt:",
le32_to_cpu(cck->sent_ba_rsp_cnt),
accum_cck->sent_ba_rsp_cnt,
delta_cck->sent_ba_rsp_cnt,
max_cck->sent_ba_rsp_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "dsp_self_kill:",
le32_to_cpu(cck->dsp_self_kill),
accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,
max_cck->dsp_self_kill);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "mh_format_err:",
le32_to_cpu(cck->mh_format_err),
accum_cck->mh_format_err, delta_cck->mh_format_err,
max_cck->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"re_acq_main_rssi_sum:",
le32_to_cpu(cck->re_acq_main_rssi_sum),
accum_cck->re_acq_main_rssi_sum,
delta_cck->re_acq_main_rssi_sum,
max_cck->re_acq_main_rssi_sum);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
"Statistics_Rx - GENERAL:");
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "bogus_cts:",
le32_to_cpu(general->bogus_cts),
accum_general->bogus_cts, delta_general->bogus_cts,
max_general->bogus_cts);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n", "bogus_ack:",
le32_to_cpu(general->bogus_ack),
accum_general->bogus_ack, delta_general->bogus_ack,
max_general->bogus_ack);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"non_bssid_frames:",
le32_to_cpu(general->non_bssid_frames),
accum_general->non_bssid_frames,
delta_general->non_bssid_frames,
max_general->non_bssid_frames);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"filtered_frames:",
le32_to_cpu(general->filtered_frames),
accum_general->filtered_frames,
delta_general->filtered_frames,
max_general->filtered_frames);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"non_channel_beacons:",
le32_to_cpu(general->non_channel_beacons),
accum_general->non_channel_beacons,
delta_general->non_channel_beacons,
max_general->non_channel_beacons);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"channel_beacons:",
le32_to_cpu(general->channel_beacons),
accum_general->channel_beacons,
delta_general->channel_beacons,
max_general->channel_beacons);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"num_missed_bcon:",
le32_to_cpu(general->num_missed_bcon),
accum_general->num_missed_bcon,
delta_general->num_missed_bcon,
max_general->num_missed_bcon);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"adc_rx_saturation_time:",
le32_to_cpu(general->adc_rx_saturation_time),
accum_general->adc_rx_saturation_time,
delta_general->adc_rx_saturation_time,
max_general->adc_rx_saturation_time);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"ina_detect_search_tm:",
le32_to_cpu(general->ina_detection_search_time),
accum_general->ina_detection_search_time,
delta_general->ina_detection_search_time,
max_general->ina_detection_search_time);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_silence_rssi_a:",
le32_to_cpu(general->beacon_silence_rssi_a),
accum_general->beacon_silence_rssi_a,
delta_general->beacon_silence_rssi_a,
max_general->beacon_silence_rssi_a);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_silence_rssi_b:",
le32_to_cpu(general->beacon_silence_rssi_b),
accum_general->beacon_silence_rssi_b,
delta_general->beacon_silence_rssi_b,
max_general->beacon_silence_rssi_b);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_silence_rssi_c:",
le32_to_cpu(general->beacon_silence_rssi_c),
accum_general->beacon_silence_rssi_c,
delta_general->beacon_silence_rssi_c,
max_general->beacon_silence_rssi_c);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"interference_data_flag:",
le32_to_cpu(general->interference_data_flag),
accum_general->interference_data_flag,
delta_general->interference_data_flag,
max_general->interference_data_flag);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"channel_load:",
le32_to_cpu(general->channel_load),
accum_general->channel_load,
delta_general->channel_load,
max_general->channel_load);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"dsp_false_alarms:",
le32_to_cpu(general->dsp_false_alarms),
accum_general->dsp_false_alarms,
delta_general->dsp_false_alarms,
max_general->dsp_false_alarms);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_rssi_a:",
le32_to_cpu(general->beacon_rssi_a),
accum_general->beacon_rssi_a,
delta_general->beacon_rssi_a,
max_general->beacon_rssi_a);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_rssi_b:",
le32_to_cpu(general->beacon_rssi_b),
accum_general->beacon_rssi_b,
delta_general->beacon_rssi_b,
max_general->beacon_rssi_b);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_rssi_c:",
le32_to_cpu(general->beacon_rssi_c),
accum_general->beacon_rssi_c,
delta_general->beacon_rssi_c,
max_general->beacon_rssi_c);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_energy_a:",
le32_to_cpu(general->beacon_energy_a),
accum_general->beacon_energy_a,
delta_general->beacon_energy_a,
max_general->beacon_energy_a);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_energy_b:",
le32_to_cpu(general->beacon_energy_b),
accum_general->beacon_energy_b,
delta_general->beacon_energy_b,
max_general->beacon_energy_b);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"beacon_energy_c:",
le32_to_cpu(general->beacon_energy_c),
accum_general->beacon_energy_c,
delta_general->beacon_energy_c,
max_general->beacon_energy_c);
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
"Statistics_Rx - OFDM_HT:");
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"plcp_err:",
le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
delta_ht->plcp_err, max_ht->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"overrun_err:",
le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
delta_ht->overrun_err, max_ht->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"early_overrun_err:",
le32_to_cpu(ht->early_overrun_err),
accum_ht->early_overrun_err,
delta_ht->early_overrun_err,
max_ht->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"crc32_good:",
le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
delta_ht->crc32_good, max_ht->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"crc32_err:",
le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
delta_ht->crc32_err, max_ht->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"mh_format_err:",
le32_to_cpu(ht->mh_format_err),
accum_ht->mh_format_err,
delta_ht->mh_format_err, max_ht->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg_crc32_good:",
le32_to_cpu(ht->agg_crc32_good),
accum_ht->agg_crc32_good,
delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg_mpdu_cnt:",
le32_to_cpu(ht->agg_mpdu_cnt),
accum_ht->agg_mpdu_cnt,
delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg_cnt:",
le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
delta_ht->agg_cnt, max_ht->agg_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"unsupport_mcs:",
le32_to_cpu(ht->unsupport_mcs),
accum_ht->unsupport_mcs,
delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
ssize_t iwl_ucode_tx_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
ssize_t ret;
struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/* the statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
tx = &priv->statistics.tx;
accum_tx = &priv->accum_statistics.tx;
delta_tx = &priv->delta_statistics.tx;
max_tx = &priv->max_delta.tx;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
"Statistics_Tx:");
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"preamble:",
le32_to_cpu(tx->preamble_cnt),
accum_tx->preamble_cnt,
delta_tx->preamble_cnt, max_tx->preamble_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"rx_detected_cnt:",
le32_to_cpu(tx->rx_detected_cnt),
accum_tx->rx_detected_cnt,
delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"bt_prio_defer_cnt:",
le32_to_cpu(tx->bt_prio_defer_cnt),
accum_tx->bt_prio_defer_cnt,
delta_tx->bt_prio_defer_cnt,
max_tx->bt_prio_defer_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"bt_prio_kill_cnt:",
le32_to_cpu(tx->bt_prio_kill_cnt),
accum_tx->bt_prio_kill_cnt,
delta_tx->bt_prio_kill_cnt,
max_tx->bt_prio_kill_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"few_bytes_cnt:",
le32_to_cpu(tx->few_bytes_cnt),
accum_tx->few_bytes_cnt,
delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"cts_timeout:",
le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
delta_tx->cts_timeout, max_tx->cts_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"ack_timeout:",
le32_to_cpu(tx->ack_timeout),
accum_tx->ack_timeout,
delta_tx->ack_timeout, max_tx->ack_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"expected_ack_cnt:",
le32_to_cpu(tx->expected_ack_cnt),
accum_tx->expected_ack_cnt,
delta_tx->expected_ack_cnt,
max_tx->expected_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"actual_ack_cnt:",
le32_to_cpu(tx->actual_ack_cnt),
accum_tx->actual_ack_cnt,
delta_tx->actual_ack_cnt,
max_tx->actual_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"dump_msdu_cnt:",
le32_to_cpu(tx->dump_msdu_cnt),
accum_tx->dump_msdu_cnt,
delta_tx->dump_msdu_cnt,
max_tx->dump_msdu_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"abort_nxt_frame_mismatch:",
le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
accum_tx->burst_abort_next_frame_mismatch_cnt,
delta_tx->burst_abort_next_frame_mismatch_cnt,
max_tx->burst_abort_next_frame_mismatch_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"abort_missing_nxt_frame:",
le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
accum_tx->burst_abort_missing_next_frame_cnt,
delta_tx->burst_abort_missing_next_frame_cnt,
max_tx->burst_abort_missing_next_frame_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"cts_timeout_collision:",
le32_to_cpu(tx->cts_timeout_collision),
accum_tx->cts_timeout_collision,
delta_tx->cts_timeout_collision,
max_tx->cts_timeout_collision);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"ack_ba_timeout_collision:",
le32_to_cpu(tx->ack_or_ba_timeout_collision),
accum_tx->ack_or_ba_timeout_collision,
delta_tx->ack_or_ba_timeout_collision,
max_tx->ack_or_ba_timeout_collision);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg ba_timeout:",
le32_to_cpu(tx->agg.ba_timeout),
accum_tx->agg.ba_timeout,
delta_tx->agg.ba_timeout,
max_tx->agg.ba_timeout);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg ba_resched_frames:",
le32_to_cpu(tx->agg.ba_reschedule_frames),
accum_tx->agg.ba_reschedule_frames,
delta_tx->agg.ba_reschedule_frames,
max_tx->agg.ba_reschedule_frames);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg scd_query_agg_frame:",
le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
accum_tx->agg.scd_query_agg_frame_cnt,
delta_tx->agg.scd_query_agg_frame_cnt,
max_tx->agg.scd_query_agg_frame_cnt);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg scd_query_no_agg:",
le32_to_cpu(tx->agg.scd_query_no_agg),
accum_tx->agg.scd_query_no_agg,
delta_tx->agg.scd_query_no_agg,
max_tx->agg.scd_query_no_agg);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg scd_query_agg:",
le32_to_cpu(tx->agg.scd_query_agg),
accum_tx->agg.scd_query_agg,
delta_tx->agg.scd_query_agg,
max_tx->agg.scd_query_agg);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg scd_query_mismatch:",
le32_to_cpu(tx->agg.scd_query_mismatch),
accum_tx->agg.scd_query_mismatch,
delta_tx->agg.scd_query_mismatch,
max_tx->agg.scd_query_mismatch);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg frame_not_ready:",
le32_to_cpu(tx->agg.frame_not_ready),
accum_tx->agg.frame_not_ready,
delta_tx->agg.frame_not_ready,
max_tx->agg.frame_not_ready);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg underrun:",
le32_to_cpu(tx->agg.underrun),
accum_tx->agg.underrun,
delta_tx->agg.underrun, max_tx->agg.underrun);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg bt_prio_kill:",
le32_to_cpu(tx->agg.bt_prio_kill),
accum_tx->agg.bt_prio_kill,
delta_tx->agg.bt_prio_kill,
max_tx->agg.bt_prio_kill);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"agg rx_ba_rsp_cnt:",
le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
accum_tx->agg.rx_ba_rsp_cnt,
delta_tx->agg.rx_ba_rsp_cnt,
max_tx->agg.rx_ba_rsp_cnt);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}
ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = sizeof(struct statistics_general) * 10 + 300;
ssize_t ret;
struct statistics_general *general, *accum_general;
struct statistics_general *delta_general, *max_general;
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct statistics_div *div, *accum_div, *delta_div, *max_div;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/* the statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
general = &priv->statistics.general;
dbg = &priv->statistics.general.dbg;
div = &priv->statistics.general.div;
accum_general = &priv->accum_statistics.general;
delta_general = &priv->delta_statistics.general;
max_general = &priv->max_delta.general;
accum_dbg = &priv->accum_statistics.general.dbg;
delta_dbg = &priv->delta_statistics.general.dbg;
max_dbg = &priv->max_delta.general.dbg;
accum_div = &priv->accum_statistics.general.div;
delta_div = &priv->delta_statistics.general.div;
max_div = &priv->max_delta.general.div;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
"acumulative delta max\n",
"Statistics_General:");
pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n",
"temperature:",
le32_to_cpu(general->temperature));
pos += scnprintf(buf + pos, bufsz - pos, " %-30s %10u\n",
"temperature_m:",
le32_to_cpu(general->temperature_m));
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"burst_check:",
le32_to_cpu(dbg->burst_check),
accum_dbg->burst_check,
delta_dbg->burst_check, max_dbg->burst_check);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"burst_count:",
le32_to_cpu(dbg->burst_count),
accum_dbg->burst_count,
delta_dbg->burst_count, max_dbg->burst_count);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"sleep_time:",
le32_to_cpu(general->sleep_time),
accum_general->sleep_time,
delta_general->sleep_time, max_general->sleep_time);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"slots_out:",
le32_to_cpu(general->slots_out),
accum_general->slots_out,
delta_general->slots_out, max_general->slots_out);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"slots_idle:",
le32_to_cpu(general->slots_idle),
accum_general->slots_idle,
delta_general->slots_idle, max_general->slots_idle);
pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
le32_to_cpu(general->ttl_timestamp));
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"tx_on_a:",
le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
delta_div->tx_on_a, max_div->tx_on_a);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"tx_on_b:",
le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
delta_div->tx_on_b, max_div->tx_on_b);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"exec_time:",
le32_to_cpu(div->exec_time), accum_div->exec_time,
delta_div->exec_time, max_div->exec_time);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"probe_time:",
le32_to_cpu(div->probe_time), accum_div->probe_time,
delta_div->probe_time, max_div->probe_time);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"rx_enable_counter:",
le32_to_cpu(general->rx_enable_counter),
accum_general->rx_enable_counter,
delta_general->rx_enable_counter,
max_general->rx_enable_counter);
pos += scnprintf(buf + pos, bufsz - pos,
" %-30s %10u %10u %10u %10u\n",
"num_of_sos_states:",
le32_to_cpu(general->num_of_sos_states),
accum_general->num_of_sos_states,
delta_general->num_of_sos_states,
max_general->num_of_sos_states);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
}

View File

@ -0,0 +1,56 @@
/******************************************************************************
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
* USA
*
* The full GNU General Public License is included in this distribution
* in the file called LICENSE.GPL.
*
* Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-debug.h"
#ifdef CONFIG_IWLWIFI_DEBUGFS
ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
#else
static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
return 0;
}
static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
return 0;
}
#endif

View File

@ -262,6 +262,7 @@ struct iwl_hcmd_ops iwlagn_hcmd = {
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
.set_tx_ant = iwlagn_send_tx_ant_config,
.send_bt_config = iwl_send_bt_config,
};
struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
@ -271,4 +272,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = {
.chain_noise_reset = iwlagn_chain_noise_reset,
.rts_tx_cmd_flag = iwlagn_rts_tx_cmd_flag,
.calc_rssi = iwlagn_calc_rssi,
.request_scan = iwlagn_request_scan,
};

View File

@ -331,7 +331,7 @@ u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
} *hdr;
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
EEPROM_5000_CALIB_ALL);
EEPROM_CALIB_ALL);
return hdr->version;
}
@ -348,22 +348,22 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
switch (address & INDIRECT_TYPE_MSK) {
case INDIRECT_HOST:
offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST);
offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST);
break;
case INDIRECT_GENERAL:
offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL);
offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL);
break;
case INDIRECT_REGULATORY:
offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY);
offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);
break;
case INDIRECT_CALIBRATION:
offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION);
offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);
break;
case INDIRECT_PROCESS_ADJST:
offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST);
offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST);
break;
case INDIRECT_OTHERS:
offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS);
offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS);
break;
default:
IWL_ERR(priv, "illegal indirect type: 0x%X\n",
@ -1111,3 +1111,392 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
sizeof(struct iwl_rx_phy_res));
}
static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
struct iwl_scan_channel *scan_ch)
{
const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int i, added = 0;
u16 channel = 0;
sband = iwl_get_hw_mode(priv, band);
if (!sband) {
IWL_ERR(priv, "invalid band\n");
return added;
}
active_dwell = iwl_get_active_dwell_time(priv, band, 0);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
/* only scan single channel, good enough to reset the RF */
/* pick the first valid not in-use channel */
if (band == IEEE80211_BAND_5GHZ) {
for (i = 14; i < priv->channel_count; i++) {
if (priv->channel_info[i].channel !=
le16_to_cpu(priv->staging_rxon.channel)) {
channel = priv->channel_info[i].channel;
ch_info = iwl_get_channel_info(priv,
band, channel);
if (is_channel_valid(ch_info))
break;
}
}
} else {
for (i = 0; i < 14; i++) {
if (priv->channel_info[i].channel !=
le16_to_cpu(priv->staging_rxon.channel)) {
channel =
priv->channel_info[i].channel;
ch_info = iwl_get_channel_info(priv,
band, channel);
if (is_channel_valid(ch_info))
break;
}
}
}
if (channel) {
scan_ch->channel = cpu_to_le16(channel);
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
/* Set txpower levels to defaults */
scan_ch->dsp_atten = 110;
if (band == IEEE80211_BAND_5GHZ)
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
else
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
added++;
} else
IWL_ERR(priv, "no valid channel found\n");
return added;
}
static int iwl_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
struct iwl_scan_channel *scan_ch)
{
struct ieee80211_channel *chan;
const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int added, i;
u16 channel;
sband = iwl_get_hw_mode(priv, band);
if (!sband)
return 0;
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
chan = priv->scan_request->channels[i];
if (chan->band != band)
continue;
channel = ieee80211_frequency_to_channel(chan->center_freq);
scan_ch->channel = cpu_to_le16(channel);
ch_info = iwl_get_channel_info(priv, band, channel);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
channel);
continue;
}
if (!is_active || is_channel_passive(ch_info) ||
(chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
else
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
if (n_probes)
scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
/* Set txpower levels to defaults */
scan_ch->dsp_atten = 110;
/* NOTE: if we were doing 6Mb OFDM for scans we'd use
* power level:
* scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
*/
if (band == IEEE80211_BAND_5GHZ)
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
else
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
channel, le32_to_cpu(scan_ch->type),
(scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
"ACTIVE" : "PASSIVE",
(scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
active_dwell : passive_dwell);
scan_ch++;
added++;
}
IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
return added;
}
void iwlagn_request_scan(struct iwl_priv *priv)
{
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl_scan_cmd),
.flags = CMD_SIZE_HUGE,
};
struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
u32 rate_flags = 0;
u16 cmd_len;
u16 rx_chain = 0;
enum ieee80211_band band;
u8 n_probes = 0;
u8 rx_ant = priv->hw_params.valid_rx_ant;
u8 rate;
bool is_active = false;
int chan_mod;
u8 active_chains;
conf = ieee80211_get_hw_conf(priv->hw);
cancel_delayed_work(&priv->scan_check);
if (!iwl_is_ready(priv)) {
IWL_WARN(priv, "request scan called when driver not ready.\n");
goto done;
}
/* Make sure the scan wasn't canceled before this queued work
* was given the chance to run... */
if (!test_bit(STATUS_SCANNING, &priv->status))
goto done;
/* This should never be called or scheduled if there is currently
* a scan active in the hardware. */
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
"Ignoring second request.\n");
goto done;
}
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
goto done;
}
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n");
goto done;
}
if (iwl_is_rfkill(priv)) {
IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
goto done;
}
if (!test_bit(STATUS_READY, &priv->status)) {
IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n");
goto done;
}
if (!priv->scan_cmd) {
priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan_cmd) {
IWL_DEBUG_SCAN(priv,
"fail to allocate memory for scan\n");
goto done;
}
}
scan = priv->scan_cmd;
memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_is_associated(priv)) {
u16 interval = 0;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
unsigned long flags;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
spin_lock_irqsave(&priv->lock, flags);
interval = priv->beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
if (!interval)
interval = suspend_time;
extra = (suspend_time / interval) << 22;
scan_suspend_time = (extra |
((suspend_time % interval) * 1024));
scan->suspend_time = cpu_to_le32(scan_suspend_time);
IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
scan_suspend_time, interval);
}
if (priv->is_internal_short_scan) {
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
} else if (priv->scan_request->n_ssids) {
int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
for (i = 0; i < priv->scan_request->n_ssids; i++) {
/* always does wildcard anyway */
if (!priv->scan_request->ssids[i].ssid_len)
continue;
scan->direct_scan[p].id = WLAN_EID_SSID;
scan->direct_scan[p].len =
priv->scan_request->ssids[i].ssid_len;
memcpy(scan->direct_scan[p].ssid,
priv->scan_request->ssids[i].ssid,
priv->scan_request->ssids[i].ssid_len);
n_probes++;
p++;
}
is_active = true;
} else
IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
switch (priv->scan_band) {
case IEEE80211_BAND_2GHZ:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
>> RXON_FLG_CHANNEL_MODE_POS;
if (chan_mod == CHANNEL_MODE_PURE_40) {
rate = IWL_RATE_6M_PLCP;
} else {
rate = IWL_RATE_1M_PLCP;
rate_flags = RATE_MCS_CCK_MSK;
}
scan->good_CRC_th = 0;
break;
case IEEE80211_BAND_5GHZ:
rate = IWL_RATE_6M_PLCP;
/*
* If active scaning is requested but a certain channel
* is marked passive, we can do active scanning if we
* detect transmissions.
*/
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
break;
default:
IWL_WARN(priv, "Invalid scan band count\n");
goto done;
}
band = priv->scan_band;
if (priv->cfg->scan_antennas[band])
rx_ant = priv->cfg->scan_antennas[band];
priv->scan_tx_ant[band] =
iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
/* In power save mode use one chain, otherwise use all chains */
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
/* rx_ant has been set to all valid chains previously */
active_chains = rx_ant &
((u8)(priv->chain_noise_data.active_chains));
if (!active_chains)
active_chains = rx_ant;
IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
priv->chain_noise_data.active_chains);
rx_ant = first_antenna(active_chains);
}
/* MIMO is not used here, but value is required */
rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
scan->rx_chain = cpu_to_le16(rx_chain);
if (!priv->is_internal_short_scan) {
cmd_len = iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
priv->scan_request->ie,
priv->scan_request->ie_len,
IWL_MAX_SCAN_SIZE - sizeof(*scan));
} else {
cmd_len = iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
NULL, 0,
IWL_MAX_SCAN_SIZE - sizeof(*scan));
}
scan->tx_cmd.len = cpu_to_le16(cmd_len);
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
RXON_FILTER_BCON_AWARE_MSK);
if (priv->is_internal_short_scan) {
scan->channel_count =
iwl_get_single_channel_for_scan(priv, band,
(void *)&scan->data[le16_to_cpu(
scan->tx_cmd.len)]);
} else {
scan->channel_count =
iwl_get_channels_for_scan(priv, band,
is_active, n_probes,
(void *)&scan->data[le16_to_cpu(
scan->tx_cmd.len)]);
}
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
goto done;
}
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
scan->channel_count * sizeof(struct iwl_scan_channel);
cmd.data = scan;
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
if (iwl_send_cmd_sync(priv, &cmd))
goto done;
queue_delayed_work(priv->workqueue, &priv->scan_check,
IWL_SCAN_CHECK_WATCHDOG);
return;
done:
/* Cannot perform scan. Make sure we clear scanning
* bits from status so next scan request can be performed.
* If we don't clear scanning status bit here all next scan
* will fail
*/
clear_bit(STATUS_SCAN_HW, &priv->status);
clear_bit(STATUS_SCANNING, &priv->status);
/* inform mac80211 scan aborted */
queue_work(priv->workqueue, &priv->scan_completed);
}

View File

@ -295,11 +295,11 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
return tl->total;
}
static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
struct ieee80211_sta *sta)
{
int ret;
int ret = -EAGAIN;
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
@ -313,29 +313,29 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
*/
IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
tid);
ret = ieee80211_stop_tx_ba_session(sta, tid,
ieee80211_stop_tx_ba_session(sta, tid,
WLAN_BACK_INITIATOR);
}
}
} else
IWL_ERR(priv, "Fail finding valid aggregation tid: %d\n", tid);
return ret;
}
static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
struct iwl_lq_sta *lq_data,
struct ieee80211_sta *sta)
{
if ((tid < TID_MAX_LOAD_COUNT))
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
else if (tid == IWL_AGG_ALL_TID)
for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++)
rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
if (priv->cfg->use_rts_for_ht) {
/*
* switch to RTS/CTS if it is the prefer protection method
* for HT traffic
*/
IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
iwlcore_commit_rxon(priv);
if ((tid < TID_MAX_LOAD_COUNT) &&
!rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) {
if (priv->cfg->use_rts_for_ht) {
/*
* switch to RTS/CTS if it is the prefer protection
* method for HT traffic
*/
IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
iwlcore_commit_rxon(priv);
}
}
}
@ -2558,8 +2558,17 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
lq_sta->active_mimo3_rate);
/* These values will be overridden later */
lq_sta->lq.general_params.single_stream_ant_msk = ANT_A;
lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
lq_sta->lq.general_params.single_stream_ant_msk =
first_antenna(priv->hw_params.valid_tx_ant);
lq_sta->lq.general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant &
~first_antenna(priv->hw_params.valid_tx_ant);
if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
lq_sta->lq.general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant;
}
/* as default allow aggregation for all tids */
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;

View File

@ -167,7 +167,7 @@ static int iwlagn_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
tbl_dw_addr = priv->scd_base_addr +
IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
@ -186,9 +186,9 @@ static void iwlagn_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
/* Simply stop the queue, but don't change any configuration;
* the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
iwl_write_prph(priv,
IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
(0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
(1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id),
(0 << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
(1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}
void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
@ -196,7 +196,7 @@ void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
{
iwl_write_direct32(priv, HBUS_TARG_WRPTR,
(index & 0xff) | (txq_id << 8));
iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index);
iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(txq_id), index);
}
void iwlagn_tx_queue_set_status(struct iwl_priv *priv,
@ -206,11 +206,11 @@ void iwlagn_tx_queue_set_status(struct iwl_priv *priv,
int txq_id = txq->q.id;
int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
(active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
(tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) |
(1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) |
IWL50_SCD_QUEUE_STTS_REG_MSK);
iwl_write_prph(priv, IWLAGN_SCD_QUEUE_STATUS_BITS(txq_id),
(active << IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
(tx_fifo_id << IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF) |
(1 << IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL) |
IWLAGN_SCD_QUEUE_STTS_REG_MSK);
txq->sched_retry = scd_retry;
@ -250,10 +250,10 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
iwlagn_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
/* Set this queue as a chain-building queue */
iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<<txq_id));
iwl_set_bits_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL, (1<<txq_id));
/* enable aggregations for the queue */
iwl_set_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1<<txq_id));
iwl_set_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1<<txq_id));
/* Place first TFD at index corresponding to start sequence number.
* Assumes that ssn_idx is valid (!= 0xFFF) */
@ -263,16 +263,16 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
/* Set up Tx window size and frame limit for this queue */
iwl_write_targ_mem(priv, priv->scd_base_addr +
IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(txq_id) +
sizeof(u32),
((SCD_WIN_SIZE <<
IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
((SCD_FRAME_LIMIT <<
IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id));
iwl_set_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));
/* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
@ -298,14 +298,14 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
iwlagn_tx_queue_stop_scheduler(priv, txq_id);
iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id));
iwl_clear_bits_prph(priv, IWLAGN_SCD_AGGR_SEL, (1 << txq_id));
priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
/* supposes that ssn_idx is valid (!= 0xFFF) */
iwlagn_set_wr_ptrs(priv, txq_id, ssn_idx);
iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id));
iwl_clear_bits_prph(priv, IWLAGN_SCD_INTERRUPT_MASK, (1 << txq_id));
iwl_txq_ctx_deactivate(priv, txq_id);
iwlagn_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
@ -318,7 +318,7 @@ int iwlagn_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
*/
void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask)
{
iwl_write_prph(priv, IWL50_SCD_TXFACT, mask);
iwl_write_prph(priv, IWLAGN_SCD_TXFACT, mask);
}
static inline int get_queue_from_ac(u16 ac)

View File

@ -207,7 +207,7 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv)
{
struct iwl_calib_xtal_freq_cmd cmd;
__le16 *xtal_calib =
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_XTAL);
cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
cmd.hdr.first_group = 0;
@ -329,19 +329,19 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR);
a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET;
for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET;
priv->scd_base_addr = iwl_read_prph(priv, IWLAGN_SCD_SRAM_BASE_ADDR);
a = priv->scd_base_addr + IWLAGN_SCD_CONTEXT_DATA_OFFSET;
for (; a < priv->scd_base_addr + IWLAGN_SCD_TX_STTS_BITMAP_OFFSET;
a += 4)
iwl_write_targ_mem(priv, a, 0);
for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET;
for (; a < priv->scd_base_addr + IWLAGN_SCD_TRANSLATE_TBL_OFFSET;
a += 4)
iwl_write_targ_mem(priv, a, 0);
for (; a < priv->scd_base_addr +
IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
iwl_write_targ_mem(priv, a, 0);
iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
iwl_write_prph(priv, IWLAGN_SCD_DRAM_BASE_ADDR,
priv->scd_bc_tbls.dma >> 10);
/* Enable DMA channel */
@ -355,28 +355,28 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);
iwl_write_prph(priv, IWLAGN_SCD_QUEUECHAIN_SEL,
IWLAGN_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
iwl_write_prph(priv, IWLAGN_SCD_AGGR_SEL, 0);
/* initiate the queues */
for (i = 0; i < priv->hw_params.max_txq_num; i++) {
iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0);
iwl_write_prph(priv, IWLAGN_SCD_QUEUE_RDPTR(i), 0);
iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
iwl_write_targ_mem(priv, priv->scd_base_addr +
IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i), 0);
iwl_write_targ_mem(priv, priv->scd_base_addr +
IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) +
IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(i) +
sizeof(u32),
((SCD_WIN_SIZE <<
IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
((SCD_FRAME_LIMIT <<
IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK));
}
iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK,
iwl_write_prph(priv, IWLAGN_SCD_INTERRUPT_MASK,
IWL_MASK(0, priv->hw_params.max_txq_num));
/* Activate all Tx DMA/FIFO channels */

View File

@ -2174,7 +2174,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
}
/* Configure Bluetooth device coexistence support */
iwl_send_bt_config(priv);
priv->cfg->ops->hcmd->send_bt_config(priv);
iwl_reset_run_time_calib(priv);
@ -3178,44 +3178,6 @@ static ssize_t store_tx_power(struct device *d,
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
u32 size = sizeof(struct iwl_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *)&priv->statistics;
int rc = 0;
if (!iwl_is_alive(priv))
return -EAGAIN;
mutex_lock(&priv->mutex);
rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex);
if (rc) {
len = sprintf(buf,
"Error sending statistics request: 0x%08X\n", rc);
return len;
}
while (size && (PAGE_SIZE - len)) {
hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
PAGE_SIZE - len, 1);
len = strlen(buf);
if (PAGE_SIZE - len)
buf[len++] = '\n';
ofs += 16;
size -= min(size, 16U);
}
return len;
}
static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
static ssize_t show_rts_ht_protection(struct device *d,
struct device_attribute *attr, char *buf)
{
@ -3401,11 +3363,10 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
iwl_calib_free_results(priv);
iwlcore_free_geos(priv);
iwl_free_channel_map(priv);
kfree(priv->scan);
kfree(priv->scan_cmd);
}
static struct attribute *iwl_sysfs_entries[] = {
&dev_attr_statistics.attr,
&dev_attr_temperature.attr,
&dev_attr_tx_power.attr,
&dev_attr_rts_ht_protection.attr,
@ -3836,7 +3797,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x4238, 0x1111, iwl6000_3agn_cfg)},
{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000i_g2_2agn_cfg)},
/* 6x00 Series Gen2 */
{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)},
{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)},
{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)},
/* 6x50 WiFi/WiMax Series */
{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},

View File

@ -171,4 +171,7 @@ static inline bool iwl_is_tx_success(u32 status)
(status == TX_STATUS_DIRECT_DONE);
}
/* scan */
void iwlagn_request_scan(struct iwl_priv *priv);
#endif /* __iwl_agn_h__ */

View File

@ -1443,7 +1443,7 @@ struct iwl4965_rx_mpdu_res_start {
/* 1: Ignore Bluetooth priority for this frame.
* 0: Delay Tx until Bluetooth device is done (normal usage). */
#define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12)
#define TX_CMD_FLG_IGNORE_BT cpu_to_le32(1 << 12)
/* 1: uCode overrides sequence control field in MAC header.
* 0: Driver provides sequence control field in MAC header.

View File

@ -828,19 +828,6 @@ static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
return res;
}
/**
* iwl_is_monitor_mode - Determine if interface in monitor mode
*
* priv->iw_mode is set in add_interface, but add_interface is
* never called for monitor mode. The only way mac80211 informs us about
* monitor mode is through configuring filters (call to configure_filter).
*/
bool iwl_is_monitor_mode(struct iwl_priv *priv)
{
return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK);
}
EXPORT_SYMBOL(iwl_is_monitor_mode);
/**
* iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
*
@ -884,19 +871,6 @@ void iwl_set_rxon_chain(struct iwl_priv *priv)
rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
/* copied from 'iwl_bg_request_scan()' */
/* Force use of chains B and C (0x6) for Rx
* Avoid A (0x1) for the device has off-channel reception on A-band.
* MIMO is not used here, but value is required */
if (iwl_is_monitor_mode(priv) &&
!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) &&
priv->cfg->off_channel_workaround) {
rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS;
rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
}
priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain);
if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
@ -1480,7 +1454,7 @@ irqreturn_t iwl_isr_legacy(int irq, void *data)
}
EXPORT_SYMBOL(iwl_isr_legacy);
int iwl_send_bt_config(struct iwl_priv *priv)
void iwl_send_bt_config(struct iwl_priv *priv)
{
struct iwl_bt_cmd bt_cmd = {
.lead_time = BT_LEAD_TIME_DEF,
@ -1497,8 +1471,9 @@ int iwl_send_bt_config(struct iwl_priv *priv)
IWL_DEBUG_INFO(priv, "BT coex %s\n",
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
sizeof(struct iwl_bt_cmd), &bt_cmd);
if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
EXPORT_SYMBOL(iwl_send_bt_config);
@ -1868,7 +1843,6 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv)
iwlcore_commit_rxon(priv);
}
#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
void iwl_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@ -1989,14 +1963,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
iwl_led_associate(priv);
/*
* We have just associated, don't start scan too early
* leave time for EAPOL exchange to complete.
*
* XXX: do this in mac80211
*/
priv->next_scan_jiffies = jiffies +
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
if (!iwl_is_rfkill(priv))
priv->cfg->ops->lib->post_associate(priv);
} else
@ -2383,11 +2349,11 @@ EXPORT_SYMBOL(iwl_free_txq_mem);
int iwl_send_wimax_coex(struct iwl_priv *priv)
{
struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd);
struct iwl_wimax_coex_cmd coex_cmd;
if (priv->cfg->support_wimax_coexist) {
/* UnMask wake up src at associated sleep */
coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
/* UnMask wake up src at unassociated sleep */
coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK;

View File

@ -90,6 +90,7 @@ struct iwl_hcmd_ops {
int (*commit_rxon)(struct iwl_priv *priv);
void (*set_rxon_chain)(struct iwl_priv *priv);
int (*set_tx_ant)(struct iwl_priv *priv, u8 valid_tx_ant);
void (*send_bt_config)(struct iwl_priv *priv);
};
struct iwl_hcmd_utils_ops {
@ -105,6 +106,7 @@ struct iwl_hcmd_utils_ops {
__le32 *tx_flags);
int (*calc_rssi)(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp);
void (*request_scan)(struct iwl_priv *priv);
};
struct iwl_apm_ops {
@ -114,6 +116,15 @@ struct iwl_apm_ops {
int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
};
struct iwl_debugfs_ops {
ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
ssize_t (*general_stats_read)(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos);
};
struct iwl_temp_ops {
void (*temperature)(struct iwl_priv *priv);
void (*set_ct_kill)(struct iwl_priv *priv);
@ -199,6 +210,7 @@ struct iwl_lib_ops {
/* check for ack health */
bool (*check_ack_health)(struct iwl_priv *priv,
struct iwl_rx_packet *pkt);
struct iwl_debugfs_ops debugfs_ops;
};
struct iwl_led_ops {
@ -306,8 +318,8 @@ struct iwl_cfg {
/* timer period for monitor the driver queues */
u32 monitor_recover_period;
bool temperature_kelvin;
bool off_channel_workaround;
u32 max_event_log_size;
u8 scan_antennas[IEEE80211_NUM_BANDS];
};
/***************************
@ -339,7 +351,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags, u64 multicast);
int iwl_set_hw_params(struct iwl_priv *priv);
bool iwl_is_monitor_mode(struct iwl_priv *priv);
void iwl_post_associate(struct iwl_priv *priv);
void iwl_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@ -526,6 +537,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */
#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */
#define IWL_SCAN_CHECK_WATCHDOG (HZ * 7)
/*******************************************************************************
* Calibrations - implemented in iwl-calib.c
@ -665,7 +677,7 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv)
}
extern void iwl_rf_kill_ct_config(struct iwl_priv *priv);
extern int iwl_send_bt_config(struct iwl_priv *priv);
extern void iwl_send_bt_config(struct iwl_priv *priv);
extern int iwl_send_statistics_request(struct iwl_priv *priv,
u8 flags, bool clear);
extern int iwl_verify_ucode(struct iwl_priv *priv);

View File

@ -298,6 +298,7 @@
#define CSR_HW_REV_TYPE_1000 (0x0000060)
#define CSR_HW_REV_TYPE_6x00 (0x0000070)
#define CSR_HW_REV_TYPE_6x50 (0x0000080)
#define CSR_HW_REV_TYPE_6x00g2 (0x00000B0)
#define CSR_HW_REV_TYPE_NONE (0x00000F0)
/* EEPROM REG */

View File

@ -78,6 +78,8 @@ static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_dbgfs_register(struct iwl_priv *priv, const char *name);
void iwl_dbgfs_unregister(struct iwl_priv *priv);
extern int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
int bufsz);
#else
static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
{

View File

@ -106,6 +106,26 @@ static const struct file_operations iwl_dbgfs_##name##_ops = { \
.open = iwl_dbgfs_open_file_generic, \
};
int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
{
int p = 0;
p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
le32_to_cpu(priv->statistics.flag));
if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
p += scnprintf(buf + p, bufsz - p,
"\tStatistics have been cleared\n");
p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
(le32_to_cpu(priv->statistics.flag) &
UCODE_STATISTICS_FREQUENCY_MSK)
? "2.4 GHz" : "5.2 GHz");
p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
(le32_to_cpu(priv->statistics.flag) &
UCODE_STATISTICS_NARROW_BAND_MSK)
? "enabled" : "disabled");
return p;
}
EXPORT_SYMBOL(iwl_dbgfs_statistics_flag);
static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
char __user *user_buf,
@ -1034,474 +1054,15 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
int bufsz)
{
int p = 0;
p += scnprintf(buf + p, bufsz - p,
"Statistics Flag(0x%X):\n",
le32_to_cpu(priv->statistics.flag));
if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
p += scnprintf(buf + p, bufsz - p,
"\tStatistics have been cleared\n");
p += scnprintf(buf + p, bufsz - p,
"\tOperational Frequency: %s\n",
(le32_to_cpu(priv->statistics.flag) &
UCODE_STATISTICS_FREQUENCY_MSK)
? "2.4 GHz" : "5.2 GHz");
p += scnprintf(buf + p, bufsz - p,
"\tTGj Narrow Band: %s\n",
(le32_to_cpu(priv->statistics.flag) &
UCODE_STATISTICS_NARROW_BAND_MSK)
? "enabled" : "disabled");
return p;
}
static const char ucode_stats_header[] =
"%-32s current acumulative delta max\n";
static const char ucode_stats_short_format[] =
" %-30s %10u\n";
static const char ucode_stats_format[] =
" %-30s %10u %10u %10u %10u\n";
static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = sizeof(struct statistics_rx_phy) * 40 +
sizeof(struct statistics_rx_non_phy) * 40 +
sizeof(struct statistics_rx_ht_phy) * 40 + 400;
ssize_t ret;
struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
struct statistics_rx_non_phy *general, *accum_general;
struct statistics_rx_non_phy *delta_general, *max_general;
struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/* the statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
ofdm = &priv->statistics.rx.ofdm;
cck = &priv->statistics.rx.cck;
general = &priv->statistics.rx.general;
ht = &priv->statistics.rx.ofdm_ht;
accum_ofdm = &priv->accum_statistics.rx.ofdm;
accum_cck = &priv->accum_statistics.rx.cck;
accum_general = &priv->accum_statistics.rx.general;
accum_ht = &priv->accum_statistics.rx.ofdm_ht;
delta_ofdm = &priv->delta_statistics.rx.ofdm;
delta_cck = &priv->delta_statistics.rx.cck;
delta_general = &priv->delta_statistics.rx.general;
delta_ht = &priv->delta_statistics.rx.ofdm_ht;
max_ofdm = &priv->max_delta.rx.ofdm;
max_cck = &priv->max_delta.rx.cck;
max_general = &priv->max_delta.rx.general;
max_ht = &priv->max_delta.rx.ofdm_ht;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
"Statistics_Rx - OFDM:");
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
accum_ofdm->ina_cnt,
delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"fina_cnt:",
le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"plcp_err:",
le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
delta_ofdm->plcp_err, max_ofdm->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"crc32_err:",
le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
delta_ofdm->crc32_err, max_ofdm->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"overrun_err:",
le32_to_cpu(ofdm->overrun_err),
accum_ofdm->overrun_err,
delta_ofdm->overrun_err, max_ofdm->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"early_overrun_err:",
le32_to_cpu(ofdm->early_overrun_err),
accum_ofdm->early_overrun_err,
delta_ofdm->early_overrun_err,
max_ofdm->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"crc32_good:",
le32_to_cpu(ofdm->crc32_good),
accum_ofdm->crc32_good,
delta_ofdm->crc32_good, max_ofdm->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"false_alarm_cnt:",
le32_to_cpu(ofdm->false_alarm_cnt),
accum_ofdm->false_alarm_cnt,
delta_ofdm->false_alarm_cnt,
max_ofdm->false_alarm_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"fina_sync_err_cnt:",
le32_to_cpu(ofdm->fina_sync_err_cnt),
accum_ofdm->fina_sync_err_cnt,
delta_ofdm->fina_sync_err_cnt,
max_ofdm->fina_sync_err_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sfd_timeout:",
le32_to_cpu(ofdm->sfd_timeout),
accum_ofdm->sfd_timeout,
delta_ofdm->sfd_timeout,
max_ofdm->sfd_timeout);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"fina_timeout:",
le32_to_cpu(ofdm->fina_timeout),
accum_ofdm->fina_timeout,
delta_ofdm->fina_timeout,
max_ofdm->fina_timeout);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"unresponded_rts:",
le32_to_cpu(ofdm->unresponded_rts),
accum_ofdm->unresponded_rts,
delta_ofdm->unresponded_rts,
max_ofdm->unresponded_rts);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"rxe_frame_lmt_ovrun:",
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
accum_ofdm->rxe_frame_limit_overrun,
delta_ofdm->rxe_frame_limit_overrun,
max_ofdm->rxe_frame_limit_overrun);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sent_ack_cnt:",
le32_to_cpu(ofdm->sent_ack_cnt),
accum_ofdm->sent_ack_cnt,
delta_ofdm->sent_ack_cnt,
max_ofdm->sent_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sent_cts_cnt:",
le32_to_cpu(ofdm->sent_cts_cnt),
accum_ofdm->sent_cts_cnt,
delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sent_ba_rsp_cnt:",
le32_to_cpu(ofdm->sent_ba_rsp_cnt),
accum_ofdm->sent_ba_rsp_cnt,
delta_ofdm->sent_ba_rsp_cnt,
max_ofdm->sent_ba_rsp_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"dsp_self_kill:",
le32_to_cpu(ofdm->dsp_self_kill),
accum_ofdm->dsp_self_kill,
delta_ofdm->dsp_self_kill,
max_ofdm->dsp_self_kill);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"mh_format_err:",
le32_to_cpu(ofdm->mh_format_err),
accum_ofdm->mh_format_err,
delta_ofdm->mh_format_err,
max_ofdm->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"re_acq_main_rssi_sum:",
le32_to_cpu(ofdm->re_acq_main_rssi_sum),
accum_ofdm->re_acq_main_rssi_sum,
delta_ofdm->re_acq_main_rssi_sum,
max_ofdm->re_acq_main_rssi_sum);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
"Statistics_Rx - CCK:");
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"ina_cnt:",
le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
delta_cck->ina_cnt, max_cck->ina_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"fina_cnt:",
le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
delta_cck->fina_cnt, max_cck->fina_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"plcp_err:",
le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
delta_cck->plcp_err, max_cck->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"crc32_err:",
le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
delta_cck->crc32_err, max_cck->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"overrun_err:",
le32_to_cpu(cck->overrun_err),
accum_cck->overrun_err,
delta_cck->overrun_err, max_cck->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"early_overrun_err:",
le32_to_cpu(cck->early_overrun_err),
accum_cck->early_overrun_err,
delta_cck->early_overrun_err,
max_cck->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"crc32_good:",
le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
delta_cck->crc32_good,
max_cck->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"false_alarm_cnt:",
le32_to_cpu(cck->false_alarm_cnt),
accum_cck->false_alarm_cnt,
delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"fina_sync_err_cnt:",
le32_to_cpu(cck->fina_sync_err_cnt),
accum_cck->fina_sync_err_cnt,
delta_cck->fina_sync_err_cnt,
max_cck->fina_sync_err_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sfd_timeout:",
le32_to_cpu(cck->sfd_timeout),
accum_cck->sfd_timeout,
delta_cck->sfd_timeout, max_cck->sfd_timeout);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"fina_timeout:",
le32_to_cpu(cck->fina_timeout),
accum_cck->fina_timeout,
delta_cck->fina_timeout, max_cck->fina_timeout);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"unresponded_rts:",
le32_to_cpu(cck->unresponded_rts),
accum_cck->unresponded_rts,
delta_cck->unresponded_rts,
max_cck->unresponded_rts);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"rxe_frame_lmt_ovrun:",
le32_to_cpu(cck->rxe_frame_limit_overrun),
accum_cck->rxe_frame_limit_overrun,
delta_cck->rxe_frame_limit_overrun,
max_cck->rxe_frame_limit_overrun);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sent_ack_cnt:",
le32_to_cpu(cck->sent_ack_cnt),
accum_cck->sent_ack_cnt,
delta_cck->sent_ack_cnt,
max_cck->sent_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sent_cts_cnt:",
le32_to_cpu(cck->sent_cts_cnt),
accum_cck->sent_cts_cnt,
delta_cck->sent_cts_cnt,
max_cck->sent_cts_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sent_ba_rsp_cnt:",
le32_to_cpu(cck->sent_ba_rsp_cnt),
accum_cck->sent_ba_rsp_cnt,
delta_cck->sent_ba_rsp_cnt,
max_cck->sent_ba_rsp_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"dsp_self_kill:",
le32_to_cpu(cck->dsp_self_kill),
accum_cck->dsp_self_kill,
delta_cck->dsp_self_kill,
max_cck->dsp_self_kill);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"mh_format_err:",
le32_to_cpu(cck->mh_format_err),
accum_cck->mh_format_err,
delta_cck->mh_format_err, max_cck->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"re_acq_main_rssi_sum:",
le32_to_cpu(cck->re_acq_main_rssi_sum),
accum_cck->re_acq_main_rssi_sum,
delta_cck->re_acq_main_rssi_sum,
max_cck->re_acq_main_rssi_sum);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
"Statistics_Rx - GENERAL:");
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"bogus_cts:",
le32_to_cpu(general->bogus_cts),
accum_general->bogus_cts,
delta_general->bogus_cts, max_general->bogus_cts);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"bogus_ack:",
le32_to_cpu(general->bogus_ack),
accum_general->bogus_ack,
delta_general->bogus_ack, max_general->bogus_ack);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"non_bssid_frames:",
le32_to_cpu(general->non_bssid_frames),
accum_general->non_bssid_frames,
delta_general->non_bssid_frames,
max_general->non_bssid_frames);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"filtered_frames:",
le32_to_cpu(general->filtered_frames),
accum_general->filtered_frames,
delta_general->filtered_frames,
max_general->filtered_frames);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"non_channel_beacons:",
le32_to_cpu(general->non_channel_beacons),
accum_general->non_channel_beacons,
delta_general->non_channel_beacons,
max_general->non_channel_beacons);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"channel_beacons:",
le32_to_cpu(general->channel_beacons),
accum_general->channel_beacons,
delta_general->channel_beacons,
max_general->channel_beacons);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"num_missed_bcon:",
le32_to_cpu(general->num_missed_bcon),
accum_general->num_missed_bcon,
delta_general->num_missed_bcon,
max_general->num_missed_bcon);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"adc_rx_saturation_time:",
le32_to_cpu(general->adc_rx_saturation_time),
accum_general->adc_rx_saturation_time,
delta_general->adc_rx_saturation_time,
max_general->adc_rx_saturation_time);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"ina_detect_search_tm:",
le32_to_cpu(general->ina_detection_search_time),
accum_general->ina_detection_search_time,
delta_general->ina_detection_search_time,
max_general->ina_detection_search_time);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_silence_rssi_a:",
le32_to_cpu(general->beacon_silence_rssi_a),
accum_general->beacon_silence_rssi_a,
delta_general->beacon_silence_rssi_a,
max_general->beacon_silence_rssi_a);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_silence_rssi_b:",
le32_to_cpu(general->beacon_silence_rssi_b),
accum_general->beacon_silence_rssi_b,
delta_general->beacon_silence_rssi_b,
max_general->beacon_silence_rssi_b);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_silence_rssi_c:",
le32_to_cpu(general->beacon_silence_rssi_c),
accum_general->beacon_silence_rssi_c,
delta_general->beacon_silence_rssi_c,
max_general->beacon_silence_rssi_c);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"interference_data_flag:",
le32_to_cpu(general->interference_data_flag),
accum_general->interference_data_flag,
delta_general->interference_data_flag,
max_general->interference_data_flag);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"channel_load:",
le32_to_cpu(general->channel_load),
accum_general->channel_load,
delta_general->channel_load,
max_general->channel_load);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"dsp_false_alarms:",
le32_to_cpu(general->dsp_false_alarms),
accum_general->dsp_false_alarms,
delta_general->dsp_false_alarms,
max_general->dsp_false_alarms);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_rssi_a:",
le32_to_cpu(general->beacon_rssi_a),
accum_general->beacon_rssi_a,
delta_general->beacon_rssi_a,
max_general->beacon_rssi_a);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_rssi_b:",
le32_to_cpu(general->beacon_rssi_b),
accum_general->beacon_rssi_b,
delta_general->beacon_rssi_b,
max_general->beacon_rssi_b);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_rssi_c:",
le32_to_cpu(general->beacon_rssi_c),
accum_general->beacon_rssi_c,
delta_general->beacon_rssi_c,
max_general->beacon_rssi_c);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_energy_a:",
le32_to_cpu(general->beacon_energy_a),
accum_general->beacon_energy_a,
delta_general->beacon_energy_a,
max_general->beacon_energy_a);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_energy_b:",
le32_to_cpu(general->beacon_energy_b),
accum_general->beacon_energy_b,
delta_general->beacon_energy_b,
max_general->beacon_energy_b);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"beacon_energy_c:",
le32_to_cpu(general->beacon_energy_c),
accum_general->beacon_energy_c,
delta_general->beacon_energy_c,
max_general->beacon_energy_c);
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
"Statistics_Rx - OFDM_HT:");
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"plcp_err:",
le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
delta_ht->plcp_err, max_ht->plcp_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"overrun_err:",
le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
delta_ht->overrun_err, max_ht->overrun_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"early_overrun_err:",
le32_to_cpu(ht->early_overrun_err),
accum_ht->early_overrun_err,
delta_ht->early_overrun_err,
max_ht->early_overrun_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"crc32_good:",
le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
delta_ht->crc32_good, max_ht->crc32_good);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"crc32_err:",
le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
delta_ht->crc32_err, max_ht->crc32_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"mh_format_err:",
le32_to_cpu(ht->mh_format_err),
accum_ht->mh_format_err,
delta_ht->mh_format_err, max_ht->mh_format_err);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg_crc32_good:",
le32_to_cpu(ht->agg_crc32_good),
accum_ht->agg_crc32_good,
delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg_mpdu_cnt:",
le32_to_cpu(ht->agg_mpdu_cnt),
accum_ht->agg_mpdu_cnt,
delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg_cnt:",
le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
delta_ht->agg_cnt, max_ht->agg_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"unsupport_mcs:",
le32_to_cpu(ht->unsupport_mcs),
accum_ht->unsupport_mcs,
delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
if (priv->cfg->ops->lib->debugfs_ops.rx_stats_read)
return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
user_buf, count, ppos);
return 0;
}
static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
@ -1509,173 +1070,10 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
ssize_t ret;
struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/* the statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
tx = &priv->statistics.tx;
accum_tx = &priv->accum_statistics.tx;
delta_tx = &priv->delta_statistics.tx;
max_tx = &priv->max_delta.tx;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
"Statistics_Tx:");
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"preamble:",
le32_to_cpu(tx->preamble_cnt),
accum_tx->preamble_cnt,
delta_tx->preamble_cnt, max_tx->preamble_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"rx_detected_cnt:",
le32_to_cpu(tx->rx_detected_cnt),
accum_tx->rx_detected_cnt,
delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"bt_prio_defer_cnt:",
le32_to_cpu(tx->bt_prio_defer_cnt),
accum_tx->bt_prio_defer_cnt,
delta_tx->bt_prio_defer_cnt,
max_tx->bt_prio_defer_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"bt_prio_kill_cnt:",
le32_to_cpu(tx->bt_prio_kill_cnt),
accum_tx->bt_prio_kill_cnt,
delta_tx->bt_prio_kill_cnt,
max_tx->bt_prio_kill_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"few_bytes_cnt:",
le32_to_cpu(tx->few_bytes_cnt),
accum_tx->few_bytes_cnt,
delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"cts_timeout:",
le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
delta_tx->cts_timeout, max_tx->cts_timeout);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"ack_timeout:",
le32_to_cpu(tx->ack_timeout),
accum_tx->ack_timeout,
delta_tx->ack_timeout, max_tx->ack_timeout);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"expected_ack_cnt:",
le32_to_cpu(tx->expected_ack_cnt),
accum_tx->expected_ack_cnt,
delta_tx->expected_ack_cnt,
max_tx->expected_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"actual_ack_cnt:",
le32_to_cpu(tx->actual_ack_cnt),
accum_tx->actual_ack_cnt,
delta_tx->actual_ack_cnt,
max_tx->actual_ack_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"dump_msdu_cnt:",
le32_to_cpu(tx->dump_msdu_cnt),
accum_tx->dump_msdu_cnt,
delta_tx->dump_msdu_cnt,
max_tx->dump_msdu_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"abort_nxt_frame_mismatch:",
le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
accum_tx->burst_abort_next_frame_mismatch_cnt,
delta_tx->burst_abort_next_frame_mismatch_cnt,
max_tx->burst_abort_next_frame_mismatch_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"abort_missing_nxt_frame:",
le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
accum_tx->burst_abort_missing_next_frame_cnt,
delta_tx->burst_abort_missing_next_frame_cnt,
max_tx->burst_abort_missing_next_frame_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"cts_timeout_collision:",
le32_to_cpu(tx->cts_timeout_collision),
accum_tx->cts_timeout_collision,
delta_tx->cts_timeout_collision,
max_tx->cts_timeout_collision);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"ack_ba_timeout_collision:",
le32_to_cpu(tx->ack_or_ba_timeout_collision),
accum_tx->ack_or_ba_timeout_collision,
delta_tx->ack_or_ba_timeout_collision,
max_tx->ack_or_ba_timeout_collision);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg ba_timeout:",
le32_to_cpu(tx->agg.ba_timeout),
accum_tx->agg.ba_timeout,
delta_tx->agg.ba_timeout,
max_tx->agg.ba_timeout);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg ba_resched_frames:",
le32_to_cpu(tx->agg.ba_reschedule_frames),
accum_tx->agg.ba_reschedule_frames,
delta_tx->agg.ba_reschedule_frames,
max_tx->agg.ba_reschedule_frames);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg scd_query_agg_frame:",
le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
accum_tx->agg.scd_query_agg_frame_cnt,
delta_tx->agg.scd_query_agg_frame_cnt,
max_tx->agg.scd_query_agg_frame_cnt);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg scd_query_no_agg:",
le32_to_cpu(tx->agg.scd_query_no_agg),
accum_tx->agg.scd_query_no_agg,
delta_tx->agg.scd_query_no_agg,
max_tx->agg.scd_query_no_agg);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg scd_query_agg:",
le32_to_cpu(tx->agg.scd_query_agg),
accum_tx->agg.scd_query_agg,
delta_tx->agg.scd_query_agg,
max_tx->agg.scd_query_agg);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg scd_query_mismatch:",
le32_to_cpu(tx->agg.scd_query_mismatch),
accum_tx->agg.scd_query_mismatch,
delta_tx->agg.scd_query_mismatch,
max_tx->agg.scd_query_mismatch);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg frame_not_ready:",
le32_to_cpu(tx->agg.frame_not_ready),
accum_tx->agg.frame_not_ready,
delta_tx->agg.frame_not_ready,
max_tx->agg.frame_not_ready);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg underrun:",
le32_to_cpu(tx->agg.underrun),
accum_tx->agg.underrun,
delta_tx->agg.underrun, max_tx->agg.underrun);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg bt_prio_kill:",
le32_to_cpu(tx->agg.bt_prio_kill),
accum_tx->agg.bt_prio_kill,
delta_tx->agg.bt_prio_kill,
max_tx->agg.bt_prio_kill);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"agg rx_ba_rsp_cnt:",
le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
accum_tx->agg.rx_ba_rsp_cnt,
delta_tx->agg.rx_ba_rsp_cnt,
max_tx->agg.rx_ba_rsp_cnt);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
if (priv->cfg->ops->lib->debugfs_ops.tx_stats_read)
return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
user_buf, count, ppos);
return 0;
}
static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
@ -1683,107 +1081,10 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
size_t count, loff_t *ppos)
{
struct iwl_priv *priv = file->private_data;
int pos = 0;
char *buf;
int bufsz = sizeof(struct statistics_general) * 10 + 300;
ssize_t ret;
struct statistics_general *general, *accum_general;
struct statistics_general *delta_general, *max_general;
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
struct statistics_div *div, *accum_div, *delta_div, *max_div;
if (!iwl_is_alive(priv))
return -EAGAIN;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf) {
IWL_ERR(priv, "Can not allocate Buffer\n");
return -ENOMEM;
}
/* the statistic information display here is based on
* the last statistics notification from uCode
* might not reflect the current uCode activity
*/
general = &priv->statistics.general;
dbg = &priv->statistics.general.dbg;
div = &priv->statistics.general.div;
accum_general = &priv->accum_statistics.general;
delta_general = &priv->delta_statistics.general;
max_general = &priv->max_delta.general;
accum_dbg = &priv->accum_statistics.general.dbg;
delta_dbg = &priv->delta_statistics.general.dbg;
max_dbg = &priv->max_delta.general.dbg;
accum_div = &priv->accum_statistics.general.div;
delta_div = &priv->delta_statistics.general.div;
max_div = &priv->max_delta.general.div;
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_header,
"Statistics_General:");
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
"temperature:",
le32_to_cpu(general->temperature));
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_short_format,
"temperature_m:",
le32_to_cpu(general->temperature_m));
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"burst_check:",
le32_to_cpu(dbg->burst_check),
accum_dbg->burst_check,
delta_dbg->burst_check, max_dbg->burst_check);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"burst_count:",
le32_to_cpu(dbg->burst_count),
accum_dbg->burst_count,
delta_dbg->burst_count, max_dbg->burst_count);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"sleep_time:",
le32_to_cpu(general->sleep_time),
accum_general->sleep_time,
delta_general->sleep_time, max_general->sleep_time);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"slots_out:",
le32_to_cpu(general->slots_out),
accum_general->slots_out,
delta_general->slots_out, max_general->slots_out);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"slots_idle:",
le32_to_cpu(general->slots_idle),
accum_general->slots_idle,
delta_general->slots_idle, max_general->slots_idle);
pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
le32_to_cpu(general->ttl_timestamp));
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"tx_on_a:",
le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
delta_div->tx_on_a, max_div->tx_on_a);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"tx_on_b:",
le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
delta_div->tx_on_b, max_div->tx_on_b);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"exec_time:",
le32_to_cpu(div->exec_time), accum_div->exec_time,
delta_div->exec_time, max_div->exec_time);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"probe_time:",
le32_to_cpu(div->probe_time), accum_div->probe_time,
delta_div->probe_time, max_div->probe_time);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"rx_enable_counter:",
le32_to_cpu(general->rx_enable_counter),
accum_general->rx_enable_counter,
delta_general->rx_enable_counter,
max_general->rx_enable_counter);
pos += scnprintf(buf + pos, bufsz - pos, ucode_stats_format,
"num_of_sos_states:",
le32_to_cpu(general->num_of_sos_states),
accum_general->num_of_sos_states,
delta_general->num_of_sos_states,
max_general->num_of_sos_states);
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
kfree(buf);
return ret;
if (priv->cfg->ops->lib->debugfs_ops.general_stats_read)
return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
user_buf, count, ppos);
return 0;
}
static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
@ -2341,10 +1642,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);

View File

@ -58,7 +58,7 @@ extern struct iwl_cfg iwl5100_abg_cfg;
extern struct iwl_cfg iwl5150_agn_cfg;
extern struct iwl_cfg iwl5150_abg_cfg;
extern struct iwl_cfg iwl6000i_2agn_cfg;
extern struct iwl_cfg iwl6000i_g2_2agn_cfg;
extern struct iwl_cfg iwl6000g2_2agn_cfg;
extern struct iwl_cfg iwl6000i_2abg_cfg;
extern struct iwl_cfg iwl6000i_2bg_cfg;
extern struct iwl_cfg iwl6000_3agn_cfg;
@ -1049,12 +1049,10 @@ struct iwl_priv {
struct iwl_calib_result calib_results[IWL_CALIB_MAX];
/* Scan related variables */
unsigned long next_scan_jiffies;
unsigned long scan_start;
unsigned long scan_pass_start;
unsigned long scan_start_tsf;
void *scan;
int scan_bands;
void *scan_cmd;
enum ieee80211_band scan_band;
struct cfg80211_scan_request *scan_request;
bool is_internal_short_scan;
u8 scan_tx_ant[IEEE80211_NUM_BANDS];
@ -1259,7 +1257,6 @@ struct iwl_priv {
struct work_struct scan_completed;
struct work_struct rx_replenish;
struct work_struct abort_scan;
struct work_struct request_scan;
struct work_struct beacon_update;
struct work_struct tt_work;
struct work_struct ct_enter;

View File

@ -172,22 +172,22 @@ struct iwl_eeprom_enhanced_txpwr {
#define EEPROM_5000_TX_POWER_VERSION (4)
#define EEPROM_5000_EEPROM_VERSION (0x11A)
/*5000 calibrations */
#define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
#define EEPROM_5000_XTAL ((2*0x128) | EEPROM_5000_CALIB_ALL)
#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_5000_CALIB_ALL)
/* 5000 and up calibration */
#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL)
/* 5000 links */
#define EEPROM_5000_LINK_HOST (2*0x64)
#define EEPROM_5000_LINK_GENERAL (2*0x65)
#define EEPROM_5000_LINK_REGULATORY (2*0x66)
#define EEPROM_5000_LINK_CALIBRATION (2*0x67)
#define EEPROM_5000_LINK_PROCESS_ADJST (2*0x68)
#define EEPROM_5000_LINK_OTHERS (2*0x69)
/* 5000 temperature */
#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
/* 5000 regulatory - indirect access */
#define EEPROM_5000_REG_SKU_ID ((0x02)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */
/* agn links */
#define EEPROM_LINK_HOST (2*0x64)
#define EEPROM_LINK_GENERAL (2*0x65)
#define EEPROM_LINK_REGULATORY (2*0x66)
#define EEPROM_LINK_CALIBRATION (2*0x67)
#define EEPROM_LINK_PROCESS_ADJST (2*0x68)
#define EEPROM_LINK_OTHERS (2*0x69)
/* agn regulatory - indirect access */
#define EEPROM_REG_BAND_1_CHANNELS ((0x08)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */
#define EEPROM_REG_BAND_2_CHANNELS ((0x26)\
@ -276,6 +276,10 @@ struct iwl_eeprom_enhanced_txpwr {
#define EEPROM_6050_TX_POWER_VERSION (4)
#define EEPROM_6050_EEPROM_VERSION (0x532)
/* 6x00g2 Specific */
#define EEPROM_6000G2_TX_POWER_VERSION (6)
#define EEPROM_6000G2_EEPROM_VERSION (0x709)
/* OTP */
/* lower blocks contain EEPROM image and calibration data */
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */

View File

@ -529,48 +529,48 @@
#define IWL_SCD_TXFIFO_POS_RA (4)
#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
/* 5000 SCD */
#define IWL50_SCD_QUEUE_STTS_REG_POS_TXF (0)
#define IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE (3)
#define IWL50_SCD_QUEUE_STTS_REG_POS_WSL (4)
#define IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
#define IWL50_SCD_QUEUE_STTS_REG_MSK (0x00FF0000)
/* agn SCD */
#define IWLAGN_SCD_QUEUE_STTS_REG_POS_TXF (0)
#define IWLAGN_SCD_QUEUE_STTS_REG_POS_ACTIVE (3)
#define IWLAGN_SCD_QUEUE_STTS_REG_POS_WSL (4)
#define IWLAGN_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19)
#define IWLAGN_SCD_QUEUE_STTS_REG_MSK (0x00FF0000)
#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0)
#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F)
#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
#define IWLAGN_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
#define IWLAGN_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0)
#define IWLAGN_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F)
#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
#define IWLAGN_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
#define IWL50_SCD_CONTEXT_DATA_OFFSET (0x600)
#define IWL50_SCD_TX_STTS_BITMAP_OFFSET (0x7B1)
#define IWL50_SCD_TRANSLATE_TBL_OFFSET (0x7E0)
#define IWLAGN_SCD_CONTEXT_DATA_OFFSET (0x600)
#define IWLAGN_SCD_TX_STTS_BITMAP_OFFSET (0x7B1)
#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET (0x7E0)
#define IWL50_SCD_CONTEXT_QUEUE_OFFSET(x)\
(IWL50_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
#define IWLAGN_SCD_CONTEXT_QUEUE_OFFSET(x)\
(IWLAGN_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
#define IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
((IWL50_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
#define IWLAGN_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
((IWLAGN_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc)
#define IWL50_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\
#define IWLAGN_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\
(~(1<<IWL_CMD_QUEUE_NUM)))
#define IWL50_SCD_BASE (PRPH_BASE + 0xa02c00)
#define IWLAGN_SCD_BASE (PRPH_BASE + 0xa02c00)
#define IWL50_SCD_SRAM_BASE_ADDR (IWL50_SCD_BASE + 0x0)
#define IWL50_SCD_DRAM_BASE_ADDR (IWL50_SCD_BASE + 0x8)
#define IWL50_SCD_AIT (IWL50_SCD_BASE + 0x0c)
#define IWL50_SCD_TXFACT (IWL50_SCD_BASE + 0x10)
#define IWL50_SCD_ACTIVE (IWL50_SCD_BASE + 0x14)
#define IWL50_SCD_QUEUE_WRPTR(x) (IWL50_SCD_BASE + 0x18 + (x) * 4)
#define IWL50_SCD_QUEUE_RDPTR(x) (IWL50_SCD_BASE + 0x68 + (x) * 4)
#define IWL50_SCD_QUEUECHAIN_SEL (IWL50_SCD_BASE + 0xe8)
#define IWL50_SCD_AGGR_SEL (IWL50_SCD_BASE + 0x248)
#define IWL50_SCD_INTERRUPT_MASK (IWL50_SCD_BASE + 0x108)
#define IWL50_SCD_QUEUE_STATUS_BITS(x) (IWL50_SCD_BASE + 0x10c + (x) * 4)
#define IWLAGN_SCD_SRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x0)
#define IWLAGN_SCD_DRAM_BASE_ADDR (IWLAGN_SCD_BASE + 0x8)
#define IWLAGN_SCD_AIT (IWLAGN_SCD_BASE + 0x0c)
#define IWLAGN_SCD_TXFACT (IWLAGN_SCD_BASE + 0x10)
#define IWLAGN_SCD_ACTIVE (IWLAGN_SCD_BASE + 0x14)
#define IWLAGN_SCD_QUEUE_WRPTR(x) (IWLAGN_SCD_BASE + 0x18 + (x) * 4)
#define IWLAGN_SCD_QUEUE_RDPTR(x) (IWLAGN_SCD_BASE + 0x68 + (x) * 4)
#define IWLAGN_SCD_QUEUECHAIN_SEL (IWLAGN_SCD_BASE + 0xe8)
#define IWLAGN_SCD_AGGR_SEL (IWLAGN_SCD_BASE + 0x248)
#define IWLAGN_SCD_INTERRUPT_MASK (IWLAGN_SCD_BASE + 0x108)
#define IWLAGN_SCD_QUEUE_STATUS_BITS(x) (IWLAGN_SCD_BASE + 0x10c + (x) * 4)
/*********************** END TX SCHEDULER *************************************/

View File

@ -69,9 +69,8 @@ int iwl_scan_cancel(struct iwl_priv *priv)
}
if (test_bit(STATUS_SCANNING, &priv->status)) {
if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
if (!test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n");
set_bit(STATUS_SCAN_ABORTING, &priv->status);
queue_work(priv->workqueue, &priv->abort_scan);
} else
@ -201,9 +200,6 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
le32_to_cpu(notif->statistics[0]),
le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
#endif
if (!priv->is_internal_short_scan)
priv->next_scan_jiffies = 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
@ -223,49 +219,24 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
/* The HW is no longer scanning */
clear_bit(STATUS_SCAN_HW, &priv->status);
IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n",
(priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ?
"2.4" : "5.2",
IWL_DEBUG_INFO(priv, "Scan on %sGHz took %dms\n",
(priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
jiffies_to_msecs(elapsed_jiffies
(priv->scan_pass_start, jiffies)));
(priv->scan_start, jiffies)));
/* Remove this scanned band from the list of pending
* bands to scan, band G precedes A in order of scanning
* as seen in iwl_bg_request_scan */
if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ))
priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ);
else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ))
priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ);
/* If a request to abort was given, or the scan did not succeed
/*
* If a request to abort was given, or the scan did not succeed
* then we reset the scan state machine and terminate,
* re-queuing another scan if one has been requested */
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
* re-queuing another scan if one has been requested
*/
if (test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status))
IWL_DEBUG_INFO(priv, "Aborted scan completed.\n");
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
} else {
/* If there are more bands on this scan pass reschedule */
if (priv->scan_bands)
goto reschedule;
}
if (!priv->is_internal_short_scan)
priv->next_scan_jiffies = 0;
IWL_DEBUG_INFO(priv, "Setting scan to off\n");
clear_bit(STATUS_SCANNING, &priv->status);
IWL_DEBUG_INFO(priv, "Scan took %dms\n",
jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies)));
queue_work(priv->workqueue, &priv->scan_completed);
return;
reschedule:
priv->scan_pass_start = jiffies;
queue_work(priv->workqueue, &priv->request_scan);
}
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
@ -314,150 +285,6 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_get_passive_dwell_time);
static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
struct iwl_scan_channel *scan_ch)
{
const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int i, added = 0;
u16 channel = 0;
sband = iwl_get_hw_mode(priv, band);
if (!sband) {
IWL_ERR(priv, "invalid band\n");
return added;
}
active_dwell = iwl_get_active_dwell_time(priv, band, 0);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
/* only scan single channel, good enough to reset the RF */
/* pick the first valid not in-use channel */
if (band == IEEE80211_BAND_5GHZ) {
for (i = 14; i < priv->channel_count; i++) {
if (priv->channel_info[i].channel !=
le16_to_cpu(priv->staging_rxon.channel)) {
channel = priv->channel_info[i].channel;
ch_info = iwl_get_channel_info(priv,
band, channel);
if (is_channel_valid(ch_info))
break;
}
}
} else {
for (i = 0; i < 14; i++) {
if (priv->channel_info[i].channel !=
le16_to_cpu(priv->staging_rxon.channel)) {
channel =
priv->channel_info[i].channel;
ch_info = iwl_get_channel_info(priv,
band, channel);
if (is_channel_valid(ch_info))
break;
}
}
}
if (channel) {
scan_ch->channel = cpu_to_le16(channel);
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
/* Set txpower levels to defaults */
scan_ch->dsp_atten = 110;
if (band == IEEE80211_BAND_5GHZ)
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
else
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
added++;
} else
IWL_ERR(priv, "no valid channel found\n");
return added;
}
static int iwl_get_channels_for_scan(struct iwl_priv *priv,
enum ieee80211_band band,
u8 is_active, u8 n_probes,
struct iwl_scan_channel *scan_ch)
{
struct ieee80211_channel *chan;
const struct ieee80211_supported_band *sband;
const struct iwl_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int added, i;
u16 channel;
sband = iwl_get_hw_mode(priv, band);
if (!sband)
return 0;
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
passive_dwell = iwl_get_passive_dwell_time(priv, band);
if (passive_dwell <= active_dwell)
passive_dwell = active_dwell + 1;
for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
chan = priv->scan_request->channels[i];
if (chan->band != band)
continue;
channel = ieee80211_frequency_to_channel(chan->center_freq);
scan_ch->channel = cpu_to_le16(channel);
ch_info = iwl_get_channel_info(priv, band, channel);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
channel);
continue;
}
if (!is_active || is_channel_passive(ch_info) ||
(chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
else
scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
if (n_probes)
scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
/* Set txpower levels to defaults */
scan_ch->dsp_atten = 110;
/* NOTE: if we were doing 6Mb OFDM for scans we'd use
* power level:
* scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
*/
if (band == IEEE80211_BAND_5GHZ)
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
else
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
channel, le32_to_cpu(scan_ch->type),
(scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
"ACTIVE" : "PASSIVE",
(scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
active_dwell : passive_dwell);
scan_ch++;
added++;
}
IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
return added;
}
void iwl_init_scan_params(struct iwl_priv *priv)
{
u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
@ -476,26 +303,27 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
set_bit(STATUS_SCANNING, &priv->status);
priv->is_internal_short_scan = false;
priv->scan_start = jiffies;
priv->scan_pass_start = priv->scan_start;
queue_work(priv->workqueue, &priv->request_scan);
if (WARN_ON(!priv->cfg->ops->utils->request_scan))
return -EOPNOTSUPP;
priv->cfg->ops->utils->request_scan(priv);
return 0;
}
#define IWL_DELAY_NEXT_SCAN (HZ*2)
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
struct cfg80211_scan_request *req)
{
unsigned long flags;
struct iwl_priv *priv = hw->priv;
int ret, i;
int ret;
IWL_DEBUG_MAC80211(priv, "enter\n");
if (req->n_channels == 0)
return -EINVAL;
mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
if (!iwl_is_ready_rf(priv)) {
ret = -EIO;
@ -515,22 +343,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
goto out_unlock;
}
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
*/
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n");
queue_work(priv->workqueue, &priv->scan_completed);
ret = 0;
goto out_unlock;
}
priv->scan_bands = 0;
for (i = 0; i < req->n_channels; i++)
priv->scan_bands |= BIT(req->channels[i]->band);
/* mac80211 will only ask for one band at a time */
priv->scan_band = req->channels[0]->band;
priv->scan_request = req;
ret = iwl_scan_initiate(priv);
@ -538,7 +352,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(priv, "leave\n");
out_unlock:
spin_unlock_irqrestore(&priv->lock, flags);
mutex_unlock(&priv->mutex);
return ret;
@ -576,22 +389,20 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
goto unlock;
}
priv->scan_bands = 0;
if (priv->band == IEEE80211_BAND_5GHZ)
priv->scan_bands |= BIT(IEEE80211_BAND_5GHZ);
else
priv->scan_bands |= BIT(IEEE80211_BAND_2GHZ);
priv->scan_band = priv->band;
IWL_DEBUG_SCAN(priv, "Start internal short scan...\n");
set_bit(STATUS_SCANNING, &priv->status);
priv->is_internal_short_scan = true;
queue_work(priv->workqueue, &priv->request_scan);
if (WARN_ON(!priv->cfg->ops->utils->request_scan))
goto unlock;
priv->cfg->ops->utils->request_scan(priv);
unlock:
mutex_unlock(&priv->mutex);
}
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
void iwl_bg_scan_check(struct work_struct *data)
{
struct iwl_priv *priv =
@ -653,275 +464,15 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
if (WARN_ON(left < ie_len))
return len;
if (ies)
if (ies && ie_len) {
memcpy(pos, ies, ie_len);
len += ie_len;
left -= ie_len;
len += ie_len;
}
return (u16)len;
}
EXPORT_SYMBOL(iwl_fill_probe_req);
static void iwl_bg_request_scan(struct work_struct *data)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, request_scan);
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl_scan_cmd),
.flags = CMD_SIZE_HUGE,
};
struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
u32 rate_flags = 0;
u16 cmd_len;
u16 rx_chain = 0;
enum ieee80211_band band;
u8 n_probes = 0;
u8 rx_ant = priv->hw_params.valid_rx_ant;
u8 rate;
bool is_active = false;
int chan_mod;
u8 active_chains;
conf = ieee80211_get_hw_conf(priv->hw);
mutex_lock(&priv->mutex);
cancel_delayed_work(&priv->scan_check);
if (!iwl_is_ready(priv)) {
IWL_WARN(priv, "request scan called when driver not ready.\n");
goto done;
}
/* Make sure the scan wasn't canceled before this queued work
* was given the chance to run... */
if (!test_bit(STATUS_SCANNING, &priv->status))
goto done;
/* This should never be called or scheduled if there is currently
* a scan active in the hardware. */
if (test_bit(STATUS_SCAN_HW, &priv->status)) {
IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. "
"Ignoring second request.\n");
goto done;
}
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n");
goto done;
}
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n");
goto done;
}
if (iwl_is_rfkill(priv)) {
IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n");
goto done;
}
if (!test_bit(STATUS_READY, &priv->status)) {
IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n");
goto done;
}
if (!priv->scan_bands) {
IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
goto done;
}
if (!priv->scan) {
priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan) {
IWL_DEBUG_SCAN(priv,
"fail to allocate memory for scan\n");
goto done;
}
}
scan = priv->scan;
memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
if (iwl_is_associated(priv)) {
u16 interval = 0;
u32 extra;
u32 suspend_time = 100;
u32 scan_suspend_time = 100;
unsigned long flags;
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
spin_lock_irqsave(&priv->lock, flags);
interval = priv->beacon_int;
spin_unlock_irqrestore(&priv->lock, flags);
scan->suspend_time = 0;
scan->max_out_time = cpu_to_le32(200 * 1024);
if (!interval)
interval = suspend_time;
extra = (suspend_time / interval) << 22;
scan_suspend_time = (extra |
((suspend_time % interval) * 1024));
scan->suspend_time = cpu_to_le32(scan_suspend_time);
IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
scan_suspend_time, interval);
}
if (priv->is_internal_short_scan) {
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
} else if (priv->scan_request->n_ssids) {
int i, p = 0;
IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
for (i = 0; i < priv->scan_request->n_ssids; i++) {
/* always does wildcard anyway */
if (!priv->scan_request->ssids[i].ssid_len)
continue;
scan->direct_scan[p].id = WLAN_EID_SSID;
scan->direct_scan[p].len =
priv->scan_request->ssids[i].ssid_len;
memcpy(scan->direct_scan[p].ssid,
priv->scan_request->ssids[i].ssid,
priv->scan_request->ssids[i].ssid_len);
n_probes++;
p++;
}
is_active = true;
} else
IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
band = IEEE80211_BAND_2GHZ;
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
>> RXON_FLG_CHANNEL_MODE_POS;
if (chan_mod == CHANNEL_MODE_PURE_40) {
rate = IWL_RATE_6M_PLCP;
} else {
rate = IWL_RATE_1M_PLCP;
rate_flags = RATE_MCS_CCK_MSK;
}
scan->good_CRC_th = 0;
} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
band = IEEE80211_BAND_5GHZ;
rate = IWL_RATE_6M_PLCP;
/*
* If active scaning is requested but a certain channel
* is marked passive, we can do active scanning if we
* detect transmissions.
*/
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
/* Force use of chains B and C (0x6) for scan Rx
* Avoid A (0x1) for the device has off-channel reception
* on A-band.
*/
if (priv->cfg->off_channel_workaround)
rx_ant = ANT_BC;
} else {
IWL_WARN(priv, "Invalid scan band count\n");
goto done;
}
priv->scan_tx_ant[band] =
iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
/* In power save mode use one chain, otherwise use all chains */
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
/* rx_ant has been set to all valid chains previously */
active_chains = rx_ant &
((u8)(priv->chain_noise_data.active_chains));
if (!active_chains)
active_chains = rx_ant;
IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
priv->chain_noise_data.active_chains);
rx_ant = first_antenna(active_chains);
}
/* MIMO is not used here, but value is required */
rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
scan->rx_chain = cpu_to_le16(rx_chain);
if (!priv->is_internal_short_scan) {
cmd_len = iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
priv->scan_request->ie,
priv->scan_request->ie_len,
IWL_MAX_SCAN_SIZE - sizeof(*scan));
} else {
cmd_len = iwl_fill_probe_req(priv,
(struct ieee80211_mgmt *)scan->data,
NULL, 0,
IWL_MAX_SCAN_SIZE - sizeof(*scan));
}
scan->tx_cmd.len = cpu_to_le16(cmd_len);
if (iwl_is_monitor_mode(priv))
scan->filter_flags = RXON_FILTER_PROMISC_MSK;
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
RXON_FILTER_BCON_AWARE_MSK);
if (priv->is_internal_short_scan) {
scan->channel_count =
iwl_get_single_channel_for_scan(priv, band,
(void *)&scan->data[le16_to_cpu(
scan->tx_cmd.len)]);
} else {
scan->channel_count =
iwl_get_channels_for_scan(priv, band,
is_active, n_probes,
(void *)&scan->data[le16_to_cpu(
scan->tx_cmd.len)]);
}
if (scan->channel_count == 0) {
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
goto done;
}
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
scan->channel_count * sizeof(struct iwl_scan_channel);
cmd.data = scan;
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
if (iwl_send_cmd_sync(priv, &cmd))
goto done;
queue_delayed_work(priv->workqueue, &priv->scan_check,
IWL_SCAN_CHECK_WATCHDOG);
mutex_unlock(&priv->mutex);
return;
done:
/* Cannot perform scan. Make sure we clear scanning
* bits from status so next scan request can be performed.
* If we don't clear scanning status bit here all next scan
* will fail
*/
clear_bit(STATUS_SCAN_HW, &priv->status);
clear_bit(STATUS_SCANNING, &priv->status);
/* inform mac80211 scan aborted */
queue_work(priv->workqueue, &priv->scan_completed);
mutex_unlock(&priv->mutex);
}
void iwl_bg_abort_scan(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
@ -969,7 +520,6 @@ EXPORT_SYMBOL(iwl_bg_scan_completed);
void iwl_setup_scan_deferred_work(struct iwl_priv *priv)
{
INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);

View File

@ -451,7 +451,17 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)
link_cmd.general_params.single_stream_ant_msk =
first_antenna(priv->hw_params.valid_tx_ant);
link_cmd.general_params.dual_stream_ant_msk = 3;
link_cmd.general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant &
~first_antenna(priv->hw_params.valid_tx_ant);
if (!link_cmd.general_params.dual_stream_ant_msk) {
link_cmd.general_params.dual_stream_ant_msk = ANT_AB;
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
link_cmd.general_params.dual_stream_ant_msk =
priv->hw_params.valid_tx_ant;
}
link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
link_cmd.agg_params.agg_time_limit =
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
@ -1196,7 +1206,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
iwl_dump_lq_cmd(priv, lq);
BUG_ON(init && (cmd.flags & CMD_ASYNC));
iwl_dump_lq_cmd(priv, lq);
ret = iwl_send_cmd(priv, &cmd);
if (ret || (cmd.flags & CMD_ASYNC))
return ret;

View File

@ -2527,7 +2527,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
}
/* Configure Bluetooth device coexistence support */
iwl_send_bt_config(priv);
priv->cfg->ops->hcmd->send_bt_config(priv);
/* Configure the adapter for unassociated operation */
iwlcore_commit_rxon(priv);
@ -2791,11 +2791,8 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
}
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
static void iwl3945_bg_request_scan(struct work_struct *data)
void iwl3945_request_scan(struct iwl_priv *priv)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, request_scan);
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = sizeof(struct iwl3945_scan_cmd),
@ -2809,8 +2806,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
conf = ieee80211_get_hw_conf(priv->hw);
mutex_lock(&priv->mutex);
cancel_delayed_work(&priv->scan_check);
if (!iwl_is_ready(priv)) {
@ -2853,20 +2848,15 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
goto done;
}
if (!priv->scan_bands) {
IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n");
goto done;
}
if (!priv->scan) {
priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan) {
if (!priv->scan_cmd) {
priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan_cmd) {
IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
goto done;
}
}
scan = priv->scan;
scan = priv->scan_cmd;
memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
@ -2935,12 +2925,14 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
/* flags + rate selection */
if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
switch (priv->scan_band) {
case IEEE80211_BAND_2GHZ:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
scan->good_CRC_th = 0;
band = IEEE80211_BAND_2GHZ;
} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
break;
case IEEE80211_BAND_5GHZ:
scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
/*
* If active scaning is requested but a certain channel
@ -2949,8 +2941,9 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
*/
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
band = IEEE80211_BAND_5GHZ;
} else {
IWL_WARN(priv, "Invalid scan band count\n");
break;
default:
IWL_WARN(priv, "Invalid scan band\n");
goto done;
}
@ -2971,9 +2964,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
/* select Rx antennas */
scan->flags |= iwl3945_get_antenna_flags(priv);
if (iwl_is_monitor_mode(priv))
scan->filter_flags = RXON_FILTER_PROMISC_MSK;
scan->channel_count =
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
@ -2995,7 +2985,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
queue_delayed_work(priv->workqueue, &priv->scan_check,
IWL_SCAN_CHECK_WATCHDOG);
mutex_unlock(&priv->mutex);
return;
done:
@ -3009,7 +2998,6 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
/* inform mac80211 scan aborted */
queue_work(priv->workqueue, &priv->scan_completed);
mutex_unlock(&priv->mutex);
}
static void iwl3945_bg_restart(struct work_struct *data)
@ -3051,8 +3039,6 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
mutex_unlock(&priv->mutex);
}
#define IWL_DELAY_NEXT_SCAN (HZ*2)
void iwl3945_post_associate(struct iwl_priv *priv)
{
int rc = 0;
@ -3137,9 +3123,6 @@ void iwl3945_post_associate(struct iwl_priv *priv)
__func__, priv->iw_mode);
break;
}
/* we have just associated, don't start scan too early */
priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
}
/*****************************************************************************
@ -3672,44 +3655,6 @@ static ssize_t show_channels(struct device *d,
static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = dev_get_drvdata(d);
u32 size = sizeof(struct iwl3945_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *)&priv->_3945.statistics;
int rc = 0;
if (!iwl_is_alive(priv))
return -EAGAIN;
mutex_lock(&priv->mutex);
rc = iwl_send_statistics_request(priv, CMD_SYNC, false);
mutex_unlock(&priv->mutex);
if (rc) {
len = sprintf(buf,
"Error sending statistics request: 0x%08X\n", rc);
return len;
}
while (size && (PAGE_SIZE - len)) {
hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
PAGE_SIZE - len, 1);
len = strlen(buf);
if (PAGE_SIZE - len)
buf[len++] = '\n';
ofs += 16;
size -= min(size, 16U);
}
return len;
}
static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
static ssize_t show_antenna(struct device *d,
struct device_attribute *attr, char *buf)
{
@ -3793,7 +3738,6 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
@ -3830,7 +3774,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
&dev_attr_filter_flags.attr,
&dev_attr_measurement.attr,
&dev_attr_retry_rate.attr,
&dev_attr_statistics.attr,
&dev_attr_status.attr,
&dev_attr_temperature.attr,
&dev_attr_tx_power.attr,
@ -4253,7 +4196,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
iwl_free_channel_map(priv);
iwlcore_free_geos(priv);
kfree(priv->scan);
kfree(priv->scan_cmd);
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);

View File

@ -6,3 +6,5 @@ iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
iwmc3200wifi-$(CONFIG_IWM_TRACING) += trace.o
CFLAGS_trace.o := -I$(src)
ccflags-y += -D__CHECK_ENDIAN__

View File

@ -431,7 +431,8 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
return PTR_ERR(ticket_node);
IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n",
ticket->action == IWM_RX_TICKET_RELEASE ?
__le16_to_cpu(ticket->action) ==
IWM_RX_TICKET_RELEASE ?
"RELEASE" : "DROP",
ticket->id);
spin_lock(&iwm->ticket_lock);

View File

@ -76,7 +76,7 @@ TRACE_EVENT(iwm_tx_wifi_cmd,
IWM_ASSIGN;
__entry->opcode = hdr->sw_hdr.cmd.cmd;
__entry->lmac = 0;
__entry->seq = hdr->sw_hdr.cmd.seq_num;
__entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
__entry->resp = GET_VAL8(hdr->sw_hdr.cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ);
__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
__entry->eot = GET_VAL32(hdr->hw_hdr.cmd, UMAC_HDI_OUT_CMD_EOT);
@ -123,7 +123,7 @@ TRACE_EVENT(iwm_tx_packets,
__entry->ra_tid = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_RATID);
__entry->credit_group = GET_VAL32(hdr->hw_hdr.meta_data, UMAC_HDI_OUT_CREDIT_GRP);
__entry->color = GET_VAL32(hdr->sw_hdr.meta_data, UMAC_FW_CMD_TX_STA_COLOR);
__entry->seq = hdr->sw_hdr.cmd.seq_num;
__entry->seq = __le16_to_cpu(hdr->sw_hdr.cmd.seq_num);
__entry->npkt = 1;
__entry->bytes = len;

View File

@ -302,8 +302,8 @@ void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
#define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr)
static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
int pool_id, u8 *buf)
static __le16 iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
int pool_id, u8 *buf)
{
struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf;
struct iwm_udma_wifi_cmd udma_cmd;

View File

@ -315,12 +315,28 @@ out:
return ret;
}
static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition)
{
u8 status;
unsigned long timeout;
int ret = 0;
timeout = jiffies + HZ;
while (1) {
status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
if (ret || (status & condition))
break;
if (time_after(jiffies, timeout))
return -ETIMEDOUT;
mdelay(1);
}
return ret;
}
static int if_sdio_card_to_host(struct if_sdio_card *card)
{
int ret;
u8 status;
u16 size, type, chunk;
unsigned long timeout;
lbs_deb_enter(LBS_DEB_SDIO);
@ -335,19 +351,9 @@ static int if_sdio_card_to_host(struct if_sdio_card *card)
goto out;
}
timeout = jiffies + HZ;
while (1) {
status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
if (ret)
goto out;
if (status & IF_SDIO_IO_RDY)
break;
if (time_after(jiffies, timeout)) {
ret = -ETIMEDOUT;
goto out;
}
mdelay(1);
}
ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY);
if (ret)
goto out;
/*
* The transfer must be in one transaction or the firmware
@ -414,8 +420,6 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
{
struct if_sdio_card *card;
struct if_sdio_packet *packet;
unsigned long timeout;
u8 status;
int ret;
unsigned long flags;
@ -435,25 +439,15 @@ static void if_sdio_host_to_card_worker(struct work_struct *work)
sdio_claim_host(card->func);
timeout = jiffies + HZ;
while (1) {
status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
if (ret)
goto release;
if (status & IF_SDIO_IO_RDY)
break;
if (time_after(jiffies, timeout)) {
ret = -ETIMEDOUT;
goto release;
}
mdelay(1);
ret = if_sdio_wait_status(card, IF_SDIO_IO_RDY);
if (ret == 0) {
ret = sdio_writesb(card->func, card->ioport,
packet->buffer, packet->nb);
}
ret = sdio_writesb(card->func, card->ioport,
packet->buffer, packet->nb);
if (ret)
goto release;
release:
lbs_pr_err("error %d sending packet to firmware\n", ret);
sdio_release_host(card->func);
kfree(packet);
@ -466,10 +460,11 @@ release:
/* Firmware */
/********************************************************************/
#define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY)
static int if_sdio_prog_helper(struct if_sdio_card *card)
{
int ret;
u8 status;
const struct firmware *fw;
unsigned long timeout;
u8 *chunk_buffer;
@ -501,20 +496,14 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
size = fw->size;
while (size) {
timeout = jiffies + HZ;
while (1) {
status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
if (ret)
goto release;
if ((status & IF_SDIO_IO_RDY) &&
(status & IF_SDIO_DL_RDY))
break;
if (time_after(jiffies, timeout)) {
ret = -ETIMEDOUT;
goto release;
}
mdelay(1);
}
ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
if (ret)
goto release;
/* On some platforms (like Davinci) the chip needs more time
* between helper blocks.
*/
mdelay(2);
chunk_size = min(size, (size_t)60);
@ -584,7 +573,6 @@ out:
static int if_sdio_prog_real(struct if_sdio_card *card)
{
int ret;
u8 status;
const struct firmware *fw;
unsigned long timeout;
u8 *chunk_buffer;
@ -616,20 +604,9 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
size = fw->size;
while (size) {
timeout = jiffies + HZ;
while (1) {
status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
if (ret)
goto release;
if ((status & IF_SDIO_IO_RDY) &&
(status & IF_SDIO_DL_RDY))
break;
if (time_after(jiffies, timeout)) {
ret = -ETIMEDOUT;
goto release;
}
mdelay(1);
}
ret = if_sdio_wait_status(card, FW_DL_READY_STATUS);
if (ret)
goto release;
req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret);
if (ret)

View File

@ -830,6 +830,33 @@ static int mac80211_hwsim_conf_tx(
return 0;
}
static int mac80211_hwsim_get_survey(
struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
struct ieee80211_conf *conf = &hw->conf;
printk(KERN_DEBUG "%s:%s (idx=%d)\n",
wiphy_name(hw->wiphy), __func__, idx);
if (idx != 0)
return -ENOENT;
/* Current channel */
survey->channel = conf->channel;
/*
* Magically conjured noise level --- this is only ok for simulated hardware.
*
* A real driver which cannot determine the real channel noise MUST NOT
* report any noise, especially not a magically conjured one :-)
*/
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = -92;
return 0;
}
#ifdef CONFIG_NL80211_TESTMODE
/*
* This section contains example code for using netlink
@ -1013,6 +1040,7 @@ static struct ieee80211_ops mac80211_hwsim_ops =
.sta_notify = mac80211_hwsim_sta_notify,
.set_tim = mac80211_hwsim_set_tim,
.conf_tx = mac80211_hwsim_conf_tx,
.get_survey = mac80211_hwsim_get_survey,
CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
.ampdu_action = mac80211_hwsim_ampdu_action,
.sw_scan_start = mac80211_hwsim_sw_scan,

View File

@ -11,3 +11,6 @@ obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
# Orinoco should be endian clean.
ccflags-y += -D__CHECK_ENDIAN__

View File

@ -88,7 +88,9 @@ int orinoco_wiphy_register(struct wiphy *wiphy)
wiphy->rts_threshold = priv->rts_thresh;
if (!priv->has_mwo)
wiphy->frag_threshold = priv->frag_thresh;
wiphy->frag_threshold = priv->frag_thresh + 1;
wiphy->retry_short = priv->short_retry_limit;
wiphy->retry_long = priv->long_retry_limit;
return wiphy_register(wiphy);
}
@ -196,8 +198,92 @@ static int orinoco_set_channel(struct wiphy *wiphy,
return err;
}
static int orinoco_set_wiphy_params(struct wiphy *wiphy, u32 changed)
{
struct orinoco_private *priv = wiphy_priv(wiphy);
int frag_value = -1;
int rts_value = -1;
int err = 0;
if (changed & WIPHY_PARAM_RETRY_SHORT) {
/* Setting short retry not supported */
err = -EINVAL;
}
if (changed & WIPHY_PARAM_RETRY_LONG) {
/* Setting long retry not supported */
err = -EINVAL;
}
if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
/* Set fragmentation */
if (priv->has_mwo) {
if (wiphy->frag_threshold < 0)
frag_value = 0;
else {
printk(KERN_WARNING "%s: Fixed fragmentation "
"is not supported on this firmware. "
"Using MWO robust instead.\n",
priv->ndev->name);
frag_value = 1;
}
} else {
if (wiphy->frag_threshold < 0)
frag_value = 2346;
else if ((wiphy->frag_threshold < 257) ||
(wiphy->frag_threshold > 2347))
err = -EINVAL;
else
/* cfg80211 value is 257-2347 (odd only)
* orinoco rid has range 256-2346 (even only) */
frag_value = wiphy->frag_threshold & ~0x1;
}
}
if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
/* Set RTS.
*
* Prism documentation suggests default of 2432,
* and a range of 0-3000.
*
* Current implementation uses 2347 as the default and
* the upper limit.
*/
if (wiphy->rts_threshold < 0)
rts_value = 2347;
else if (wiphy->rts_threshold > 2347)
err = -EINVAL;
else
rts_value = wiphy->rts_threshold;
}
if (!err) {
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
if (frag_value >= 0) {
if (priv->has_mwo)
priv->mwo_robust = frag_value;
else
priv->frag_thresh = frag_value;
}
if (rts_value >= 0)
priv->rts_thresh = rts_value;
err = orinoco_commit(priv);
orinoco_unlock(priv, &flags);
}
return err;
}
const struct cfg80211_ops orinoco_cfg_ops = {
.change_virtual_intf = orinoco_change_vif,
.set_channel = orinoco_set_channel,
.scan = orinoco_scan,
.set_wiphy_params = orinoco_set_wiphy_params,
};

View File

@ -374,6 +374,32 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
err = hermes_read_wordrec(hw, USER_BAP,
HERMES_RID_CNFPREAMBLE_SYMBOL,
&priv->preamble);
if (err) {
dev_err(dev, "Failed to read preamble setup\n");
goto out;
}
}
/* Retry settings */
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
&priv->short_retry_limit);
if (err) {
dev_err(dev, "Failed to read short retry limit\n");
goto out;
}
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
&priv->long_retry_limit);
if (err) {
dev_err(dev, "Failed to read long retry limit\n");
goto out;
}
err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
&priv->retry_lifetime);
if (err) {
dev_err(dev, "Failed to read max retry lifetime\n");
goto out;
}
out:

View File

@ -33,18 +33,6 @@ int orinoco_commit(struct orinoco_private *priv);
void orinoco_reset(struct work_struct *work);
/* Information element helpers - find a home for these... */
static inline u8 *orinoco_get_ie(u8 *data, size_t len,
enum ieee80211_eid eid)
{
u8 *p = data;
while ((p + 2) < (data + len)) {
if (p[0] == eid)
return p;
p += p[1] + 2;
}
return NULL;
}
#define WPA_OUI_TYPE "\x00\x50\xF2\x01"
#define WPA_SELECTOR_LEN 4
static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)

View File

@ -131,6 +131,8 @@ struct orinoco_private {
u16 ap_density, rts_thresh;
u16 pm_on, pm_mcast, pm_period, pm_timeout;
u16 preamble;
u16 short_retry_limit, long_retry_limit;
u16 retry_lifetime;
#ifdef WIRELESS_SPY
struct iw_spy_data spy_data; /* iwspy support */
struct iw_public_data wireless_data;

View File

@ -127,7 +127,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
{
struct wiphy *wiphy = priv_to_wiphy(priv);
struct ieee80211_channel *channel;
u8 *ie;
const u8 *ie;
u64 timestamp;
s32 signal;
u16 capability;
@ -136,7 +136,7 @@ void orinoco_add_extscan_result(struct orinoco_private *priv,
int chan, freq;
ie_len = len - sizeof(*bss);
ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS);
ie = cfg80211_find_ie(WLAN_EID_DS_PARAMS, bss->data, ie_len);
chan = ie ? ie[2] : 0;
freq = ieee80211_dsss_chan_to_freq(chan);
channel = ieee80211_get_channel(wiphy, freq);

Some files were not shown because too many files have changed in this diff Show More