forked from Minki/linux
Merge branch 'master' of git://git.infradead.org/users/linville/wireless-next into for-davem
Conflicts: drivers/net/wireless/iwlwifi/iwl-pci.c drivers/net/wireless/wl12xx/main.c
This commit is contained in:
commit
8e00f5fbb4
@ -3426,7 +3426,7 @@ M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://intellinuxwireless.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi.git
|
||||
S: Supported
|
||||
F: drivers/net/wireless/iwlwifi/
|
||||
|
||||
@ -4528,7 +4528,7 @@ L: linux-wireless@vger.kernel.org
|
||||
S: Maintained
|
||||
F: net/nfc/
|
||||
F: include/linux/nfc.h
|
||||
F: include/net/nfc.h
|
||||
F: include/net/nfc/
|
||||
F: drivers/nfc/
|
||||
|
||||
NFS, SUNRPC, AND LOCKD CLIENTS
|
||||
|
@ -18,20 +18,40 @@ static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
|
||||
return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
|
||||
}
|
||||
|
||||
static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
|
||||
u32 offset, u32 mask, u32 set)
|
||||
void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
|
||||
{
|
||||
u32 value;
|
||||
bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
|
||||
bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
|
||||
bcma_cc_write32(cc, BCMA_CC_PLLCTL_DATA, value);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_pll_write);
|
||||
|
||||
bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
|
||||
void bcma_chipco_pll_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
|
||||
u32 set)
|
||||
{
|
||||
bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
|
||||
bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
|
||||
bcma_cc_maskset32(cc, BCMA_CC_PLLCTL_DATA, mask, set);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_pll_maskset);
|
||||
|
||||
void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc,
|
||||
u32 offset, u32 mask, u32 set)
|
||||
{
|
||||
bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset);
|
||||
bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR);
|
||||
value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
|
||||
value &= mask;
|
||||
value |= set;
|
||||
bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value);
|
||||
bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA);
|
||||
bcma_cc_maskset32(cc, BCMA_CC_CHIPCTL_DATA, mask, set);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_chipctl_maskset);
|
||||
|
||||
void bcma_chipco_regctl_maskset(struct bcma_drv_cc *cc, u32 offset, u32 mask,
|
||||
u32 set)
|
||||
{
|
||||
bcma_cc_write32(cc, BCMA_CC_REGCTL_ADDR, offset);
|
||||
bcma_cc_read32(cc, BCMA_CC_REGCTL_ADDR);
|
||||
bcma_cc_maskset32(cc, BCMA_CC_REGCTL_DATA, mask, set);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_chipco_regctl_maskset);
|
||||
|
||||
static void bcma_pmu_pll_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
|
@ -1249,7 +1249,8 @@ static int adm8211_hw_reset(struct ieee80211_hw *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 adm8211_get_tsft(struct ieee80211_hw *dev)
|
||||
static u64 adm8211_get_tsft(struct ieee80211_hw *dev,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct adm8211_priv *priv = dev->priv;
|
||||
u32 tsftl;
|
||||
|
@ -602,7 +602,7 @@ ath5k_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
|
||||
|
||||
static u64
|
||||
ath5k_get_tsf(struct ieee80211_hw *hw)
|
||||
ath5k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath5k_hw *ah = hw->priv;
|
||||
|
||||
@ -611,7 +611,7 @@ ath5k_get_tsf(struct ieee80211_hw *hw)
|
||||
|
||||
|
||||
static void
|
||||
ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
ath5k_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u64 tsf)
|
||||
{
|
||||
struct ath5k_hw *ah = hw->priv;
|
||||
|
||||
@ -620,7 +620,7 @@ ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
|
||||
|
||||
static void
|
||||
ath5k_reset_tsf(struct ieee80211_hw *hw)
|
||||
ath5k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath5k_hw *ah = hw->priv;
|
||||
|
||||
|
@ -273,7 +273,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel)
|
||||
immunityLevel, aniState->noiseFloor,
|
||||
aniState->rssiThrLow, aniState->rssiThrHigh);
|
||||
|
||||
aniState->ofdmNoiseImmunityLevel = immunityLevel;
|
||||
if (aniState->update_ani)
|
||||
aniState->ofdmNoiseImmunityLevel = immunityLevel;
|
||||
|
||||
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
|
||||
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
|
||||
@ -346,7 +347,8 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel)
|
||||
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
|
||||
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
|
||||
|
||||
aniState->cckNoiseImmunityLevel = immunityLevel;
|
||||
if (aniState->update_ani)
|
||||
aniState->cckNoiseImmunityLevel = immunityLevel;
|
||||
|
||||
entry_ofdm = &ofdm_level_table[aniState->ofdmNoiseImmunityLevel];
|
||||
entry_cck = &cck_level_table[aniState->cckNoiseImmunityLevel];
|
||||
@ -593,6 +595,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
aniState->cckNoiseImmunityLevel);
|
||||
|
||||
aniState->update_ani = false;
|
||||
ath9k_hw_set_ofdm_nil(ah, ATH9K_ANI_OFDM_DEF_LEVEL);
|
||||
ath9k_hw_set_cck_nil(ah, ATH9K_ANI_CCK_DEF_LEVEL);
|
||||
}
|
||||
@ -609,6 +612,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning)
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
aniState->cckNoiseImmunityLevel);
|
||||
|
||||
aniState->update_ani = true;
|
||||
ath9k_hw_set_ofdm_nil(ah,
|
||||
aniState->ofdmNoiseImmunityLevel);
|
||||
ath9k_hw_set_cck_nil(ah,
|
||||
@ -892,6 +896,8 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
ani->ofdmWeakSigDetectOff =
|
||||
!ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
|
||||
ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
|
||||
ani->update_ani = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -122,6 +122,7 @@ struct ar5416AniState {
|
||||
u8 firstepLevel;
|
||||
u8 ofdmWeakSigDetectOff;
|
||||
u8 cckWeakSigThreshold;
|
||||
bool update_ani;
|
||||
u32 listenTime;
|
||||
int32_t rssiThrLow;
|
||||
int32_t rssiThrHigh;
|
||||
|
@ -704,8 +704,10 @@ static void ar5008_hw_override_ini(struct ath_hw *ah,
|
||||
REG_WRITE(ah, AR_PCU_MISC_MODE2, val);
|
||||
}
|
||||
|
||||
if (!AR_SREV_5416_20_OR_LATER(ah) ||
|
||||
AR_SREV_9280_20_OR_LATER(ah))
|
||||
REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
|
||||
AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
return;
|
||||
/*
|
||||
* Disable BB clock gating
|
||||
@ -802,7 +804,8 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
|
||||
|
||||
/* Write ADDAC shifts */
|
||||
REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
|
||||
ah->eep_ops->set_addac(ah, chan);
|
||||
if (ah->eep_ops->set_addac)
|
||||
ah->eep_ops->set_addac(ah, chan);
|
||||
|
||||
if (AR_SREV_5416_22_OR_LATER(ah)) {
|
||||
REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites);
|
||||
@ -1007,24 +1010,6 @@ static void ar5008_restore_chainmask(struct ath_hw *ah)
|
||||
}
|
||||
}
|
||||
|
||||
static void ar5008_set_diversity(struct ath_hw *ah, bool value)
|
||||
{
|
||||
u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
|
||||
if (value)
|
||||
v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
else
|
||||
v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
|
||||
}
|
||||
|
||||
static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
if (chan && IS_CHAN_5GHZ(chan))
|
||||
return 0x1450;
|
||||
return 0x1458;
|
||||
}
|
||||
|
||||
static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
@ -1654,7 +1639,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
priv_ops->rfbus_req = ar5008_hw_rfbus_req;
|
||||
priv_ops->rfbus_done = ar5008_hw_rfbus_done;
|
||||
priv_ops->restore_chainmask = ar5008_restore_chainmask;
|
||||
priv_ops->set_diversity = ar5008_set_diversity;
|
||||
priv_ops->do_getnf = ar5008_hw_do_getnf;
|
||||
priv_ops->set_radar_params = ar5008_hw_set_radar_params;
|
||||
|
||||
@ -1664,9 +1648,7 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
} else
|
||||
priv_ops->ani_control = ar5008_hw_ani_control_old;
|
||||
|
||||
if (AR_SREV_9100(ah))
|
||||
priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
|
||||
else if (AR_SREV_9160_10_OR_LATER(ah))
|
||||
if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
|
||||
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
|
||||
else
|
||||
priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
|
||||
|
@ -869,6 +869,7 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
ar9002_hw_pa_cal(ah, true);
|
||||
|
||||
/* Do NF Calibration after DC offset and other calibrations */
|
||||
ath9k_hw_loadnf(ah, chan);
|
||||
ath9k_hw_start_nfcal(ah, true);
|
||||
|
||||
if (ah->caldata)
|
||||
|
@ -1514,7 +1514,7 @@ static const u32 ar9300_2p2_mac_core[][2] = {
|
||||
{0x00008258, 0x00000000},
|
||||
{0x0000825c, 0x40000000},
|
||||
{0x00008260, 0x00080922},
|
||||
{0x00008264, 0x9bc00010},
|
||||
{0x00008264, 0x9d400010},
|
||||
{0x00008268, 0xffffffff},
|
||||
{0x0000826c, 0x0000ffff},
|
||||
{0x00008270, 0x00000000},
|
||||
|
@ -652,8 +652,9 @@ static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
|
||||
outlier_idx = max_idx;
|
||||
else
|
||||
outlier_idx = min_idx;
|
||||
|
||||
mp_coeff[outlier_idx] = mp_avg;
|
||||
}
|
||||
mp_coeff[outlier_idx] = mp_avg;
|
||||
}
|
||||
|
||||
static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
|
||||
@ -884,6 +885,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
if (txiqcal_done)
|
||||
ar9003_hw_tx_iq_cal_post_proc(ah);
|
||||
|
||||
ath9k_hw_loadnf(ah, chan);
|
||||
ath9k_hw_start_nfcal(ah, true);
|
||||
|
||||
/* Initialize list pointers */
|
||||
|
@ -595,6 +595,9 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
|
||||
val = REG_READ(ah, AR_PCU_MISC_MODE2) & (~AR_ADHOC_MCAST_KEYID_ENABLE);
|
||||
REG_WRITE(ah, AR_PCU_MISC_MODE2,
|
||||
val | AR_AGG_WEP_ENABLE_FIX | AR_AGG_WEP_ENABLE);
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_CCK_DETECT,
|
||||
AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
|
||||
}
|
||||
|
||||
static void ar9003_hw_prog_ini(struct ath_hw *ah,
|
||||
@ -795,16 +798,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah)
|
||||
REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
|
||||
}
|
||||
|
||||
static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
|
||||
{
|
||||
u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
|
||||
if (value)
|
||||
v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
else
|
||||
v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
|
||||
REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
|
||||
}
|
||||
|
||||
static bool ar9003_hw_ani_control(struct ath_hw *ah,
|
||||
enum ath9k_ani_cmd cmd, int param)
|
||||
{
|
||||
@ -1287,7 +1280,6 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
|
||||
priv_ops->rfbus_req = ar9003_hw_rfbus_req;
|
||||
priv_ops->rfbus_done = ar9003_hw_rfbus_done;
|
||||
priv_ops->set_diversity = ar9003_hw_set_diversity;
|
||||
priv_ops->ani_control = ar9003_hw_ani_control;
|
||||
priv_ops->do_getnf = ar9003_hw_do_getnf;
|
||||
priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;
|
||||
|
@ -876,6 +876,15 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
TX_SAMP_DBG(rssi) = ts->ts_rssi;
|
||||
TX_SAMP_DBG(tid) = ts->tid;
|
||||
TX_SAMP_DBG(qid) = ts->qid;
|
||||
|
||||
if (ts->ts_flags & ATH9K_TX_BA) {
|
||||
TX_SAMP_DBG(ba_low) = ts->ba_low;
|
||||
TX_SAMP_DBG(ba_high) = ts->ba_high;
|
||||
} else {
|
||||
TX_SAMP_DBG(ba_low) = 0;
|
||||
TX_SAMP_DBG(ba_high) = 0;
|
||||
}
|
||||
|
||||
sc->debug.tsidx = (sc->debug.tsidx + 1) % ATH_DBG_MAX_SAMPLES;
|
||||
spin_unlock(&sc->debug.samp_lock);
|
||||
|
||||
@ -1516,14 +1525,15 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
|
||||
len += snprintf(buf + len, size - len, "Tx status Dump :\n");
|
||||
len += snprintf(buf + len, size - len,
|
||||
"Sample rssi:- ctl0 ctl1 ctl2 ext0 ext1 ext2 comb "
|
||||
"isok rts_fail data_fail rate tid qid tx_before(ms)\n");
|
||||
"isok rts_fail data_fail rate tid qid "
|
||||
"ba_low ba_high tx_before(ms)\n");
|
||||
for (sampidx = 0; sampidx < ATH_DBG_MAX_SAMPLES; sampidx++) {
|
||||
for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
|
||||
if (!ATH_SAMP_DBG(ts[i].jiffies))
|
||||
continue;
|
||||
len += snprintf(buf + len, size - len, "%4d \t"
|
||||
"%8d %4d %4d %4d %4d %4d %4d %4d %4d "
|
||||
"%4d %4d %2d %2d %d\n",
|
||||
len += snprintf(buf + len, size - len, "%-14d"
|
||||
"%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-8d "
|
||||
"%-9d %-4d %-3d %-3d %08x %08x %-11d\n",
|
||||
sampidx,
|
||||
ATH_SAMP_DBG(ts[i].rssi_ctl0),
|
||||
ATH_SAMP_DBG(ts[i].rssi_ctl1),
|
||||
@ -1538,6 +1548,8 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
|
||||
ATH_SAMP_DBG(ts[i].rateindex),
|
||||
ATH_SAMP_DBG(ts[i].tid),
|
||||
ATH_SAMP_DBG(ts[i].qid),
|
||||
ATH_SAMP_DBG(ts[i].ba_low),
|
||||
ATH_SAMP_DBG(ts[i].ba_high),
|
||||
jiffies_to_msecs(jiffies -
|
||||
ATH_SAMP_DBG(ts[i].jiffies)));
|
||||
}
|
||||
@ -1550,8 +1562,8 @@ static int open_file_bb_mac_samps(struct inode *inode, struct file *file)
|
||||
for (i = 0; i < ATH_DBG_MAX_SAMPLES; i++) {
|
||||
if (!ATH_SAMP_DBG(rs[i].jiffies))
|
||||
continue;
|
||||
len += snprintf(buf + len, size - len, "%4d \t"
|
||||
"%8d %4d %4d %4d %4d %4d %4d %s %4d %02x %d\n",
|
||||
len += snprintf(buf + len, size - len, "%-14d"
|
||||
"%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-9s %-2d %02x %-13d\n",
|
||||
sampidx,
|
||||
ATH_SAMP_DBG(rs[i].rssi_ctl0),
|
||||
ATH_SAMP_DBG(rs[i].rssi_ctl1),
|
||||
|
@ -196,6 +196,8 @@ struct ath_dbg_bb_mac_samp {
|
||||
u8 rateindex;
|
||||
u8 qid;
|
||||
u8 tid;
|
||||
u32 ba_low;
|
||||
u32 ba_high;
|
||||
} ts[ATH_DBG_MAX_SAMPLES];
|
||||
struct {
|
||||
u64 jiffies;
|
||||
|
@ -456,12 +456,7 @@ void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
|
||||
pPdGainBoundaries[i] =
|
||||
min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
|
||||
|
||||
if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
|
||||
minDelta = pPdGainBoundaries[0] - 23;
|
||||
pPdGainBoundaries[0] = 23;
|
||||
} else {
|
||||
minDelta = 0;
|
||||
}
|
||||
minDelta = 0;
|
||||
|
||||
if (i == 0) {
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
|
@ -405,12 +405,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
|
||||
|
||||
for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
|
||||
if (AR_SREV_5416_20_OR_LATER(ah) &&
|
||||
(ah->rxchainmask == 5 || ah->txchainmask == 5) &&
|
||||
(i != 0)) {
|
||||
regChainOffset = (i == 1) ? 0x2000 : 0x1000;
|
||||
} else
|
||||
regChainOffset = i * 0x1000;
|
||||
regChainOffset = i * 0x1000;
|
||||
|
||||
if (pEepData->baseEepHeader.txMask & (1 << i)) {
|
||||
pRawDataset = pEepData->calPierData2G[i];
|
||||
@ -423,19 +418,17 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
|
||||
REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
|
||||
SM(pdGainOverlap_t2,
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
|
||||
| SM(gainBoundaries[0],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
|
||||
| SM(gainBoundaries[1],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
|
||||
| SM(gainBoundaries[2],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
|
||||
| SM(gainBoundaries[3],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
|
||||
}
|
||||
REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
|
||||
SM(pdGainOverlap_t2,
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
|
||||
| SM(gainBoundaries[0],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
|
||||
| SM(gainBoundaries[1],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
|
||||
| SM(gainBoundaries[2],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
|
||||
| SM(gainBoundaries[3],
|
||||
AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
|
||||
|
||||
regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
|
||||
for (j = 0; j < 32; j++) {
|
||||
@ -715,10 +708,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
||||
if (test)
|
||||
return;
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
|
||||
}
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
@ -788,28 +779,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct modal_eep_4k_header *pModal;
|
||||
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
|
||||
u8 biaslevel;
|
||||
|
||||
if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
|
||||
return;
|
||||
|
||||
if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
|
||||
return;
|
||||
|
||||
pModal = &eep->modalHeader;
|
||||
|
||||
if (pModal->xpaBiasLvl != 0xff) {
|
||||
biaslevel = pModal->xpaBiasLvl;
|
||||
INI_RA(&ah->iniAddac, 7, 1) =
|
||||
(INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
|
||||
struct modal_eep_4k_header *pModal,
|
||||
struct ar5416_eeprom_4k *eep,
|
||||
@ -877,6 +846,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
|
||||
u8 txRxAttenLocal;
|
||||
u8 ob[5], db1[5], db2[5];
|
||||
u8 ant_div_control1, ant_div_control2;
|
||||
u8 bb_desired_scale;
|
||||
u32 regVal;
|
||||
|
||||
pModal = &eep->modalHeader;
|
||||
@ -1096,30 +1066,29 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
|
||||
AR_PHY_SETTLING_SWITCH,
|
||||
pModal->swSettleHt40);
|
||||
}
|
||||
if (AR_SREV_9271(ah) || AR_SREV_9285(ah)) {
|
||||
u8 bb_desired_scale = (pModal->bb_scale_smrt_antenna &
|
||||
EEP_4K_BB_DESIRED_SCALE_MASK);
|
||||
if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
|
||||
u32 pwrctrl, mask, clr;
|
||||
|
||||
mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
|
||||
pwrctrl = mask * bb_desired_scale;
|
||||
clr = mask * 0x1f;
|
||||
REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
|
||||
REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
|
||||
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
|
||||
bb_desired_scale = (pModal->bb_scale_smrt_antenna &
|
||||
EEP_4K_BB_DESIRED_SCALE_MASK);
|
||||
if ((pBase->txGainType == 0) && (bb_desired_scale != 0)) {
|
||||
u32 pwrctrl, mask, clr;
|
||||
|
||||
mask = BIT(0)|BIT(5)|BIT(15);
|
||||
pwrctrl = mask * bb_desired_scale;
|
||||
clr = mask * 0x1f;
|
||||
REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
|
||||
mask = BIT(0)|BIT(5)|BIT(10)|BIT(15)|BIT(20)|BIT(25);
|
||||
pwrctrl = mask * bb_desired_scale;
|
||||
clr = mask * 0x1f;
|
||||
REG_RMW(ah, AR_PHY_TX_PWRCTRL8, pwrctrl, clr);
|
||||
REG_RMW(ah, AR_PHY_TX_PWRCTRL10, pwrctrl, clr);
|
||||
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL12, pwrctrl, clr);
|
||||
|
||||
mask = BIT(0)|BIT(5);
|
||||
pwrctrl = mask * bb_desired_scale;
|
||||
clr = mask * 0x1f;
|
||||
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
|
||||
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
|
||||
}
|
||||
mask = BIT(0)|BIT(5)|BIT(15);
|
||||
pwrctrl = mask * bb_desired_scale;
|
||||
clr = mask * 0x1f;
|
||||
REG_RMW(ah, AR_PHY_TX_PWRCTRL9, pwrctrl, clr);
|
||||
|
||||
mask = BIT(0)|BIT(5);
|
||||
pwrctrl = mask * bb_desired_scale;
|
||||
clr = mask * 0x1f;
|
||||
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL11, pwrctrl, clr);
|
||||
REG_RMW(ah, AR_PHY_CH0_TX_PWRCTRL13, pwrctrl, clr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1161,7 +1130,6 @@ const struct eeprom_ops eep_4k_ops = {
|
||||
.get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
|
||||
.get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
|
||||
.set_board_values = ath9k_hw_4k_set_board_values,
|
||||
.set_addac = ath9k_hw_4k_set_addac,
|
||||
.set_txpower = ath9k_hw_4k_set_txpower,
|
||||
.get_spur_channel = ath9k_hw_4k_get_spur_channel
|
||||
};
|
||||
|
@ -851,10 +851,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
|
||||
if (test)
|
||||
return;
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
|
||||
}
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
@ -944,11 +942,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
}
|
||||
|
||||
static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
}
|
||||
|
||||
static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
@ -1100,7 +1093,6 @@ const struct eeprom_ops eep_ar9287_ops = {
|
||||
.get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver,
|
||||
.get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
|
||||
.set_board_values = ath9k_hw_ar9287_set_board_values,
|
||||
.set_addac = ath9k_hw_ar9287_set_addac,
|
||||
.set_txpower = ath9k_hw_ar9287_set_txpower,
|
||||
.get_spur_channel = ath9k_hw_ar9287_get_spur_channel
|
||||
};
|
||||
|
@ -547,8 +547,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
||||
break;
|
||||
}
|
||||
|
||||
if (AR_SREV_5416_20_OR_LATER(ah) &&
|
||||
(ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
|
||||
if ((ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
|
||||
regChainOffset = (i == 1) ? 0x2000 : 0x1000;
|
||||
else
|
||||
regChainOffset = i * 0x1000;
|
||||
@ -565,9 +564,8 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
|
||||
SM(pModal->iqCalQCh[i],
|
||||
AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
|
||||
|
||||
if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
|
||||
ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
|
||||
regChainOffset, i);
|
||||
ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
|
||||
regChainOffset, i);
|
||||
}
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
@ -893,8 +891,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
xpdGainValues[2]);
|
||||
|
||||
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
|
||||
if (AR_SREV_5416_20_OR_LATER(ah) &&
|
||||
(ah->rxchainmask == 5 || ah->txchainmask == 5) &&
|
||||
if ((ah->rxchainmask == 5 || ah->txchainmask == 5) &&
|
||||
(i != 0)) {
|
||||
regChainOffset = (i == 1) ? 0x2000 : 0x1000;
|
||||
} else
|
||||
@ -935,27 +932,24 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
|
||||
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
|
||||
if (OLC_FOR_AR9280_20_LATER) {
|
||||
REG_WRITE(ah,
|
||||
AR_PHY_TPCRG5 + regChainOffset,
|
||||
SM(0x6,
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
|
||||
SM_PD_GAIN(1) | SM_PD_GAIN(2) |
|
||||
SM_PD_GAIN(3) | SM_PD_GAIN(4));
|
||||
} else {
|
||||
REG_WRITE(ah,
|
||||
AR_PHY_TPCRG5 + regChainOffset,
|
||||
SM(pdGainOverlap_t2,
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
|
||||
SM_PDGAIN_B(0, 1) |
|
||||
SM_PDGAIN_B(1, 2) |
|
||||
SM_PDGAIN_B(2, 3) |
|
||||
SM_PDGAIN_B(3, 4));
|
||||
}
|
||||
if (OLC_FOR_AR9280_20_LATER) {
|
||||
REG_WRITE(ah,
|
||||
AR_PHY_TPCRG5 + regChainOffset,
|
||||
SM(0x6,
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
|
||||
SM_PD_GAIN(1) | SM_PD_GAIN(2) |
|
||||
SM_PD_GAIN(3) | SM_PD_GAIN(4));
|
||||
} else {
|
||||
REG_WRITE(ah,
|
||||
AR_PHY_TPCRG5 + regChainOffset,
|
||||
SM(pdGainOverlap_t2,
|
||||
AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
|
||||
SM_PDGAIN_B(0, 1) |
|
||||
SM_PDGAIN_B(1, 2) |
|
||||
SM_PDGAIN_B(2, 3) |
|
||||
SM_PDGAIN_B(3, 4));
|
||||
}
|
||||
|
||||
|
||||
ath9k_adjust_pdadc_values(ah, pwr_table_offset,
|
||||
diff, pdadcValues);
|
||||
|
||||
|
@ -1563,7 +1563,8 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
u64 tsf;
|
||||
@ -1577,7 +1578,8 @@ static u64 ath9k_htc_get_tsf(struct ieee80211_hw *hw)
|
||||
return tsf;
|
||||
}
|
||||
|
||||
static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
static void ath9k_htc_set_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u64 tsf)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
@ -1588,7 +1590,8 @@ static void ath9k_htc_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
|
||||
static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
|
@ -181,11 +181,6 @@ static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
|
||||
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)
|
||||
{
|
||||
|
@ -584,7 +584,6 @@ struct ath_hw_private_ops {
|
||||
bool (*rfbus_req)(struct ath_hw *ah);
|
||||
void (*rfbus_done)(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,
|
||||
|
@ -506,7 +506,6 @@ static void ath9k_init_misc(struct ath_softc *sc)
|
||||
sc->sc_flags |= SC_OP_RXAGGR;
|
||||
}
|
||||
|
||||
ath9k_hw_set_diversity(sc->sc_ah, true);
|
||||
sc->rx.defant = ath9k_hw_getdefantenna(sc->sc_ah);
|
||||
|
||||
memcpy(common->bssidmask, ath_bcast_mac, ETH_ALEN);
|
||||
|
@ -584,7 +584,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
|
||||
else
|
||||
rs->rs_keyix = ATH9K_RXKEYIX_INVALID;
|
||||
|
||||
rs->rs_rate = RXSTATUS_RATE(ah, (&ads));
|
||||
rs->rs_rate = MS(ads.ds_rxstatus0, AR_RxRate);
|
||||
rs->rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
|
||||
|
||||
rs->rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
|
||||
|
@ -17,10 +17,6 @@
|
||||
#ifndef MAC_H
|
||||
#define MAC_H
|
||||
|
||||
#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \
|
||||
MS(ads->ds_rxstatus0, AR_RxRate) : \
|
||||
(ads->ds_rxstatus3 >> 2) & 0xFF)
|
||||
|
||||
#define set11nTries(_series, _index) \
|
||||
(SM((_series)[_index].Tries, AR_XmitDataTries##_index))
|
||||
|
||||
|
@ -133,7 +133,7 @@ void ath9k_ps_restore(struct ath_softc *sc)
|
||||
ath_hw_cycle_counters_update(common);
|
||||
spin_unlock(&common->cc_lock);
|
||||
|
||||
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
|
||||
ath9k_hw_setpower(sc->sc_ah, mode);
|
||||
|
||||
unlock:
|
||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||
@ -2021,6 +2021,7 @@ static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
|
||||
/* Stop ANI */
|
||||
sc->sc_flags &= ~SC_OP_ANI_RUN;
|
||||
del_timer_sync(&common->ani.timer);
|
||||
memset(&sc->caldata, 0, sizeof(sc->caldata));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2142,7 +2143,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
u64 tsf;
|
||||
@ -2156,7 +2157,9 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
|
||||
return tsf;
|
||||
}
|
||||
|
||||
static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
static void ath9k_set_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u64 tsf)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
@ -2167,7 +2170,7 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
mutex_unlock(&sc->mutex);
|
||||
}
|
||||
|
||||
static void ath9k_reset_tsf(struct ieee80211_hw *hw)
|
||||
static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
|
@ -205,14 +205,22 @@ static void ath_rx_remove_buffer(struct ath_softc *sc,
|
||||
|
||||
static void ath_rx_edma_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
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)
|
||||
if (bf->bf_mpdu) {
|
||||
dma_unmap_single(sc->dev, bf->bf_buf_addr,
|
||||
common->rx_bufsize,
|
||||
DMA_BIDIRECTIONAL);
|
||||
dev_kfree_skb_any(bf->bf_mpdu);
|
||||
bf->bf_buf_addr = 0;
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sc->rx.rxbuf);
|
||||
|
@ -803,10 +803,6 @@
|
||||
#define AR_SREV_5416(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
|
||||
((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE))
|
||||
#define AR_SREV_5416_20_OR_LATER(_ah) \
|
||||
(((AR_SREV_5416(_ah)) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \
|
||||
((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100))
|
||||
#define AR_SREV_5416_22_OR_LATER(_ah) \
|
||||
(((AR_SREV_5416(_ah)) && \
|
||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \
|
||||
|
@ -262,6 +262,7 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath_frame_info *fi = get_frame_info(skb);
|
||||
struct ath_buf *bf = fi->bf;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
TX_STAT_INC(txq->axq_qnum, a_retries);
|
||||
@ -270,6 +271,8 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY);
|
||||
dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
|
||||
sizeof(*hdr), DMA_TO_DEVICE);
|
||||
}
|
||||
|
||||
static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
|
||||
@ -1017,8 +1020,6 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
|
||||
while (bf) {
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
struct ath_frame_info *fi = get_frame_info(skb);
|
||||
struct ieee80211_hdr *hdr;
|
||||
int padpos, padsize;
|
||||
|
||||
info.type = get_hw_packet_type(skb);
|
||||
if (bf->bf_next)
|
||||
@ -1026,20 +1027,8 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
|
||||
else
|
||||
info.link = 0;
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
|
||||
info.buf_addr[0] = bf->bf_buf_addr;
|
||||
info.buf_len[0] = padpos + padsize;
|
||||
info.buf_addr[1] = info.buf_addr[0] + padpos;
|
||||
info.buf_len[1] = skb->len - padpos;
|
||||
} else {
|
||||
info.buf_addr[0] = bf->bf_buf_addr;
|
||||
info.buf_len[0] = skb->len;
|
||||
}
|
||||
|
||||
info.buf_addr[0] = bf->bf_buf_addr;
|
||||
info.buf_len[0] = skb->len;
|
||||
info.pkt_len = fi->framelen;
|
||||
info.keyix = fi->keyix;
|
||||
info.keytype = fi->keytype;
|
||||
@ -1892,17 +1881,16 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
|
||||
}
|
||||
|
||||
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
|
||||
/* Add the padding after the header if this is not already done */
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len > padpos) {
|
||||
if (skb_headroom(skb) < padsize)
|
||||
return -ENOMEM;
|
||||
/* Add the padding after the header if this is not already done */
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len > padpos) {
|
||||
if (skb_headroom(skb) < padsize)
|
||||
return -ENOMEM;
|
||||
|
||||
skb_push(skb, padsize);
|
||||
memmove(skb->data, skb->data + padsize, padpos);
|
||||
}
|
||||
skb_push(skb, padsize);
|
||||
memmove(skb->data, skb->data + padsize, padpos);
|
||||
hdr = (struct ieee80211_hdr *) skb->data;
|
||||
}
|
||||
|
||||
if ((vif && vif->type != NL80211_IFTYPE_AP &&
|
||||
@ -1952,17 +1940,15 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
/* Frame was ACKed */
|
||||
tx_info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len>padpos+padsize) {
|
||||
/*
|
||||
* Remove MAC header padding before giving the frame back to
|
||||
* mac80211.
|
||||
*/
|
||||
memmove(skb->data + padsize, skb->data, padpos);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
padpos = ath9k_cmn_padpos(hdr->frame_control);
|
||||
padsize = padpos & 3;
|
||||
if (padsize && skb->len>padpos+padsize) {
|
||||
/*
|
||||
* Remove MAC header padding before giving the frame back to
|
||||
* mac80211.
|
||||
*/
|
||||
memmove(skb->data + padsize, skb->data, padpos);
|
||||
skb_pull(skb, padsize);
|
||||
}
|
||||
|
||||
if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {
|
||||
|
@ -1078,7 +1078,8 @@ out:
|
||||
mutex_unlock(&ar->mutex);
|
||||
}
|
||||
|
||||
static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct carl9170_tsf_rsp tsf;
|
||||
|
@ -107,6 +107,40 @@
|
||||
#define B43_MMIO_RADIO_HWENABLED_LO 0x49A
|
||||
#define B43_MMIO_GPIO_CONTROL 0x49C
|
||||
#define B43_MMIO_GPIO_MASK 0x49E
|
||||
#define B43_MMIO_TXE0_CTL 0x500
|
||||
#define B43_MMIO_TXE0_AUX 0x502
|
||||
#define B43_MMIO_TXE0_TS_LOC 0x504
|
||||
#define B43_MMIO_TXE0_TIME_OUT 0x506
|
||||
#define B43_MMIO_TXE0_WM_0 0x508
|
||||
#define B43_MMIO_TXE0_WM_1 0x50A
|
||||
#define B43_MMIO_TXE0_PHYCTL 0x50C
|
||||
#define B43_MMIO_TXE0_STATUS 0x50E
|
||||
#define B43_MMIO_TXE0_MMPLCP0 0x510
|
||||
#define B43_MMIO_TXE0_MMPLCP1 0x512
|
||||
#define B43_MMIO_TXE0_PHYCTL1 0x514
|
||||
#define B43_MMIO_XMTFIFODEF 0x520
|
||||
#define B43_MMIO_XMTFIFO_FRAME_CNT 0x522 /* core rev>= 16 only */
|
||||
#define B43_MMIO_XMTFIFO_BYTE_CNT 0x524 /* core rev>= 16 only */
|
||||
#define B43_MMIO_XMTFIFO_HEAD 0x526 /* core rev>= 16 only */
|
||||
#define B43_MMIO_XMTFIFO_RD_PTR 0x528 /* core rev>= 16 only */
|
||||
#define B43_MMIO_XMTFIFO_WR_PTR 0x52A /* core rev>= 16 only */
|
||||
#define B43_MMIO_XMTFIFODEF1 0x52C /* core rev>= 16 only */
|
||||
#define B43_MMIO_XMTFIFOCMD 0x540
|
||||
#define B43_MMIO_XMTFIFOFLUSH 0x542
|
||||
#define B43_MMIO_XMTFIFOTHRESH 0x544
|
||||
#define B43_MMIO_XMTFIFORDY 0x546
|
||||
#define B43_MMIO_XMTFIFOPRIRDY 0x548
|
||||
#define B43_MMIO_XMTFIFORQPRI 0x54A
|
||||
#define B43_MMIO_XMTTPLATETXPTR 0x54C
|
||||
#define B43_MMIO_XMTTPLATEPTR 0x550
|
||||
#define B43_MMIO_SMPL_CLCT_STRPTR 0x552 /* core rev>= 22 only */
|
||||
#define B43_MMIO_SMPL_CLCT_STPPTR 0x554 /* core rev>= 22 only */
|
||||
#define B43_MMIO_SMPL_CLCT_CURPTR 0x556 /* core rev>= 22 only */
|
||||
#define B43_MMIO_XMTTPLATEDATALO 0x560
|
||||
#define B43_MMIO_XMTTPLATEDATAHI 0x562
|
||||
#define B43_MMIO_XMTSEL 0x568
|
||||
#define B43_MMIO_XMTTXCNT 0x56A
|
||||
#define B43_MMIO_XMTTXSHMADDR 0x56C
|
||||
#define B43_MMIO_TSF_CFP_START_LOW 0x604
|
||||
#define B43_MMIO_TSF_CFP_START_HIGH 0x606
|
||||
#define B43_MMIO_TSF_CFP_PRETBTT 0x612
|
||||
@ -118,12 +152,16 @@
|
||||
#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */
|
||||
#define B43_MMIO_RNG 0x65A
|
||||
#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */
|
||||
#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
|
||||
#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */
|
||||
#define B43_MMIO_IFSSTAT 0x690
|
||||
#define B43_MMIO_IFSMEDBUSYCTL 0x692
|
||||
#define B43_MMIO_IFTXDUR 0x694
|
||||
#define B43_MMIO_IFSCTL_USE_EDCF 0x0004
|
||||
#define B43_MMIO_POWERUP_DELAY 0x6A8
|
||||
#define B43_MMIO_BTCOEX_CTL 0x6B4 /* Bluetooth Coexistence Control */
|
||||
#define B43_MMIO_BTCOEX_STAT 0x6B6 /* Bluetooth Coexistence Status */
|
||||
#define B43_MMIO_BTCOEX_TXCTL 0x6B8 /* Bluetooth Coexistence Transmit Control */
|
||||
#define B43_MMIO_WEPCTL 0x7C0
|
||||
|
||||
/* SPROM boardflags_lo values */
|
||||
#define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */
|
||||
|
@ -729,52 +729,59 @@ void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on)
|
||||
for (i = 0; i < 5; i++)
|
||||
b43_ram_write(dev, i * 4, buffer[i]);
|
||||
|
||||
b43_write16(dev, 0x0568, 0x0000);
|
||||
b43_write16(dev, B43_MMIO_XMTSEL, 0x0000);
|
||||
|
||||
if (dev->dev->core_rev < 11)
|
||||
b43_write16(dev, 0x07C0, 0x0000);
|
||||
b43_write16(dev, B43_MMIO_WEPCTL, 0x0000);
|
||||
else
|
||||
b43_write16(dev, 0x07C0, 0x0100);
|
||||
b43_write16(dev, B43_MMIO_WEPCTL, 0x0100);
|
||||
|
||||
value = (ofdm ? 0x41 : 0x40);
|
||||
b43_write16(dev, 0x050C, value);
|
||||
if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP))
|
||||
b43_write16(dev, 0x0514, 0x1A02);
|
||||
b43_write16(dev, 0x0508, 0x0000);
|
||||
b43_write16(dev, 0x050A, 0x0000);
|
||||
b43_write16(dev, 0x054C, 0x0000);
|
||||
b43_write16(dev, 0x056A, 0x0014);
|
||||
b43_write16(dev, 0x0568, 0x0826);
|
||||
b43_write16(dev, 0x0500, 0x0000);
|
||||
if (!pa_on && (phy->type == B43_PHYTYPE_N)) {
|
||||
//SPEC TODO
|
||||
}
|
||||
b43_write16(dev, B43_MMIO_TXE0_PHYCTL, value);
|
||||
if (phy->type == B43_PHYTYPE_N || phy->type == B43_PHYTYPE_LP ||
|
||||
phy->type == B43_PHYTYPE_LCN)
|
||||
b43_write16(dev, B43_MMIO_TXE0_PHYCTL1, 0x1A02);
|
||||
|
||||
b43_write16(dev, B43_MMIO_TXE0_WM_0, 0x0000);
|
||||
b43_write16(dev, B43_MMIO_TXE0_WM_1, 0x0000);
|
||||
|
||||
b43_write16(dev, B43_MMIO_XMTTPLATETXPTR, 0x0000);
|
||||
b43_write16(dev, B43_MMIO_XMTTXCNT, 0x0014);
|
||||
b43_write16(dev, B43_MMIO_XMTSEL, 0x0826);
|
||||
b43_write16(dev, B43_MMIO_TXE0_CTL, 0x0000);
|
||||
|
||||
if (!pa_on && phy->type == B43_PHYTYPE_N)
|
||||
; /*b43_nphy_pa_override(dev, false) */
|
||||
|
||||
switch (phy->type) {
|
||||
case B43_PHYTYPE_N:
|
||||
b43_write16(dev, 0x0502, 0x00D0);
|
||||
case B43_PHYTYPE_LCN:
|
||||
b43_write16(dev, B43_MMIO_TXE0_AUX, 0x00D0);
|
||||
break;
|
||||
case B43_PHYTYPE_LP:
|
||||
b43_write16(dev, 0x0502, 0x0050);
|
||||
b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0050);
|
||||
break;
|
||||
default:
|
||||
b43_write16(dev, 0x0502, 0x0030);
|
||||
b43_write16(dev, B43_MMIO_TXE0_AUX, 0x0030);
|
||||
}
|
||||
b43_read16(dev, B43_MMIO_TXE0_AUX);
|
||||
|
||||
if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5)
|
||||
b43_radio_write16(dev, 0x0051, 0x0017);
|
||||
for (i = 0x00; i < max_loop; i++) {
|
||||
value = b43_read16(dev, 0x050E);
|
||||
value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
|
||||
if (value & 0x0080)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
for (i = 0x00; i < 0x0A; i++) {
|
||||
value = b43_read16(dev, 0x050E);
|
||||
value = b43_read16(dev, B43_MMIO_TXE0_STATUS);
|
||||
if (value & 0x0400)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
for (i = 0x00; i < 0x19; i++) {
|
||||
value = b43_read16(dev, 0x0690);
|
||||
value = b43_read16(dev, B43_MMIO_IFSSTAT);
|
||||
if (!(value & 0x0100))
|
||||
break;
|
||||
udelay(10);
|
||||
@ -3599,7 +3606,7 @@ static int b43_op_get_stats(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 b43_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev;
|
||||
@ -3618,7 +3625,8 @@ static u64 b43_op_get_tsf(struct ieee80211_hw *hw)
|
||||
return tsf;
|
||||
}
|
||||
|
||||
static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
static void b43_op_set_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u64 tsf)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev;
|
||||
|
@ -20,6 +20,14 @@
|
||||
the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
|
||||
This file incorporates work covered by the following copyright and
|
||||
permission notice:
|
||||
|
||||
Copyright (c) 2010 Broadcom Corporation
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
@ -29,6 +37,56 @@
|
||||
#include "tables_phy_lcn.h"
|
||||
#include "main.h"
|
||||
|
||||
struct lcn_tx_gains {
|
||||
u16 gm_gain;
|
||||
u16 pga_gain;
|
||||
u16 pad_gain;
|
||||
u16 dac_gain;
|
||||
};
|
||||
|
||||
struct lcn_tx_iir_filter {
|
||||
u8 type;
|
||||
u16 values[16];
|
||||
};
|
||||
|
||||
enum lcn_sense_type {
|
||||
B43_SENSE_TEMP,
|
||||
B43_SENSE_VBAT,
|
||||
};
|
||||
|
||||
/* In theory it's PHY common function, move if needed */
|
||||
/* brcms_b_switch_macfreq */
|
||||
static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
|
||||
{
|
||||
if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
|
||||
switch (spurmode) {
|
||||
case 2: /* 126 Mhz */
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
|
||||
break;
|
||||
case 1: /* 123 Mhz */
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
|
||||
break;
|
||||
default: /* 120 Mhz */
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
|
||||
break;
|
||||
}
|
||||
} else if (dev->phy.type == B43_PHYTYPE_LCN) {
|
||||
switch (spurmode) {
|
||||
case 1: /* 82 Mhz */
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
|
||||
break;
|
||||
default: /* 80 Mhz */
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
|
||||
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Radio 2064.
|
||||
**************************************************/
|
||||
@ -152,6 +210,29 @@ static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
|
||||
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_get_pa_gain */
|
||||
static u16 b43_phy_lcn_get_pa_gain(struct b43_wldev *dev)
|
||||
{
|
||||
return (b43_phy_read(dev, 0x4fb) & 0x7f00) >> 8;
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_set_dac_gain */
|
||||
static void b43_phy_lcn_set_dac_gain(struct b43_wldev *dev, u16 dac_gain)
|
||||
{
|
||||
u16 dac_ctrl;
|
||||
|
||||
dac_ctrl = b43_phy_read(dev, 0x439);
|
||||
dac_ctrl = dac_ctrl & 0xc7f;
|
||||
dac_ctrl = dac_ctrl | (dac_gain << 7);
|
||||
b43_phy_maskset(dev, 0x439, ~0xfff, dac_ctrl);
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_set_bbmult */
|
||||
static void b43_phy_lcn_set_bbmult(struct b43_wldev *dev, u8 m0)
|
||||
{
|
||||
b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x57), m0 << 8);
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_clear_tx_power_offsets */
|
||||
static void b43_phy_lcn_clear_tx_power_offsets(struct b43_wldev *dev)
|
||||
{
|
||||
@ -231,18 +312,40 @@ static void b43_phy_lcn_bu_tweaks(struct b43_wldev *dev)
|
||||
|
||||
b43_phy_write(dev, 0x7d6, 0x0902);
|
||||
|
||||
/* TODO: more ops */
|
||||
b43_phy_maskset(dev, 0x429, ~0xf, 0x9);
|
||||
b43_phy_maskset(dev, 0x429, ~(0x3f << 4), 0xe << 4);
|
||||
|
||||
if (dev->phy.rev == 1) {
|
||||
/* TODO: more ops */
|
||||
b43_phy_maskset(dev, 0x423, ~0xff, 0x46);
|
||||
b43_phy_maskset(dev, 0x411, ~0xff, 1);
|
||||
b43_phy_set(dev, 0x434, 0xff); /* FIXME: update to wl */
|
||||
|
||||
/* TODO: wl operates on PHY 0x416, brcmsmac is outdated here */
|
||||
|
||||
b43_phy_maskset(dev, 0x656, ~0xf, 2);
|
||||
b43_phy_set(dev, 0x44d, 4);
|
||||
|
||||
b43_radio_set(dev, 0x0f7, 0x4);
|
||||
b43_radio_mask(dev, 0x0f1, ~0x3);
|
||||
b43_radio_maskset(dev, 0x0f2, ~0xf8, 0x90);
|
||||
b43_radio_maskset(dev, 0x0f3, ~0x3, 0x2);
|
||||
b43_radio_maskset(dev, 0x0f3, ~0xf0, 0xa0);
|
||||
|
||||
b43_radio_set(dev, 0x11f, 0x2);
|
||||
|
||||
b43_phy_lcn_clear_tx_power_offsets(dev);
|
||||
|
||||
/* TODO: something more? */
|
||||
}
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_vbat_temp_sense_setup */
|
||||
static void b43_phy_lcn_sense_setup(struct b43_wldev *dev)
|
||||
static void b43_phy_lcn_sense_setup(struct b43_wldev *dev,
|
||||
enum lcn_sense_type sense_type)
|
||||
{
|
||||
u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
|
||||
u16 auxpga_vmid;
|
||||
u8 tx_pwr_idx;
|
||||
u8 i;
|
||||
|
||||
u16 save_radio_regs[6][2] = {
|
||||
@ -257,35 +360,312 @@ static void b43_phy_lcn_sense_setup(struct b43_wldev *dev)
|
||||
};
|
||||
u16 save_radio_4a4;
|
||||
|
||||
msleep(1);
|
||||
|
||||
/* Save */
|
||||
for (i = 0; i < 6; i++)
|
||||
save_radio_regs[i][1] = b43_radio_read(dev,
|
||||
save_radio_regs[i][0]);
|
||||
for (i = 0; i < 14; i++)
|
||||
save_phy_regs[i][1] = b43_phy_read(dev, save_phy_regs[i][0]);
|
||||
b43_mac_suspend(dev);
|
||||
save_radio_4a4 = b43_radio_read(dev, 0x4a4);
|
||||
/* wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF); */
|
||||
tx_pwr_idx = dev->phy.lcn->tx_pwr_curr_idx;
|
||||
|
||||
/* TODO: config sth */
|
||||
/* Setup */
|
||||
/* TODO: wlc_lcnphy_set_tx_pwr_by_index(pi, 127); */
|
||||
b43_radio_set(dev, 0x007, 0x1);
|
||||
b43_radio_set(dev, 0x0ff, 0x10);
|
||||
b43_radio_set(dev, 0x11f, 0x4);
|
||||
|
||||
b43_phy_mask(dev, 0x503, ~0x1);
|
||||
b43_phy_mask(dev, 0x503, ~0x4);
|
||||
b43_phy_mask(dev, 0x4a4, ~0x4000);
|
||||
b43_phy_mask(dev, 0x4a4, (u16) ~0x8000);
|
||||
b43_phy_mask(dev, 0x4d0, ~0x20);
|
||||
b43_phy_set(dev, 0x4a5, 0xff);
|
||||
b43_phy_maskset(dev, 0x4a5, ~0x7000, 0x5000);
|
||||
b43_phy_mask(dev, 0x4a5, ~0x700);
|
||||
b43_phy_maskset(dev, 0x40d, ~0xff, 64);
|
||||
b43_phy_maskset(dev, 0x40d, ~0x700, 0x600);
|
||||
b43_phy_maskset(dev, 0x4a2, ~0xff, 64);
|
||||
b43_phy_maskset(dev, 0x4a2, ~0x700, 0x600);
|
||||
b43_phy_maskset(dev, 0x4d9, ~0x70, 0x20);
|
||||
b43_phy_maskset(dev, 0x4d9, ~0x700, 0x300);
|
||||
b43_phy_maskset(dev, 0x4d9, ~0x7000, 0x1000);
|
||||
b43_phy_mask(dev, 0x4da, ~0x1000);
|
||||
b43_phy_set(dev, 0x4da, 0x2000);
|
||||
b43_phy_set(dev, 0x4a6, 0x8000);
|
||||
|
||||
b43_radio_write(dev, 0x025, 0xc);
|
||||
b43_radio_set(dev, 0x005, 0x8);
|
||||
b43_phy_set(dev, 0x938, 0x4);
|
||||
b43_phy_set(dev, 0x939, 0x4);
|
||||
b43_phy_set(dev, 0x4a4, 0x1000);
|
||||
|
||||
/* FIXME: don't hardcode */
|
||||
b43_lcntab_write(dev, B43_LCNTAB16(0x8, 0x6), 0x640);
|
||||
|
||||
switch (sense_type) {
|
||||
case B43_SENSE_TEMP:
|
||||
b43_phy_set(dev, 0x4d7, 0x8);
|
||||
b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x1000);
|
||||
auxpga_vmidcourse = 8;
|
||||
auxpga_vmidfine = 0x4;
|
||||
auxpga_gain = 2;
|
||||
b43_radio_set(dev, 0x082, 0x20);
|
||||
break;
|
||||
case B43_SENSE_VBAT:
|
||||
b43_phy_set(dev, 0x4d7, 0x8);
|
||||
b43_phy_maskset(dev, 0x4d7, ~0x7000, 0x3000);
|
||||
auxpga_vmidcourse = 7;
|
||||
auxpga_vmidfine = 0xa;
|
||||
auxpga_gain = 2;
|
||||
break;
|
||||
}
|
||||
auxpga_vmid = (0x200 | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
|
||||
|
||||
b43_phy_set(dev, 0x4d8, 0x1);
|
||||
b43_phy_maskset(dev, 0x4d8, ~(0x3ff << 2), auxpga_vmid << 2);
|
||||
b43_phy_set(dev, 0x4d8, 0x2);
|
||||
b43_phy_maskset(dev, 0x4d8, ~(0x7 << 12), auxpga_gain << 12);
|
||||
b43_phy_set(dev, 0x4d0, 0x20);
|
||||
b43_radio_write(dev, 0x112, 0x6);
|
||||
|
||||
b43_dummy_transmission(dev, true, false);
|
||||
/* Wait if not done */
|
||||
if (!(b43_phy_read(dev, 0x476) & 0x8000))
|
||||
udelay(10);
|
||||
|
||||
/* Restore */
|
||||
for (i = 0; i < 6; i++)
|
||||
b43_radio_write(dev, save_radio_regs[i][0],
|
||||
save_radio_regs[i][1]);
|
||||
for (i = 0; i < 14; i++)
|
||||
b43_phy_write(dev, save_phy_regs[i][0], save_phy_regs[i][1]);
|
||||
/* TODO: wlc_lcnphy_set_tx_pwr_by_index(tx_pwr_idx) */
|
||||
b43_radio_write(dev, 0x4a4, save_radio_4a4);
|
||||
|
||||
b43_mac_enable(dev);
|
||||
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
static bool b43_phy_lcn_load_tx_iir_cck_filter(struct b43_wldev *dev,
|
||||
u8 filter_type)
|
||||
{
|
||||
int i, j;
|
||||
u16 phy_regs[] = { 0x910, 0x91e, 0x91f, 0x924, 0x925, 0x926, 0x920,
|
||||
0x921, 0x927, 0x928, 0x929, 0x922, 0x923, 0x930,
|
||||
0x931, 0x932 };
|
||||
/* Table is from brcmsmac, values for type 25 were outdated, probably
|
||||
* others need updating too */
|
||||
struct lcn_tx_iir_filter tx_iir_filters_cck[] = {
|
||||
{ 0, { 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778,
|
||||
1582, 64, 128, 64 } },
|
||||
{ 1, { 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608,
|
||||
1863, 93, 167, 93 } },
|
||||
{ 2, { 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192,
|
||||
778, 1582, 64, 128, 64 } },
|
||||
{ 3, { 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205,
|
||||
754, 1760, 170, 340, 170 } },
|
||||
{ 20, { 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205,
|
||||
767, 1760, 256, 185, 256 } },
|
||||
{ 21, { 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205,
|
||||
767, 1760, 256, 273, 256 } },
|
||||
{ 22, { 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205,
|
||||
767, 1760, 256, 352, 256 } },
|
||||
{ 23, { 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205,
|
||||
767, 1760, 128, 233, 128 } },
|
||||
{ 24, { 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766,
|
||||
1760, 256, 1881, 256 } },
|
||||
{ 25, { 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765,
|
||||
1760, 262, 1878, 262 } },
|
||||
/* brcmsmac version { 25, { 1, 299, 1884, 51, 64, 51, 736, 1720,
|
||||
* 256, 471, 256, 765, 1760, 256, 1881, 256 } }, */
|
||||
{ 26, { 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614,
|
||||
1864, 128, 384, 288 } },
|
||||
{ 27, { 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576,
|
||||
613, 1864, 128, 384, 288 } },
|
||||
{ 30, { 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205,
|
||||
754, 1760, 170, 340, 170 } },
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tx_iir_filters_cck); i++) {
|
||||
if (tx_iir_filters_cck[i].type == filter_type) {
|
||||
for (j = 0; j < 16; j++)
|
||||
b43_phy_write(dev, phy_regs[j],
|
||||
tx_iir_filters_cck[i].values[j]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool b43_phy_lcn_load_tx_iir_ofdm_filter(struct b43_wldev *dev,
|
||||
u8 filter_type)
|
||||
{
|
||||
int i, j;
|
||||
u16 phy_regs[] = { 0x90f, 0x900, 0x901, 0x906, 0x907, 0x908, 0x902,
|
||||
0x903, 0x909, 0x90a, 0x90b, 0x904, 0x905, 0x90c,
|
||||
0x90d, 0x90e };
|
||||
struct lcn_tx_iir_filter tx_iir_filters_ofdm[] = {
|
||||
{ 0, { 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0,
|
||||
0x0, 0x278, 0xfea0, 0x80, 0x100, 0x80 } },
|
||||
{ 1, { 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50, 750,
|
||||
0xFE2B, 212, 0xFFCE, 212 } },
|
||||
{ 2, { 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
|
||||
0xFEF2, 128, 0xFFE2, 128 } },
|
||||
};
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tx_iir_filters_ofdm); i++) {
|
||||
if (tx_iir_filters_ofdm[i].type == filter_type) {
|
||||
for (j = 0; j < 16; j++)
|
||||
b43_phy_write(dev, phy_regs[j],
|
||||
tx_iir_filters_ofdm[i].values[j]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_set_tx_gain_override */
|
||||
static void b43_phy_lcn_set_tx_gain_override(struct b43_wldev *dev, bool enable)
|
||||
{
|
||||
b43_phy_maskset(dev, 0x4b0, ~(0x1 << 7), enable << 7);
|
||||
b43_phy_maskset(dev, 0x4b0, ~(0x1 << 14), enable << 14);
|
||||
b43_phy_maskset(dev, 0x43b, ~(0x1 << 6), enable << 6);
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_set_tx_gain */
|
||||
static void b43_phy_lcn_set_tx_gain(struct b43_wldev *dev,
|
||||
struct lcn_tx_gains *target_gains)
|
||||
{
|
||||
u16 pa_gain = b43_phy_lcn_get_pa_gain(dev);
|
||||
|
||||
b43_phy_write(dev, 0x4b5,
|
||||
(target_gains->gm_gain | (target_gains->pga_gain << 8)));
|
||||
b43_phy_maskset(dev, 0x4fb, ~0x7fff,
|
||||
(target_gains->pad_gain | (pa_gain << 8)));
|
||||
b43_phy_write(dev, 0x4fc,
|
||||
(target_gains->gm_gain | (target_gains->pga_gain << 8)));
|
||||
b43_phy_maskset(dev, 0x4fd, ~0x7fff,
|
||||
(target_gains->pad_gain | (pa_gain << 8)));
|
||||
|
||||
b43_phy_lcn_set_dac_gain(dev, target_gains->dac_gain);
|
||||
b43_phy_lcn_set_tx_gain_override(dev, true);
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_tx_pwr_ctrl_init */
|
||||
static void b43_phy_lcn_tx_pwr_ctl_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct lcn_tx_gains tx_gains;
|
||||
u8 bbmult;
|
||||
|
||||
b43_mac_suspend(dev);
|
||||
|
||||
if (!dev->phy.lcn->hw_pwr_ctl_capable) {
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
tx_gains.gm_gain = 4;
|
||||
tx_gains.pga_gain = 12;
|
||||
tx_gains.pad_gain = 12;
|
||||
tx_gains.dac_gain = 0;
|
||||
bbmult = 150;
|
||||
} else {
|
||||
tx_gains.gm_gain = 7;
|
||||
tx_gains.pga_gain = 15;
|
||||
tx_gains.pad_gain = 14;
|
||||
tx_gains.dac_gain = 0;
|
||||
bbmult = 150;
|
||||
}
|
||||
b43_phy_lcn_set_tx_gain(dev, &tx_gains);
|
||||
b43_phy_lcn_set_bbmult(dev, bbmult);
|
||||
b43_phy_lcn_sense_setup(dev, B43_SENSE_TEMP);
|
||||
} else {
|
||||
b43err(dev->wl, "TX power control not supported for this HW\n");
|
||||
}
|
||||
|
||||
b43_mac_enable(dev);
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_txrx_spur_avoidance_mode */
|
||||
static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
|
||||
bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
b43_phy_write(dev, 0x942, 0x7);
|
||||
b43_phy_write(dev, 0x93b, ((1 << 13) + 23));
|
||||
b43_phy_write(dev, 0x93c, ((1 << 13) + 1989));
|
||||
|
||||
b43_phy_write(dev, 0x44a, 0x084);
|
||||
b43_phy_write(dev, 0x44a, 0x080);
|
||||
b43_phy_write(dev, 0x6d3, 0x2222);
|
||||
b43_phy_write(dev, 0x6d3, 0x2220);
|
||||
} else {
|
||||
b43_phy_write(dev, 0x942, 0x0);
|
||||
b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
|
||||
b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
|
||||
}
|
||||
b43_phy_switch_macfreq(dev, enable);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Channel switching ops.
|
||||
**************************************************/
|
||||
|
||||
/* wlc_lcnphy_set_chanspec_tweaks */
|
||||
static void b43_phy_lcn_set_channel_tweaks(struct b43_wldev *dev, int channel)
|
||||
{
|
||||
struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
|
||||
|
||||
b43_phy_maskset(dev, 0x448, ~0x300, (channel == 14) ? 0x200 : 0x100);
|
||||
|
||||
if (channel == 1 || channel == 2 || channel == 3 || channel == 4 ||
|
||||
channel == 9 || channel == 10 || channel == 11 || channel == 12) {
|
||||
bcma_chipco_pll_write(cc, 0x2, 0x03000c04);
|
||||
bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x0);
|
||||
bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
|
||||
|
||||
bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
|
||||
|
||||
b43_phy_write(dev, 0x942, 0);
|
||||
|
||||
b43_phy_lcn_txrx_spur_avoidance_mode(dev, false);
|
||||
b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1b00);
|
||||
b43_phy_write(dev, 0x425, 0x5907);
|
||||
} else {
|
||||
bcma_chipco_pll_write(cc, 0x2, 0x03140c04);
|
||||
bcma_chipco_pll_maskset(cc, 0x3, 0x00ffffff, 0x333333);
|
||||
bcma_chipco_pll_write(cc, 0x4, 0x202c2820);
|
||||
|
||||
bcma_cc_set32(cc, BCMA_CC_PMU_CTL, 0x400);
|
||||
|
||||
b43_phy_write(dev, 0x942, 0);
|
||||
|
||||
b43_phy_lcn_txrx_spur_avoidance_mode(dev, true);
|
||||
b43_phy_maskset(dev, 0x424, (u16) ~0xff00, 0x1f00);
|
||||
b43_phy_write(dev, 0x425, 0x590a);
|
||||
}
|
||||
|
||||
b43_phy_set(dev, 0x44a, 0x44);
|
||||
b43_phy_write(dev, 0x44a, 0x80);
|
||||
}
|
||||
|
||||
/* wlc_phy_chanspec_set_lcnphy */
|
||||
static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
|
||||
struct ieee80211_channel *channel,
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
/* TODO: PLL and PHY ops */
|
||||
static const u16 sfo_cfg[14][2] = {
|
||||
{965, 1087}, {967, 1085}, {969, 1082}, {971, 1080}, {973, 1078},
|
||||
{975, 1076}, {977, 1073}, {979, 1071}, {981, 1069}, {983, 1067},
|
||||
{985, 1065}, {987, 1063}, {989, 1060}, {994, 1055},
|
||||
};
|
||||
|
||||
b43_phy_set(dev, 0x44a, 0x44);
|
||||
b43_phy_write(dev, 0x44a, 0x80);
|
||||
b43_phy_lcn_set_channel_tweaks(dev, channel->hw_value);
|
||||
|
||||
b43_phy_set(dev, 0x44a, 0x44);
|
||||
b43_phy_write(dev, 0x44a, 0x80);
|
||||
@ -295,7 +675,21 @@ static int b43_phy_lcn_set_channel(struct b43_wldev *dev,
|
||||
|
||||
b43_phy_lcn_afe_set_unset(dev);
|
||||
|
||||
/* TODO */
|
||||
b43_phy_write(dev, 0x657, sfo_cfg[channel->hw_value - 1][0]);
|
||||
b43_phy_write(dev, 0x658, sfo_cfg[channel->hw_value - 1][1]);
|
||||
|
||||
if (channel->hw_value == 14) {
|
||||
b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (2) << 8);
|
||||
b43_phy_lcn_load_tx_iir_cck_filter(dev, 3);
|
||||
} else {
|
||||
b43_phy_maskset(dev, 0x448, ~(0x3 << 8), (1) << 8);
|
||||
/* brcmsmac uses filter_type 2, we follow wl with 25 */
|
||||
b43_phy_lcn_load_tx_iir_cck_filter(dev, 25);
|
||||
}
|
||||
/* brcmsmac uses filter_type 2, we follow wl with 0 */
|
||||
b43_phy_lcn_load_tx_iir_ofdm_filter(dev, 0);
|
||||
|
||||
b43_phy_maskset(dev, 0x4eb, ~(0x7 << 3), 0x1 << 3);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -336,6 +730,8 @@ static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
|
||||
/* wlc_phy_init_lcnphy */
|
||||
static int b43_phy_lcn_op_init(struct b43_wldev *dev)
|
||||
{
|
||||
struct bcma_drv_cc *cc = &dev->dev->bdev->bus->drv_cc;
|
||||
|
||||
b43_phy_set(dev, 0x44a, 0x80);
|
||||
b43_phy_mask(dev, 0x44a, 0x7f);
|
||||
b43_phy_set(dev, 0x6d1, 0x80);
|
||||
@ -357,7 +753,21 @@ static int b43_phy_lcn_op_init(struct b43_wldev *dev)
|
||||
else
|
||||
B43_WARN_ON(1);
|
||||
|
||||
b43_phy_lcn_sense_setup(dev);
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
|
||||
b43_phy_lcn_tx_pwr_ctl_init(dev);
|
||||
|
||||
b43_switch_channel(dev, dev->phy.channel);
|
||||
|
||||
bcma_chipco_regctl_maskset(cc, 0, 0xf, 0x9);
|
||||
bcma_chipco_chipctl_maskset(cc, 0, 0, 0x03cddddd);
|
||||
|
||||
/* TODO */
|
||||
|
||||
b43_phy_set(dev, 0x448, 0x4000);
|
||||
udelay(100);
|
||||
b43_phy_mask(dev, 0x448, ~0x4000);
|
||||
|
||||
/* TODO */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,6 +19,9 @@
|
||||
|
||||
|
||||
struct b43_phy_lcn {
|
||||
bool hw_pwr_ctl;
|
||||
bool hw_pwr_ctl_capable;
|
||||
u8 tx_pwr_curr_idx;
|
||||
};
|
||||
|
||||
|
||||
|
@ -657,8 +657,25 @@ void b43_phy_lcn_load_tx_gain_tab(struct b43_wldev *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/* wlc_lcnphy_load_rfpower */
|
||||
static void b43_phy_lcn_load_rfpower(struct b43_wldev *dev)
|
||||
{
|
||||
u32 bbmult, rfgain;
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < 128; i++) {
|
||||
bbmult = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0x140 + i));
|
||||
bbmult >>= 20;
|
||||
rfgain = b43_lcntab_read(dev, B43_LCNTAB32(0x7, 0xc0 + i));
|
||||
|
||||
/* TODO: calculate value for 0x240 + i table offset
|
||||
* b43_lcntab_write(dev, B43_LCNTAB32(0x7, 0x240 + i), val);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Not implemented in brcmsmac, noticed in wl in MMIO dump */
|
||||
static void b43_phy_lcn_rewrite_tables(struct b43_wldev *dev)
|
||||
static void b43_phy_lcn_rewrite_rfpower_table(struct b43_wldev *dev)
|
||||
{
|
||||
int i;
|
||||
u32 tmp;
|
||||
@ -685,7 +702,7 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev)
|
||||
b43_phy_lcn_upload_static_tables(dev);
|
||||
|
||||
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
|
||||
if (sprom->boardflags_lo & B43_BFL_EXTLNA)
|
||||
if (sprom->boardflags_lo & B43_BFL_FEM)
|
||||
b43_phy_lcn_load_tx_gain_tab(dev,
|
||||
b43_lcntab_tx_gain_tbl_2ghz_ext_pa_rev0);
|
||||
else
|
||||
@ -701,7 +718,7 @@ void b43_phy_lcn_tables_init(struct b43_wldev *dev)
|
||||
else
|
||||
b43err(dev->wl, "SW ctl table is unknown for this card\n");
|
||||
|
||||
/* TODO: various tables ops here */
|
||||
b43_phy_lcn_rewrite_tables(dev);
|
||||
b43_phy_lcn_load_rfpower(dev);
|
||||
b43_phy_lcn_rewrite_rfpower_table(dev);
|
||||
b43_phy_lcn_clean_papd_comp_table(dev);
|
||||
}
|
||||
|
@ -937,7 +937,7 @@ void iwl_legacy_irq_handle_error(struct iwl_priv *priv)
|
||||
&priv->contexts[IWL_RXON_CTX_BSS]);
|
||||
#endif
|
||||
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
|
||||
/* Keep the restart process from trying to send host
|
||||
* commands by clearing the INIT status bit */
|
||||
@ -1746,7 +1746,7 @@ int iwl_legacy_force_reset(struct iwl_priv *priv, bool external)
|
||||
|
||||
/* Set the FW error flag -- cleared on iwl_down */
|
||||
set_bit(STATUS_FW_ERROR, &priv->status);
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
/*
|
||||
* Keep the restart process from trying to send host
|
||||
* commands by clearing the INIT status bit
|
||||
@ -2220,7 +2220,8 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_legacy_mac_config);
|
||||
|
||||
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
|
||||
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
|
@ -620,7 +620,8 @@ static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
|
||||
|
||||
/* mac80211 handlers */
|
||||
int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
|
||||
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
|
@ -167,7 +167,7 @@ int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wait_event_interruptible_timeout(priv->wait_command_queue,
|
||||
ret = wait_event_timeout(priv->wait_command_queue,
|
||||
!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
|
||||
HOST_COMPLETE_TIMEOUT);
|
||||
if (!ret) {
|
||||
|
@ -625,6 +625,8 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
cmd = txq->cmd[cmd_index];
|
||||
meta = &txq->meta[cmd_index];
|
||||
|
||||
txq->time_stamp = jiffies;
|
||||
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
dma_unmap_addr(meta, mapping),
|
||||
dma_unmap_len(meta, len),
|
||||
@ -645,7 +647,7 @@ iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
|
||||
iwl_legacy_get_cmd_string(cmd->hdr.cmd));
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
}
|
||||
|
||||
/* Mark as unmapped */
|
||||
|
@ -840,7 +840,7 @@ static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
else
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2268,7 +2268,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
||||
iwl3945_reg_txpower_periodic(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
|
||||
return;
|
||||
|
||||
@ -2299,7 +2299,7 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
||||
iwl_legacy_clear_driver_stations(priv);
|
||||
|
||||
/* Unblock any waiting calls */
|
||||
wake_up_interruptible_all(&priv->wait_command_queue);
|
||||
wake_up_all(&priv->wait_command_queue);
|
||||
|
||||
/* Wipe out the EXIT_PENDING status bit if we are not actually
|
||||
* exiting the module */
|
||||
@ -2852,7 +2852,7 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw)
|
||||
|
||||
/* Wait for START_ALIVE from ucode. Otherwise callbacks from
|
||||
* mac80211 will not be run successfully. */
|
||||
ret = wait_event_interruptible_timeout(priv->wait_command_queue,
|
||||
ret = wait_event_timeout(priv->wait_command_queue,
|
||||
test_bit(STATUS_READY, &priv->status),
|
||||
UCODE_READY_TIMEOUT);
|
||||
if (!ret) {
|
||||
|
@ -575,7 +575,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
else
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -925,7 +925,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
|
||||
handled |= CSR_INT_BIT_FH_TX;
|
||||
/* Wake up uCode load routine, now that load is complete */
|
||||
priv->ucode_write_complete = 1;
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
}
|
||||
|
||||
if (inta & ~handled) {
|
||||
@ -1794,7 +1794,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv)
|
||||
iwl4965_rf_kill_ct_config(priv);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
wake_up(&priv->wait_command_queue);
|
||||
|
||||
iwl_legacy_power_update_mode(priv, true);
|
||||
IWL_DEBUG_INFO(priv, "Updated power mode\n");
|
||||
@ -1827,7 +1827,7 @@ static void __iwl4965_down(struct iwl_priv *priv)
|
||||
iwl_legacy_clear_driver_stations(priv);
|
||||
|
||||
/* Unblock any waiting calls */
|
||||
wake_up_interruptible_all(&priv->wait_command_queue);
|
||||
wake_up_all(&priv->wait_command_queue);
|
||||
|
||||
/* Wipe out the EXIT_PENDING status bit if we are not actually
|
||||
* exiting the module */
|
||||
@ -2265,7 +2265,7 @@ int iwl4965_mac_start(struct ieee80211_hw *hw)
|
||||
|
||||
/* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from
|
||||
* mac80211 will not be run successfully. */
|
||||
ret = wait_event_interruptible_timeout(priv->wait_command_queue,
|
||||
ret = wait_event_timeout(priv->wait_command_queue,
|
||||
test_bit(STATUS_READY, &priv->status),
|
||||
UCODE_READY_TIMEOUT);
|
||||
if (!ret) {
|
||||
|
@ -3,18 +3,19 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o
|
||||
iwlagn-objs := iwl-agn.o iwl-agn-rs.o
|
||||
iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o
|
||||
iwlagn-objs += iwl-agn-lib.o iwl-agn-calib.o iwl-io.o
|
||||
iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
|
||||
iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o
|
||||
|
||||
iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o
|
||||
iwlagn-objs += iwl-rx.o iwl-sta.o
|
||||
iwlagn-objs += iwl-scan.o iwl-led.o
|
||||
iwlagn-objs += iwl-agn-rxon.o
|
||||
iwlagn-objs += iwl-5000.o
|
||||
iwlagn-objs += iwl-6000.o
|
||||
iwlagn-objs += iwl-1000.o
|
||||
iwlagn-objs += iwl-2000.o
|
||||
iwlagn-objs += iwl-pci.o
|
||||
iwlagn-objs += iwl-trans.o iwl-trans-rx-pcie.o iwl-trans-tx-pcie.o
|
||||
iwlagn-objs += iwl-core.o iwl-eeprom.o iwl-power.o
|
||||
iwlagn-objs += iwl-rx.o iwl-sta.o
|
||||
iwlagn-objs += iwl-scan.o iwl-led.o
|
||||
iwlagn-objs += iwl-agn-rxon.o
|
||||
iwlagn-objs += iwl-5000.o
|
||||
iwlagn-objs += iwl-6000.o
|
||||
iwlagn-objs += iwl-1000.o
|
||||
iwlagn-objs += iwl-2000.o
|
||||
iwlagn-objs += iwl-pci.o
|
||||
iwlagn-objs += iwl-trans.o
|
||||
iwlagn-objs += iwl-trans-pcie.o iwl-trans-pcie-rx.o iwl-trans-pcie-tx.o
|
||||
|
||||
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
|
||||
iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-pci.h"
|
||||
#include "iwl-cfg.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL1000_UCODE_API_MAX 6
|
||||
@ -161,8 +161,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
if (priv->cfg->need_dc_calib)
|
||||
hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
|
||||
|
||||
hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -191,7 +189,6 @@ static struct iwl_base_params iwl1000_base_params = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-6000-hw.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-pci.h"
|
||||
#include "iwl-cfg.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL2030_UCODE_API_MAX 6
|
||||
@ -75,7 +75,7 @@
|
||||
#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
#define IWL135_FW_PRE "iwlwifi-135-"
|
||||
#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode"
|
||||
#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE __stringify(api) ".ucode"
|
||||
|
||||
static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
|
||||
{
|
||||
@ -159,8 +159,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
if (priv->cfg->need_temp_offset_calib)
|
||||
hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
|
||||
|
||||
hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -211,7 +209,6 @@ static struct iwl_base_params iwl2000_base_params = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
@ -231,7 +228,6 @@ static struct iwl_base_params iwl2030_base_params = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
@ -268,6 +264,7 @@ static struct iwl_bt_params iwl2030_bt_params = {
|
||||
.base_params = &iwl2000_base_params, \
|
||||
.need_dc_calib = true, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.iq_invert = true \
|
||||
|
||||
@ -300,6 +297,7 @@ struct iwl_cfg iwl2000_2bgn_d_cfg = {
|
||||
.bt_params = &iwl2030_bt_params, \
|
||||
.need_dc_calib = true, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true, \
|
||||
.iq_invert = true \
|
||||
@ -326,6 +324,7 @@ struct iwl_cfg iwl2030_2bg_cfg = {
|
||||
.base_params = &iwl2000_base_params, \
|
||||
.need_dc_calib = true, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true, \
|
||||
.rx_with_siso_diversity = true, \
|
||||
@ -354,6 +353,7 @@ struct iwl_cfg iwl105_bgn_cfg = {
|
||||
.bt_params = &iwl2030_bt_params, \
|
||||
.need_dc_calib = true, \
|
||||
.need_temp_offset_calib = true, \
|
||||
.temp_offset_v2 = true, \
|
||||
.led_mode = IWL_LED_RF_STATE, \
|
||||
.adv_pm = true, \
|
||||
.rx_with_siso_diversity = true, \
|
||||
|
@ -74,8 +74,8 @@
|
||||
static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
|
||||
{
|
||||
u16 temperature, voltage;
|
||||
__le16 *temp_calib =
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
|
||||
__le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(priv,
|
||||
EEPROM_KELVIN_TEMPERATURE);
|
||||
|
||||
temperature = le16_to_cpu(temp_calib[0]);
|
||||
voltage = le16_to_cpu(temp_calib[1]);
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include "iwl-5000-hw.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-pci.h"
|
||||
#include "iwl-cfg.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL5000_UCODE_API_MAX 5
|
||||
@ -184,8 +184,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
BIT(IWL_CALIB_TX_IQ_PERD) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -223,8 +221,6 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
||||
if (priv->cfg->need_dc_calib)
|
||||
hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_DC);
|
||||
|
||||
hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -353,7 +349,6 @@ static struct iwl_base_params iwl5000_base_params = {
|
||||
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.wd_timeout = IWL_LONG_WD_TIMEOUT,
|
||||
|
@ -46,7 +46,7 @@
|
||||
#include "iwl-6000-hw.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-pci.h"
|
||||
#include "iwl-cfg.h"
|
||||
|
||||
/* Highest firmware API version supported */
|
||||
#define IWL6000_UCODE_API_MAX 4
|
||||
@ -180,8 +180,6 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
if (priv->cfg->need_temp_offset_calib)
|
||||
hw_params(priv).calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
|
||||
|
||||
hw_params(priv).beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -305,7 +303,6 @@ static struct iwl_base_params iwl6000_base_params = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
@ -323,7 +320,6 @@ static struct iwl_base_params iwl6050_base_params = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
@ -340,7 +336,6 @@ static struct iwl_base_params iwl6000_g2_base_params = {
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.led_compensation = 57,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
|
@ -766,12 +766,9 @@ static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
||||
u8 first_chain;
|
||||
u16 i = 0;
|
||||
|
||||
average_sig[0] = data->chain_signal_a /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_sig[1] = data->chain_signal_b /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_sig[2] = data->chain_signal_c /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_sig[0] = data->chain_signal_a / IWL_CAL_NUM_BEACONS;
|
||||
average_sig[1] = data->chain_signal_b / IWL_CAL_NUM_BEACONS;
|
||||
average_sig[2] = data->chain_signal_c / IWL_CAL_NUM_BEACONS;
|
||||
|
||||
if (average_sig[0] >= average_sig[1]) {
|
||||
max_average_sig = average_sig[0];
|
||||
@ -1038,8 +1035,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
||||
/* If this is the "chain_noise_num_beacons", determine:
|
||||
* 1) Disconnected antennas (using signal strengths)
|
||||
* 2) Differential gain (using silence noise) to balance receivers */
|
||||
if (data->beacon_count !=
|
||||
priv->cfg->base_params->chain_noise_num_beacons)
|
||||
if (data->beacon_count != IWL_CAL_NUM_BEACONS)
|
||||
return;
|
||||
|
||||
/* Analyze signal for disconnected antenna */
|
||||
@ -1055,12 +1051,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv)
|
||||
iwl_find_disconn_antenna(priv, average_sig, data);
|
||||
|
||||
/* Analyze noise for rx balance */
|
||||
average_noise[0] = data->chain_noise_a /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_noise[1] = data->chain_noise_b /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_noise[2] = data->chain_noise_c /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_noise[0] = data->chain_noise_a / IWL_CAL_NUM_BEACONS;
|
||||
average_noise[1] = data->chain_noise_b / IWL_CAL_NUM_BEACONS;
|
||||
average_noise[2] = data->chain_noise_c / IWL_CAL_NUM_BEACONS;
|
||||
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
if (!(data->disconn_array[i]) &&
|
||||
|
@ -1,299 +0,0 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 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
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-io.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM related functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
int iwl_eeprom_check_version(struct iwl_priv *priv)
|
||||
{
|
||||
u16 eeprom_ver;
|
||||
u16 calib_ver;
|
||||
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
calib_ver = iwlagn_eeprom_calib_version(priv);
|
||||
|
||||
if (eeprom_ver < priv->cfg->eeprom_ver ||
|
||||
calib_ver < priv->cfg->eeprom_calib_ver)
|
||||
goto err;
|
||||
|
||||
IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
|
||||
eeprom_ver, calib_ver);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
|
||||
"CALIB=0x%x < 0x%x\n",
|
||||
eeprom_ver, priv->cfg->eeprom_ver,
|
||||
calib_ver, priv->cfg->eeprom_calib_ver);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
int iwl_eeprom_check_sku(struct iwl_priv *priv)
|
||||
{
|
||||
u16 radio_cfg;
|
||||
|
||||
if (!priv->cfg->sku) {
|
||||
/* not using sku overwrite */
|
||||
priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
|
||||
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
||||
!priv->cfg->ht_params) {
|
||||
IWL_ERR(priv, "Invalid 11n configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (!priv->cfg->sku) {
|
||||
IWL_ERR(priv, "Invalid device sku\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
|
||||
|
||||
if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
|
||||
/* not using .cfg overwrite */
|
||||
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
|
||||
priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||
priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||
if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
|
||||
IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
|
||||
priv->cfg->valid_tx_ant,
|
||||
priv->cfg->valid_rx_ant);
|
||||
return -EINVAL;
|
||||
}
|
||||
IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
|
||||
priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
|
||||
}
|
||||
/*
|
||||
* for some special cases,
|
||||
* EEPROM did not reflect the correct antenna setting
|
||||
* so overwrite the valid tx/rx antenna from .cfg
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
|
||||
{
|
||||
const u8 *addr = iwl_eeprom_query_addr(priv,
|
||||
EEPROM_MAC_ADDRESS);
|
||||
memcpy(mac, addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
||||
* find the highest tx power from all chains for the channel
|
||||
*/
|
||||
static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
s8 max_txpower_avg = 0; /* (dBm) */
|
||||
|
||||
/* Take the highest tx power from any valid chains */
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) &&
|
||||
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_a_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) &&
|
||||
(enhanced_txpower[element].chain_b_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_b_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) &&
|
||||
(enhanced_txpower[element].chain_c_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_c_max;
|
||||
if (((priv->cfg->valid_tx_ant == ANT_AB) |
|
||||
(priv->cfg->valid_tx_ant == ANT_BC) |
|
||||
(priv->cfg->valid_tx_ant == ANT_AC)) &&
|
||||
(enhanced_txpower[element].mimo2_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo2_max;
|
||||
if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
|
||||
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo3_max;
|
||||
|
||||
/*
|
||||
* max. tx power in EEPROM is in 1/2 dBm format
|
||||
* convert from 1/2 dBm to dBm (round-up convert)
|
||||
* but we also do not want to loss 1/2 dBm resolution which
|
||||
* will impact performance
|
||||
*/
|
||||
*max_txpower_in_half_dbm = max_txpower_avg;
|
||||
return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *txp,
|
||||
s8 max_txpower_avg)
|
||||
{
|
||||
int ch_idx;
|
||||
bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
|
||||
enum ieee80211_band band;
|
||||
|
||||
band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
|
||||
IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
|
||||
|
||||
for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
|
||||
struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
|
||||
|
||||
/* update matching channel or from common data only */
|
||||
if (txp->channel != 0 && ch_info->channel != txp->channel)
|
||||
continue;
|
||||
|
||||
/* update matching band only */
|
||||
if (band != ch_info->band)
|
||||
continue;
|
||||
|
||||
if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
|
||||
ch_info->max_power_avg = max_txpower_avg;
|
||||
ch_info->curr_txpow = max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
|
||||
if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
}
|
||||
}
|
||||
|
||||
#define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
|
||||
#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
|
||||
#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
|
||||
|
||||
#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
|
||||
? # x " " : "")
|
||||
|
||||
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
|
||||
int idx, entries;
|
||||
__le16 *txp_len;
|
||||
s8 max_txp_avg, max_txp_avg_halfdbm;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
|
||||
|
||||
/* the length is in 16-bit words, but we want entries */
|
||||
txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
|
||||
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
|
||||
|
||||
txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
|
||||
|
||||
for (idx = 0; idx < entries; idx++) {
|
||||
txp = &txp_array[idx];
|
||||
/* skip invalid entries */
|
||||
if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
|
||||
continue;
|
||||
|
||||
IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
|
||||
(txp->channel && (txp->flags &
|
||||
IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
|
||||
"Common " : (txp->channel) ?
|
||||
"Channel" : "Common",
|
||||
(txp->channel),
|
||||
TXP_CHECK_AND_PRINT(VALID),
|
||||
TXP_CHECK_AND_PRINT(BAND_52G),
|
||||
TXP_CHECK_AND_PRINT(OFDM),
|
||||
TXP_CHECK_AND_PRINT(40MHZ),
|
||||
TXP_CHECK_AND_PRINT(HT_AP),
|
||||
TXP_CHECK_AND_PRINT(RES1),
|
||||
TXP_CHECK_AND_PRINT(RES2),
|
||||
TXP_CHECK_AND_PRINT(COMMON_TYPE),
|
||||
txp->flags);
|
||||
IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
|
||||
"chain_B: 0X%02x chain_C: 0X%02x\n",
|
||||
txp->chain_a_max, txp->chain_b_max,
|
||||
txp->chain_c_max);
|
||||
IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
|
||||
"MIMO3: 0x%02x High 20_on_40: 0x%02x "
|
||||
"Low 20_on_40: 0x%02x\n",
|
||||
txp->mimo2_max, txp->mimo3_max,
|
||||
((txp->delta_20_in_40 & 0xf0) >> 4),
|
||||
(txp->delta_20_in_40 & 0x0f));
|
||||
|
||||
max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
|
||||
&max_txp_avg_halfdbm);
|
||||
|
||||
/*
|
||||
* Update the user limit values values to the highest
|
||||
* power supported by any channel
|
||||
*/
|
||||
if (max_txp_avg > priv->tx_power_user_lmt)
|
||||
priv->tx_power_user_lmt = max_txp_avg;
|
||||
if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
|
||||
priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
|
||||
|
||||
iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
|
||||
}
|
||||
}
|
@ -96,11 +96,7 @@ void iwlagn_temperature(struct iwl_priv *priv)
|
||||
|
||||
u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_eeprom_calib_hdr {
|
||||
u8 version;
|
||||
u8 pa_type;
|
||||
u16 voltage;
|
||||
} *hdr;
|
||||
struct iwl_eeprom_calib_hdr *hdr;
|
||||
|
||||
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
|
||||
EEPROM_CALIB_ALL);
|
||||
@ -194,433 +190,6 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int 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, vif);
|
||||
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
||||
channel = iwl_get_single_channel_number(priv, band);
|
||||
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,
|
||||
struct ieee80211_vif *vif,
|
||||
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, vif);
|
||||
|
||||
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 = chan->hw_value;
|
||||
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;
|
||||
}
|
||||
|
||||
int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_SCAN_CMD,
|
||||
.len = { sizeof(struct iwl_scan_cmd), },
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
struct iwl_scan_cmd *scan;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
u32 rate_flags = 0;
|
||||
u16 cmd_len;
|
||||
u16 rx_chain = 0;
|
||||
enum ieee80211_band band;
|
||||
u8 n_probes = 0;
|
||||
u8 rx_ant = hw_params(priv).valid_rx_ant;
|
||||
u8 rate;
|
||||
bool is_active = false;
|
||||
int chan_mod;
|
||||
u8 active_chains;
|
||||
u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
|
||||
if (vif)
|
||||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
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");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
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 (priv->scan_type != IWL_SCAN_ROC &&
|
||||
iwl_is_any_associated(priv)) {
|
||||
u16 interval = 0;
|
||||
u32 extra;
|
||||
u32 suspend_time = 100;
|
||||
u32 scan_suspend_time = 100;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_ROC:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
interval = 0;
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
interval = vif->bss_conf.beacon_int;
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
} else if (priv->scan_type == IWL_SCAN_ROC) {
|
||||
scan->suspend_time = 0;
|
||||
scan->max_out_time = 0;
|
||||
scan->quiet_time = 0;
|
||||
scan->quiet_plcp_th = 0;
|
||||
}
|
||||
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
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");
|
||||
break;
|
||||
case IWL_SCAN_ROC:
|
||||
IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
scan->tx_cmd.sta_id = ctx->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->contexts[IWL_RXON_CTX_BSS].active.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;
|
||||
}
|
||||
/*
|
||||
* Internal scans are passive, so we can indiscriminately set
|
||||
* the BT ignore flag on 2.4 GHz since it applies to TX only.
|
||||
*/
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist)
|
||||
scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
rate = IWL_RATE_6M_PLCP;
|
||||
break;
|
||||
default:
|
||||
IWL_WARN(priv, "Invalid scan band\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If active scanning is requested but a certain channel is
|
||||
* marked passive, we can do active scanning if we detect
|
||||
* transmissions.
|
||||
*
|
||||
* There is an issue with some firmware versions that triggers
|
||||
* a sysassert on a "good CRC threshold" of zero (== disabled),
|
||||
* on a radar channel even though this means that we should NOT
|
||||
* send probes.
|
||||
*
|
||||
* The "good CRC threshold" is the number of frames that we
|
||||
* need to receive during our dwell time on a channel before
|
||||
* sending out probes -- setting this to a huge value will
|
||||
* mean we never reach it, but at the same time work around
|
||||
* the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
|
||||
* here instead of IWL_GOOD_CRC_TH_DISABLED.
|
||||
*
|
||||
* This was fixed in later versions along with some other
|
||||
* scan changes, and the threshold behaves as a flag in those
|
||||
* versions.
|
||||
*/
|
||||
if (priv->new_scan_threshold_behaviour)
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_DISABLED;
|
||||
else
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_NEVER;
|
||||
|
||||
band = priv->scan_band;
|
||||
|
||||
if (priv->cfg->scan_rx_antennas[band])
|
||||
rx_ant = priv->cfg->scan_rx_antennas[band];
|
||||
|
||||
if (band == IEEE80211_BAND_2GHZ &&
|
||||
priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
/* transmit 2.4 GHz probes only on first antenna */
|
||||
scan_tx_antennas = first_antenna(scan_tx_antennas);
|
||||
}
|
||||
|
||||
priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band],
|
||||
scan_tx_antennas);
|
||||
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->shrd->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);
|
||||
}
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
priv->bt_full_concurrent) {
|
||||
/* operated as 1x1 in full concurrency mode */
|
||||
rx_ant = first_antenna(rx_ant);
|
||||
}
|
||||
|
||||
/* MIMO is not used here, but value is required */
|
||||
rx_chain |=
|
||||
hw_params(priv).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);
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_NORMAL:
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
vif->addr,
|
||||
priv->scan_request->ie,
|
||||
priv->scan_request->ie_len,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
break;
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
case IWL_SCAN_ROC:
|
||||
/* use bcast addr, will not be transmitted but must be valid */
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
iwl_bcast_addr, NULL, 0,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
scan->tx_cmd.len = cpu_to_le16(cmd_len);
|
||||
|
||||
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
|
||||
RXON_FILTER_BCON_AWARE_MSK);
|
||||
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
scan->channel_count =
|
||||
iwl_get_single_channel_for_scan(priv, vif, band,
|
||||
(void *)&scan->data[cmd_len]);
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
scan->channel_count =
|
||||
iwl_get_channels_for_scan(priv, vif, band,
|
||||
is_active, n_probes,
|
||||
(void *)&scan->data[cmd_len]);
|
||||
break;
|
||||
case IWL_SCAN_ROC: {
|
||||
struct iwl_scan_channel *scan_ch;
|
||||
|
||||
scan->channel_count = 1;
|
||||
|
||||
scan_ch = (void *)&scan->data[cmd_len];
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||
scan_ch->channel =
|
||||
cpu_to_le16(priv->hw_roc_channel->hw_value);
|
||||
scan_ch->active_dwell =
|
||||
scan_ch->passive_dwell =
|
||||
cpu_to_le16(priv->hw_roc_duration);
|
||||
|
||||
/* 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 (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
|
||||
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
|
||||
else
|
||||
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (scan->channel_count == 0) {
|
||||
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
|
||||
scan->channel_count * sizeof(struct iwl_scan_channel);
|
||||
cmd.data[0] = scan;
|
||||
cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
|
||||
scan->len = cpu_to_le16(cmd.len[0]);
|
||||
|
||||
/* set scan bit here for PAN params */
|
||||
set_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
|
||||
ret = iwlagn_set_pan_params(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
if (ret) {
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
iwlagn_set_pan_params(priv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add)
|
||||
{
|
||||
@ -1136,8 +705,9 @@ static void iwlagn_set_kill_msk(struct iwl_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -1146,7 +716,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
|
||||
if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
|
||||
/* bt coex disabled */
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
|
||||
@ -1188,6 +758,7 @@ void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
spin_lock_irqsave(&priv->shrd->lock, flags);
|
||||
priv->bt_ci_compliance = coex->bt_ci_compliance;
|
||||
spin_unlock_irqrestore(&priv->shrd->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
|
||||
|
@ -346,7 +346,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
|
||||
{
|
||||
struct iwl_station_priv *sta_priv =
|
||||
container_of(lq_sta, struct iwl_station_priv, lq_sta);
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
struct iwl_rxon_context *ctx = sta_priv->ctx;
|
||||
|
||||
lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */
|
||||
lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
|
||||
@ -710,7 +710,7 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
|
||||
static bool rs_use_green(struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
struct iwl_rxon_context *ctx = sta_priv->ctx;
|
||||
|
||||
return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
|
||||
!(ctx->ht.non_gf_sta_present);
|
||||
@ -917,7 +917,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
struct iwl_scale_tbl_info tbl_type;
|
||||
struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
struct iwl_rxon_context *ctx = sta_priv->ctx;
|
||||
|
||||
IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
|
||||
|
||||
@ -1283,7 +1283,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
|
||||
s32 rate;
|
||||
s8 is_green = lq_sta->is_green;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
struct iwl_rxon_context *ctx = sta_priv->ctx;
|
||||
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
@ -1339,7 +1339,7 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
|
||||
s32 rate;
|
||||
s8 is_green = lq_sta->is_green;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
struct iwl_rxon_context *ctx = sta_priv->ctx;
|
||||
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
@ -1396,7 +1396,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
|
||||
u8 is_green = lq_sta->is_green;
|
||||
s32 rate;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
struct iwl_rxon_context *ctx = sta_priv->ctx;
|
||||
|
||||
if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
|
||||
return -1;
|
||||
@ -2263,7 +2263,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
u8 tid = IWL_MAX_TID_COUNT;
|
||||
struct iwl_tid_data *tid_data;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
struct iwl_rxon_context *ctx = sta_priv->common.ctx;
|
||||
struct iwl_rxon_context *ctx = sta_priv->ctx;
|
||||
|
||||
IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
|
||||
|
||||
@ -2706,7 +2706,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
|
||||
return;
|
||||
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
ctx = sta_priv->common.ctx;
|
||||
ctx = sta_priv->ctx;
|
||||
|
||||
i = lq_sta->last_txrate_idx;
|
||||
|
||||
|
@ -370,7 +370,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
|
||||
slot1 = IWL_MIN_SLOT_TIME;
|
||||
} else if (!ctx_pan->vif->bss_conf.idle &&
|
||||
!ctx_pan->vif->bss_conf.assoc) {
|
||||
slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME;
|
||||
slot1 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
|
||||
slot0 = IWL_MIN_SLOT_TIME;
|
||||
}
|
||||
} else if (ctx_pan->vif) {
|
||||
|
@ -114,9 +114,6 @@ static bool iwl_within_ct_kill_margin(struct iwl_priv *priv)
|
||||
s32 temp = priv->temperature; /* degrees CELSIUS except specified */
|
||||
bool within_margin = false;
|
||||
|
||||
if (priv->cfg->base_params->temperature_kelvin)
|
||||
temp = KELVIN_TO_CELSIUS(priv->temperature);
|
||||
|
||||
if (!priv->thermal_throttle.advanced_tt)
|
||||
within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >=
|
||||
CT_KILL_THRESHOLD_LEGACY) ? true : false;
|
||||
@ -209,7 +206,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
|
||||
{
|
||||
if (stop) {
|
||||
IWL_DEBUG_TEMP(priv, "Stop all queues\n");
|
||||
if (priv->shrd->mac80211_registered)
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
IWL_DEBUG_TEMP(priv,
|
||||
"Schedule 5 seconds CT_KILL Timer\n");
|
||||
@ -217,7 +214,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
|
||||
jiffies + CT_KILL_EXIT_DURATION * HZ);
|
||||
} else {
|
||||
IWL_DEBUG_TEMP(priv, "Wake all queues\n");
|
||||
if (priv->shrd->mac80211_registered)
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_wake_queues(priv->hw);
|
||||
}
|
||||
}
|
||||
@ -591,9 +588,6 @@ static void iwl_bg_tt_work(struct work_struct *work)
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
return;
|
||||
|
||||
if (priv->cfg->base_params->temperature_kelvin)
|
||||
temp = KELVIN_TO_CELSIUS(priv->temperature);
|
||||
|
||||
if (!priv->thermal_throttle.advanced_tt)
|
||||
iwl_legacy_tt_handler(priv, temp, false);
|
||||
else
|
||||
@ -641,11 +635,13 @@ void iwl_tt_initialize(struct iwl_priv *priv)
|
||||
|
||||
if (priv->cfg->base_params->adv_thermal_throttle) {
|
||||
IWL_DEBUG_TEMP(priv, "Advanced Thermal Throttling\n");
|
||||
tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
|
||||
IWL_TI_STATE_MAX, GFP_KERNEL);
|
||||
tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) *
|
||||
IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1),
|
||||
GFP_KERNEL);
|
||||
tt->restriction = kcalloc(IWL_TI_STATE_MAX,
|
||||
sizeof(struct iwl_tt_restriction),
|
||||
GFP_KERNEL);
|
||||
tt->transaction = kcalloc(IWL_TI_STATE_MAX *
|
||||
(IWL_TI_STATE_MAX - 1),
|
||||
sizeof(struct iwl_tt_trans),
|
||||
GFP_KERNEL);
|
||||
if (!tt->restriction || !tt->transaction) {
|
||||
IWL_ERR(priv, "Fallback to Legacy Throttling\n");
|
||||
priv->thermal_throttle.advanced_tt = false;
|
||||
|
@ -313,6 +313,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
iwl_sta_modify_sleep_tx_count(priv, sta_id, 1);
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
is_agg = true;
|
||||
|
||||
/* irqs already disabled/saved above when locking priv->shrd->lock */
|
||||
spin_lock(&priv->shrd->sta_lock);
|
||||
|
||||
@ -322,10 +325,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
goto drop_unlock_sta;
|
||||
|
||||
memset(dev_cmd, 0, sizeof(*dev_cmd));
|
||||
tx_cmd = &dev_cmd->cmd.tx;
|
||||
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
memcpy(tx_cmd->hdr, hdr, hdr_len);
|
||||
tx_cmd = (struct iwl_tx_cmd *) dev_cmd->payload;
|
||||
|
||||
/* Total # bytes to be transmitted */
|
||||
len = (u16)skb->len;
|
||||
@ -342,6 +342,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
|
||||
iwl_update_stats(priv, true, fc, len);
|
||||
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
|
||||
info->driver_data[0] = ctx;
|
||||
info->driver_data[1] = dev_cmd;
|
||||
|
||||
@ -580,6 +582,9 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
|
||||
IWL_DEBUG_COEX(priv, "receive reply tx w/ bt_kill\n");
|
||||
}
|
||||
|
||||
if (tx_resp->frame_count == 1)
|
||||
return;
|
||||
|
||||
/* Construct bit-map of pending frames within Tx window */
|
||||
for (i = 0; i < tx_resp->frame_count; i++) {
|
||||
u16 fstatus = le16_to_cpu(frame_status[i].status);
|
||||
@ -736,7 +741,8 @@ static void iwl_check_abort_status(struct iwl_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
@ -824,6 +830,7 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
|
||||
iwl_check_abort_status(priv, tx_resp->frame_count, status);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -832,8 +839,9 @@ void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
* Handles block-acknowledge notification from device, which reports success
|
||||
* of frames sent via aggregation.
|
||||
*/
|
||||
void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
|
||||
@ -857,7 +865,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
if (scd_flow >= hw_params(priv).max_txq_num) {
|
||||
IWL_ERR(priv,
|
||||
"BUG_ON scd_flow is bigger than number of queues\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
sta_id = ba_resp->sta_id;
|
||||
@ -877,14 +885,14 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
"BA scd_flow %d does not match txq_id %d\n",
|
||||
scd_flow, agg->txq_id);
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely(!agg->wait_for_ba)) {
|
||||
if (unlikely(ba_resp->bitmap))
|
||||
IWL_ERR(priv, "Received BA when not expected\n");
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
|
||||
@ -901,7 +909,7 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
ba_resp->scd_ssn);
|
||||
|
||||
/* Mark that the expected block-ack response arrived */
|
||||
agg->wait_for_ba = 0;
|
||||
agg->wait_for_ba = false;
|
||||
|
||||
/* Sanity check values reported by uCode */
|
||||
if (ba_resp->txed_2_done > ba_resp->txed) {
|
||||
@ -935,7 +943,10 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
else
|
||||
WARN_ON_ONCE(1);
|
||||
|
||||
if (freed == 0) {
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
|
||||
|
||||
if (freed == 1) {
|
||||
/* this is the first skb we deliver in this batch */
|
||||
/* put the rate scaling data there */
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
@ -948,11 +959,9 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
info);
|
||||
}
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
|
||||
|
||||
ieee80211_tx_status_irqsafe(priv->hw, skb);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->shrd->sta_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
@ -114,13 +114,8 @@ static int iwlagn_load_section(struct iwl_priv *priv, const char *name,
|
||||
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
|
||||
|
||||
IWL_DEBUG_FW(priv, "%s uCode section being loaded...\n", name);
|
||||
ret = wait_event_interruptible_timeout(priv->shrd->wait_command_queue,
|
||||
priv->ucode_write_complete, 5 * HZ);
|
||||
if (ret == -ERESTARTSYS) {
|
||||
IWL_ERR(priv, "Could not load the %s uCode section due "
|
||||
"to interrupt\n", name);
|
||||
return ret;
|
||||
}
|
||||
ret = wait_event_timeout(priv->shrd->wait_command_queue,
|
||||
priv->ucode_write_complete, 5 * HZ);
|
||||
if (!ret) {
|
||||
IWL_ERR(priv, "Could not load the %s uCode section\n",
|
||||
name);
|
||||
@ -164,7 +159,7 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_temperature_offset_cmd cmd;
|
||||
__le16 *offset_calib =
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_TEMPERATURE);
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
|
||||
@ -178,6 +173,42 @@ static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv)
|
||||
(u8 *)&cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int iwlagn_set_temperature_offset_calib_v2(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_temperature_offset_v2_cmd cmd;
|
||||
__le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(priv,
|
||||
EEPROM_KELVIN_TEMPERATURE);
|
||||
__le16 *offset_calib_low =
|
||||
(__le16 *)iwl_eeprom_query_addr(priv, EEPROM_RAW_TEMPERATURE);
|
||||
struct iwl_eeprom_calib_hdr *hdr;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
|
||||
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
|
||||
EEPROM_CALIB_ALL);
|
||||
memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
|
||||
sizeof(*offset_calib_high));
|
||||
memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
|
||||
sizeof(*offset_calib_low));
|
||||
if (!(cmd.radio_sensor_offset_low)) {
|
||||
IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
|
||||
cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||
cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
|
||||
}
|
||||
memcpy(&cmd.burntVoltageRef, &hdr->voltage,
|
||||
sizeof(hdr->voltage));
|
||||
|
||||
IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
|
||||
le16_to_cpu(cmd.radio_sensor_offset_high));
|
||||
IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
|
||||
le16_to_cpu(cmd.radio_sensor_offset_low));
|
||||
IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
|
||||
le16_to_cpu(cmd.burntVoltageRef));
|
||||
|
||||
return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET],
|
||||
(u8 *)&cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_calib_cfg_cmd calib_cfg_cmd;
|
||||
@ -197,8 +228,9 @@ static int iwlagn_send_calib_cfg(struct iwl_priv *priv)
|
||||
return iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
}
|
||||
|
||||
void iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
int iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
|
||||
@ -231,9 +263,10 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
default:
|
||||
IWL_ERR(priv, "Unknown calibration notification %d\n",
|
||||
hdr->op_code);
|
||||
return;
|
||||
return -1;
|
||||
}
|
||||
iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iwlagn_init_alive_start(struct iwl_priv *priv)
|
||||
@ -263,8 +296,12 @@ int iwlagn_init_alive_start(struct iwl_priv *priv)
|
||||
* temperature offset calibration is only needed for runtime ucode,
|
||||
* so prepare the value now.
|
||||
*/
|
||||
if (priv->cfg->need_temp_offset_calib)
|
||||
return iwlagn_set_temperature_offset_calib(priv);
|
||||
if (priv->cfg->need_temp_offset_calib) {
|
||||
if (priv->cfg->temp_offset_v2)
|
||||
return iwlagn_set_temperature_offset_calib_v2(priv);
|
||||
else
|
||||
return iwlagn_set_temperature_offset_calib(priv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -453,122 +453,6 @@ static void iwl_bg_tx_flush(struct work_struct *work)
|
||||
iwlagn_dev_txfifo_flush(priv, IWL_DROP_ALL);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* sysfs attributes
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
||||
/*
|
||||
* The following adds a new attribute to the sysfs representation
|
||||
* of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
|
||||
* used for controlling the debug level.
|
||||
*
|
||||
* See the level definitions in iwl for details.
|
||||
*
|
||||
* The debug_level being managed using sysfs below is a per device debug
|
||||
* level that is used instead of the global debug level if it (the per
|
||||
* device debug level) is set.
|
||||
*/
|
||||
static ssize_t show_debug_level(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_shared *shrd = dev_get_drvdata(d);
|
||||
return sprintf(buf, "0x%08X\n", iwl_get_debug_level(shrd));
|
||||
}
|
||||
static ssize_t store_debug_level(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_shared *shrd = dev_get_drvdata(d);
|
||||
struct iwl_priv *priv = shrd->priv;
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
|
||||
else {
|
||||
shrd->dbg_level_dev = val;
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(shrd->priv,
|
||||
"Not enough memory to generate traffic log\n");
|
||||
}
|
||||
return strnlen(buf, count);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
|
||||
show_debug_level, store_debug_level);
|
||||
|
||||
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
|
||||
static ssize_t show_temperature(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_shared *shrd = dev_get_drvdata(d);
|
||||
struct iwl_priv *priv = shrd->priv;
|
||||
|
||||
if (!iwl_is_alive(priv->shrd))
|
||||
return -EAGAIN;
|
||||
|
||||
return sprintf(buf, "%d\n", priv->temperature);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
|
||||
|
||||
static ssize_t show_tx_power(struct device *d,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
return sprintf(buf, "off\n");
|
||||
else
|
||||
return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
|
||||
}
|
||||
|
||||
static ssize_t store_tx_power(struct device *d,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct iwl_priv *priv = dev_get_drvdata(d);
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(buf, 10, &val);
|
||||
if (ret)
|
||||
IWL_INFO(priv, "%s is not in decimal form.\n", buf);
|
||||
else {
|
||||
ret = iwl_set_tx_power(priv, val, false);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed setting tx power (0x%d).\n",
|
||||
ret);
|
||||
else
|
||||
ret = count;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
|
||||
|
||||
static struct attribute *iwl_sysfs_entries[] = {
|
||||
&dev_attr_temperature.attr,
|
||||
&dev_attr_tx_power.attr,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
&dev_attr_debug_level.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group iwl_attribute_group = {
|
||||
.name = NULL, /* put in device directory */
|
||||
.attrs = iwl_sysfs_entries,
|
||||
};
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* uCode download functions
|
||||
@ -1259,13 +1143,6 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
||||
if (err)
|
||||
IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
|
||||
|
||||
err = sysfs_create_group(&(priv->bus->dev->kobj),
|
||||
&iwl_attribute_group);
|
||||
if (err) {
|
||||
IWL_ERR(priv, "failed to create sysfs device attributes\n");
|
||||
goto out_unbind;
|
||||
}
|
||||
|
||||
/* We have our copies now, allow OS release its copies */
|
||||
release_firmware(ucode_raw);
|
||||
complete(&priv->firmware_loading_complete);
|
||||
@ -1519,9 +1396,11 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
if (!exit_pending)
|
||||
clear_bit(STATUS_EXIT_PENDING, &priv->shrd->status);
|
||||
|
||||
if (priv->shrd->mac80211_registered)
|
||||
if (priv->mac80211_registered)
|
||||
ieee80211_stop_queues(priv->hw);
|
||||
|
||||
iwl_trans_stop_device(trans(priv));
|
||||
|
||||
/* Clear out all status bits but a few that are stable across reset */
|
||||
priv->shrd->status &=
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status) <<
|
||||
@ -1533,8 +1412,6 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
test_bit(STATUS_EXIT_PENDING, &priv->shrd->status) <<
|
||||
STATUS_EXIT_PENDING;
|
||||
|
||||
iwl_trans_stop_device(trans(priv));
|
||||
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = NULL;
|
||||
}
|
||||
@ -1868,7 +1745,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
|
||||
IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
priv->shrd->mac80211_registered = 1;
|
||||
priv->mac80211_registered = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1924,7 +1801,7 @@ static void iwlagn_mac_stop(struct ieee80211_hw *hw)
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int iwlagn_send_patterns(struct iwl_priv *priv,
|
||||
struct cfg80211_wowlan *wowlan)
|
||||
{
|
||||
@ -1999,7 +1876,7 @@ struct wowlan_key_data {
|
||||
bool error, use_rsc_tsc, use_tkip;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static void iwlagn_convert_p1k(u16 *p1k, __le16 *out)
|
||||
{
|
||||
int i;
|
||||
@ -2636,7 +2513,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
|
||||
sta->addr);
|
||||
sta_priv->common.sta_id = IWL_INVALID_STATION;
|
||||
sta_priv->sta_id = IWL_INVALID_STATION;
|
||||
|
||||
atomic_set(&sta_priv->pending_frames, 0);
|
||||
if (vif->type == NL80211_IFTYPE_AP)
|
||||
@ -2652,7 +2529,7 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
sta_priv->common.sta_id = sta_id;
|
||||
sta_priv->sta_id = sta_id;
|
||||
|
||||
/* Initialize rate scaling */
|
||||
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
|
||||
@ -2893,15 +2770,6 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
|
||||
/*
|
||||
* TODO: Remove this hack! Firmware needs to be updated
|
||||
* to allow longer off-channel periods in scanning for
|
||||
* this use case, based on a flag (and we'll need an API
|
||||
* flag in the firmware when it has that).
|
||||
*/
|
||||
if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80)
|
||||
duration = 80;
|
||||
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->shrd->status)) {
|
||||
err = -EBUSY;
|
||||
goto out;
|
||||
@ -2910,6 +2778,7 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
|
||||
priv->hw_roc_channel = channel;
|
||||
priv->hw_roc_chantype = channel_type;
|
||||
priv->hw_roc_duration = duration;
|
||||
priv->hw_roc_start_notified = false;
|
||||
cancel_delayed_work(&priv->hw_roc_disable_work);
|
||||
|
||||
if (!ctx->is_active) {
|
||||
@ -3208,7 +3077,7 @@ struct ieee80211_ops iwlagn_hw_ops = {
|
||||
.tx = iwlagn_mac_tx,
|
||||
.start = iwlagn_mac_start,
|
||||
.stop = iwlagn_mac_stop,
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.suspend = iwlagn_mac_suspend,
|
||||
.resume = iwlagn_mac_resume,
|
||||
#endif
|
||||
@ -3314,10 +3183,9 @@ int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
|
||||
priv = hw->priv;
|
||||
priv->bus = bus;
|
||||
priv->shrd = &priv->_shrd;
|
||||
bus->shrd = priv->shrd;
|
||||
priv->shrd->bus = bus;
|
||||
priv->shrd->priv = priv;
|
||||
priv->shrd->hw = hw;
|
||||
bus_set_drv_data(priv->bus, priv->shrd);
|
||||
|
||||
priv->shrd->trans = trans_ops->alloc(priv->shrd);
|
||||
if (priv->shrd->trans == NULL) {
|
||||
@ -3480,8 +3348,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
|
||||
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
|
||||
|
||||
iwl_dbgfs_unregister(priv);
|
||||
sysfs_remove_group(&priv->bus->dev->kobj,
|
||||
&iwl_attribute_group);
|
||||
|
||||
/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
|
||||
* to be called and iwl_down since we are removing the device
|
||||
@ -3492,9 +3358,9 @@ void __devexit iwl_remove(struct iwl_priv * priv)
|
||||
iwl_testmode_cleanup(priv);
|
||||
iwl_leds_exit(priv);
|
||||
|
||||
if (priv->shrd->mac80211_registered) {
|
||||
if (priv->mac80211_registered) {
|
||||
ieee80211_unregister_hw(priv->hw);
|
||||
priv->shrd->mac80211_registered = 0;
|
||||
priv->mac80211_registered = 0;
|
||||
}
|
||||
|
||||
iwl_tt_exit(priv);
|
||||
@ -3518,8 +3384,6 @@ void __devexit iwl_remove(struct iwl_priv * priv)
|
||||
|
||||
iwl_trans_free(trans(priv));
|
||||
|
||||
bus_set_drv_data(priv->bus, NULL);
|
||||
|
||||
iwl_uninit_drv(priv);
|
||||
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
@ -88,8 +88,9 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
u32 changes);
|
||||
|
||||
/* uCode */
|
||||
void iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
int iwlagn_rx_calib_result(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
int iwlagn_send_bt_env(struct iwl_priv *priv, u8 action, u8 type);
|
||||
void iwlagn_send_prio_tbl(struct iwl_priv *priv);
|
||||
int iwlagn_run_init_ucode(struct iwl_priv *priv);
|
||||
@ -116,9 +117,11 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
|
||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
||||
int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
static inline u32 iwl_tx_status_to_mac80211(u32 status)
|
||||
{
|
||||
@ -146,7 +149,6 @@ static inline bool iwl_is_tx_success(u32 status)
|
||||
u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
|
||||
|
||||
/* scan */
|
||||
int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void iwlagn_post_scan(struct iwl_priv *priv);
|
||||
void iwlagn_disable_roc(struct iwl_priv *priv);
|
||||
|
||||
@ -156,8 +158,9 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
|
||||
/* bt coex */
|
||||
void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
|
||||
void iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv);
|
||||
void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv);
|
||||
void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv);
|
||||
|
@ -63,19 +63,65 @@
|
||||
#ifndef __iwl_bus_h__
|
||||
#define __iwl_bus_h__
|
||||
|
||||
/*This file includes the declaration that are exported from the bus layer */
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
/**
|
||||
* DOC: Bus layer - role and goal
|
||||
*
|
||||
* iwl-bus.h defines the API to the bus layer of the iwlwifi driver.
|
||||
* The bus layer is responsible for doing very basic bus operations that are
|
||||
* listed in the iwl_bus_ops structure.
|
||||
* The bus layer registers to the bus driver, advertises the supported HW and
|
||||
* gets notifications about enumeration, suspend, resume.
|
||||
* For the moment, the bus layer is not a linux kernel module as itself, and
|
||||
* the module_init function of the driver must call the bus specific
|
||||
* registration functions. These functions are listed at the end of this file.
|
||||
* For the moment, there is only one implementation of this interface: PCI-e.
|
||||
* This implementation is iwl-pci.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: encapsulation and type safety
|
||||
*
|
||||
* The iwl_bus describes the data that is shared amongst all the bus layer
|
||||
* implementations. This data is visible to other layers. Data in the bus
|
||||
* specific area is not visible outside the bus specific implementation.
|
||||
* iwl_bus holds a pointer to iwl_shared which holds pointer to all the other
|
||||
* layers of the driver (iwl_priv, iwl_trans). In fact, this is the way to go
|
||||
* when the transport layer needs to call a function of another layer.
|
||||
*
|
||||
* In order to achieve encapsulation, iwl_priv cannot be dereferenced from the
|
||||
* bus layer. Type safety is still kept since functions that gets iwl_priv gets
|
||||
* a typed pointer (as opposed to void *).
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: probe flow
|
||||
*
|
||||
* The module_init calls the bus specific registration function. The
|
||||
* registration to the bus layer will trigger an enumeration of the bus which
|
||||
* will call the bus specific probe function.
|
||||
* The first thing this function must do is to allocate the memory needed by
|
||||
* iwl_bus + the bus_specific data.
|
||||
* Once the bus specific probe function has configured the hardware, it
|
||||
* chooses the appropriate transport layer and calls iwl_probe that will run
|
||||
* the bus independent probe flow.
|
||||
*
|
||||
* Note: The bus specific code must set the following data in iwl_bus before it
|
||||
* calls iwl_probe:
|
||||
* * bus->dev
|
||||
* * bus->irq
|
||||
* * bus->ops
|
||||
*/
|
||||
|
||||
struct iwl_shared;
|
||||
struct iwl_bus;
|
||||
|
||||
/**
|
||||
* struct iwl_bus_ops - bus specific operations
|
||||
* @get_pm_support: must returns true if the bus can go to sleep
|
||||
* @apm_config: will be called during the config of the APM configuration
|
||||
* @set_drv_data: set the shared data pointer to the bus layer
|
||||
* @apm_config: will be called during the config of the APM
|
||||
* @get_hw_id: prints the hw_id in the provided buffer
|
||||
* @write8: write a byte to register at offset ofs
|
||||
* @write32: write a dword to register at offset ofs
|
||||
@ -84,7 +130,6 @@ struct iwl_bus;
|
||||
struct iwl_bus_ops {
|
||||
bool (*get_pm_support)(struct iwl_bus *bus);
|
||||
void (*apm_config)(struct iwl_bus *bus);
|
||||
void (*set_drv_data)(struct iwl_bus *bus, struct iwl_shared *shrd);
|
||||
void (*get_hw_id)(struct iwl_bus *bus, char buf[], int buf_len);
|
||||
void (*write8)(struct iwl_bus *bus, u32 ofs, u8 val);
|
||||
void (*write32)(struct iwl_bus *bus, u32 ofs, u32 val);
|
||||
@ -93,14 +138,18 @@ struct iwl_bus_ops {
|
||||
|
||||
/**
|
||||
* struct iwl_bus - bus common data
|
||||
* @dev - pointer to struct device * that represent the device
|
||||
*
|
||||
* This data is common to all bus layer implementations.
|
||||
*
|
||||
* @dev - pointer to struct device * that represents the device
|
||||
* @ops - pointer to iwl_bus_ops
|
||||
* @shrd - pointer to iwl_shared which holds shared data from the upper layer
|
||||
* NB: for the time being this needs to be set by the upper layer since
|
||||
* it allocates the shared data
|
||||
* @irq - the irq number for the device
|
||||
* @reg_lock - protect hw register access
|
||||
*/
|
||||
struct iwl_bus {
|
||||
/* Common data to all buses */
|
||||
struct device *dev;
|
||||
const struct iwl_bus_ops *ops;
|
||||
struct iwl_shared *shrd;
|
||||
@ -123,12 +172,6 @@ static inline void bus_apm_config(struct iwl_bus *bus)
|
||||
bus->ops->apm_config(bus);
|
||||
}
|
||||
|
||||
static inline void bus_set_drv_data(struct iwl_bus *bus,
|
||||
struct iwl_shared *shrd)
|
||||
{
|
||||
bus->ops->set_drv_data(bus, shrd);
|
||||
}
|
||||
|
||||
static inline void bus_get_hw_id(struct iwl_bus *bus, char buf[], int buf_len)
|
||||
{
|
||||
bus->ops->get_hw_id(bus, buf, buf_len);
|
||||
@ -149,6 +192,9 @@ static inline u32 bus_read32(struct iwl_bus *bus, u32 ofs)
|
||||
return bus->ops->read32(bus, ofs);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Bus layer registration functions
|
||||
******************************************************/
|
||||
int __must_check iwl_pci_register_driver(void);
|
||||
void iwl_pci_unregister_driver(void);
|
||||
|
||||
|
@ -64,11 +64,10 @@
|
||||
#define __iwl_pci_h__
|
||||
|
||||
|
||||
/* This file includes the declaration that are internal to the PCI
|
||||
* implementation of the bus layer
|
||||
/*
|
||||
* This file declares the config structures for all devices.
|
||||
*/
|
||||
|
||||
/* configuration for the _agn devices */
|
||||
extern struct iwl_cfg iwl5300_agn_cfg;
|
||||
extern struct iwl_cfg iwl5100_agn_cfg;
|
||||
extern struct iwl_cfg iwl5350_agn_cfg;
|
@ -3263,6 +3263,14 @@ struct iwl_calib_temperature_offset_cmd {
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
struct iwl_calib_temperature_offset_v2_cmd {
|
||||
struct iwl_calib_hdr hdr;
|
||||
__le16 radio_sensor_offset_high;
|
||||
__le16 radio_sensor_offset_low;
|
||||
__le16 burntVoltageRef;
|
||||
__le16 reserved;
|
||||
} __packed;
|
||||
|
||||
/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
|
||||
struct iwl_calib_chain_noise_reset_cmd {
|
||||
struct iwl_calib_hdr hdr;
|
||||
|
@ -125,12 +125,12 @@ int iwl_init_geos(struct iwl_priv *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
channels = kzalloc(sizeof(struct ieee80211_channel) *
|
||||
priv->channel_count, GFP_KERNEL);
|
||||
channels = kcalloc(priv->channel_count,
|
||||
sizeof(struct ieee80211_channel), GFP_KERNEL);
|
||||
if (!channels)
|
||||
return -ENOMEM;
|
||||
|
||||
rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
|
||||
rates = kcalloc(IWL_RATE_COUNT_LEGACY, sizeof(struct ieee80211_rate),
|
||||
GFP_KERNEL);
|
||||
if (!rates) {
|
||||
kfree(channels);
|
||||
@ -817,7 +817,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid)
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||
enum iwl_rxon_context_id ctxid)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[ctxid];
|
||||
struct iwl_rxon_cmd *rxon = &ctx->staging;
|
||||
@ -868,7 +869,7 @@ void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand)
|
||||
* commands by clearing the ready bit */
|
||||
clear_bit(STATUS_READY, &priv->shrd->status);
|
||||
|
||||
wake_up_interruptible(&priv->shrd->wait_command_queue);
|
||||
wake_up(&priv->shrd->wait_command_queue);
|
||||
|
||||
if (!ondemand) {
|
||||
/*
|
||||
@ -1327,7 +1328,13 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
|
||||
WARN_ON(ctx->vif != vif);
|
||||
if (WARN_ON(ctx->vif != vif)) {
|
||||
struct iwl_rxon_context *tmp;
|
||||
IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
|
||||
for_each_context(priv, tmp)
|
||||
IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
|
||||
tmp->ctxid, tmp, tmp->vif);
|
||||
}
|
||||
ctx->vif = NULL;
|
||||
|
||||
iwl_teardown_interface(priv, vif, false);
|
||||
@ -1802,13 +1809,12 @@ u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, u32 beacon_interval)
|
||||
return 0;
|
||||
|
||||
quot = (usec / interval) &
|
||||
(iwl_beacon_time_mask_high(priv,
|
||||
hw_params(priv).beacon_time_tsf_bits) >>
|
||||
hw_params(priv).beacon_time_tsf_bits);
|
||||
(iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >>
|
||||
IWLAGN_EXT_BEACON_TIME_POS);
|
||||
rem = (usec % interval) & iwl_beacon_time_mask_low(priv,
|
||||
hw_params(priv).beacon_time_tsf_bits);
|
||||
IWLAGN_EXT_BEACON_TIME_POS);
|
||||
|
||||
return (quot << hw_params(priv).beacon_time_tsf_bits) + rem;
|
||||
return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem;
|
||||
}
|
||||
|
||||
/* base is usually what we get from ucode with each received frame,
|
||||
@ -1818,22 +1824,22 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
|
||||
u32 addon, u32 beacon_interval)
|
||||
{
|
||||
u32 base_low = base & iwl_beacon_time_mask_low(priv,
|
||||
hw_params(priv).beacon_time_tsf_bits);
|
||||
IWLAGN_EXT_BEACON_TIME_POS);
|
||||
u32 addon_low = addon & iwl_beacon_time_mask_low(priv,
|
||||
hw_params(priv).beacon_time_tsf_bits);
|
||||
IWLAGN_EXT_BEACON_TIME_POS);
|
||||
u32 interval = beacon_interval * TIME_UNIT;
|
||||
u32 res = (base & iwl_beacon_time_mask_high(priv,
|
||||
hw_params(priv).beacon_time_tsf_bits)) +
|
||||
IWLAGN_EXT_BEACON_TIME_POS)) +
|
||||
(addon & iwl_beacon_time_mask_high(priv,
|
||||
hw_params(priv).beacon_time_tsf_bits));
|
||||
IWLAGN_EXT_BEACON_TIME_POS));
|
||||
|
||||
if (base_low > addon_low)
|
||||
res += base_low - addon_low;
|
||||
else if (base_low < addon_low) {
|
||||
res += interval + base_low - addon_low;
|
||||
res += (1 << hw_params(priv).beacon_time_tsf_bits);
|
||||
res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
|
||||
} else
|
||||
res += (1 << hw_params(priv).beacon_time_tsf_bits);
|
||||
res += (1 << IWLAGN_EXT_BEACON_TIME_POS);
|
||||
|
||||
return cpu_to_le32(res);
|
||||
}
|
||||
@ -1876,3 +1882,22 @@ void iwl_nic_config(struct iwl_priv *priv)
|
||||
priv->cfg->lib->nic_config(priv);
|
||||
|
||||
}
|
||||
|
||||
void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info;
|
||||
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
kmem_cache_free(priv->tx_cmd_pool, (info->driver_data[1]));
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac)
|
||||
{
|
||||
ieee80211_stop_queue(priv->hw, ac);
|
||||
}
|
||||
|
||||
void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac)
|
||||
{
|
||||
ieee80211_wake_queue(priv->hw, ac);
|
||||
}
|
||||
|
@ -108,7 +108,6 @@ struct iwl_lib_ops {
|
||||
* radio tuning when there is a high receiving plcp error rate
|
||||
* @chain_noise_scale: default chain noise scale used for gain computation
|
||||
* @wd_timeout: TX queues watchdog timeout
|
||||
* @temperature_kelvin: temperature report by uCode in kelvin
|
||||
* @max_event_log_size: size of event log buffer size for ucode event logging
|
||||
* @shadow_reg_enable: HW shadhow register bit
|
||||
* @no_idle_support: do not support idle mode
|
||||
@ -124,14 +123,12 @@ struct iwl_base_params {
|
||||
const u16 max_ll_items;
|
||||
const bool shadow_ram_support;
|
||||
u16 led_compensation;
|
||||
int chain_noise_num_beacons;
|
||||
bool adv_thermal_throttle;
|
||||
bool support_ct_kill_exit;
|
||||
const bool support_wimax_coexist;
|
||||
u8 plcp_delta_threshold;
|
||||
s32 chain_noise_scale;
|
||||
unsigned int wd_timeout;
|
||||
bool temperature_kelvin;
|
||||
u32 max_event_log_size;
|
||||
const bool shadow_reg_enable;
|
||||
const bool no_idle_support;
|
||||
@ -194,6 +191,7 @@ struct iwl_ht_params {
|
||||
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
|
||||
* @internal_wimax_coex: internal wifi/wimax combo device
|
||||
* @iq_invert: I/Q inversion
|
||||
* @temp_offset_v2: support v2 of temperature offset calibration
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt API version. The
|
||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||
@ -231,6 +229,7 @@ struct iwl_cfg {
|
||||
const bool rx_with_siso_diversity;
|
||||
const bool internal_wimax_coex;
|
||||
const bool iq_invert;
|
||||
const bool temp_offset_v2;
|
||||
};
|
||||
|
||||
/***************************
|
||||
@ -319,7 +318,7 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
|
||||
******************************************************************************/
|
||||
void iwl_init_scan_params(struct iwl_priv *priv);
|
||||
int iwl_scan_cancel(struct iwl_priv *priv);
|
||||
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
||||
void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
||||
void iwl_force_scan_end(struct iwl_priv *priv);
|
||||
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
@ -329,12 +328,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external);
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
const u8 *ta, const u8 *ie, int ie_len, int left);
|
||||
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
|
||||
u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
u8 n_probes);
|
||||
u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
|
||||
void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
|
||||
int __must_check iwl_scan_initiate(struct iwl_priv *priv,
|
||||
|
@ -64,6 +64,14 @@
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
#define DEBUGFS_ADD_U32(name, parent, ptr, mode) do { \
|
||||
struct dentry *__tmp; \
|
||||
__tmp = debugfs_create_u32(#name, mode, \
|
||||
parent, ptr); \
|
||||
if (IS_ERR(__tmp) || !__tmp) \
|
||||
goto err; \
|
||||
} while (0)
|
||||
|
||||
/* file operation */
|
||||
#define DEBUGFS_READ_FUNC(name) \
|
||||
static ssize_t iwl_dbgfs_##name##_read(struct file *file, \
|
||||
@ -707,6 +715,20 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_temperature_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
char buf[8];
|
||||
int pos = 0;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%d\n", priv->temperature);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@ -801,6 +823,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(rx_handlers);
|
||||
DEBUGFS_READ_FILE_OPS(qos);
|
||||
DEBUGFS_READ_FILE_OPS(thermal_throttling);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
|
||||
DEBUGFS_READ_FILE_OPS(temperature);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
|
||||
DEBUGFS_READ_FILE_OPS(current_sleep_command);
|
||||
|
||||
@ -2229,8 +2252,8 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
|
||||
|
||||
static ssize_t iwl_dbgfs_force_reset_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int i, pos = 0;
|
||||
char buf[300];
|
||||
@ -2309,8 +2332,8 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file,
|
||||
|
||||
static ssize_t iwl_dbgfs_wd_timeout_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
char buf[8];
|
||||
int buf_size;
|
||||
@ -2445,6 +2468,52 @@ DEBUGFS_READ_FILE_OPS(bt_traffic);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(protection_mode);
|
||||
DEBUGFS_READ_FILE_OPS(reply_tx_error);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
static ssize_t iwl_dbgfs_debug_level_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
struct iwl_shared *shrd = priv->shrd;
|
||||
char buf[11];
|
||||
int len;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "0x%.8x",
|
||||
iwl_get_debug_level(shrd));
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_debug_level_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
struct iwl_shared *shrd = priv->shrd;
|
||||
char buf[11];
|
||||
unsigned long val;
|
||||
int ret;
|
||||
|
||||
if (count > sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (copy_from_user(buf, user_buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
ret = strict_strtoul(buf, 0, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
shrd->dbg_level_dev = val;
|
||||
if (iwl_alloc_traffic_mem(priv))
|
||||
IWL_ERR(priv, "Not enough memory to generate traffic log\n");
|
||||
|
||||
return count;
|
||||
}
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(debug_level);
|
||||
#endif /* CONFIG_IWLWIFI_DEBUG */
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
*
|
||||
@ -2482,6 +2551,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(temperature, dir_data, S_IRUSR);
|
||||
|
||||
DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
|
||||
@ -2496,7 +2567,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(txfifo_flush, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(protection_mode, dir_debug, S_IWUSR | 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);
|
||||
@ -2507,6 +2577,10 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
|
||||
if (iwl_advanced_bt_coexist(priv))
|
||||
DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
DEBUGFS_ADD_FILE(debug_level, dir_debug, S_IRUSR | S_IWUSR);
|
||||
#endif
|
||||
|
||||
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
|
||||
&priv->disable_sens_cal);
|
||||
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
|
||||
@ -2534,6 +2608,3 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
||||
debugfs_remove_recursive(priv->debugfs_dir);
|
||||
priv->debugfs_dir = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -202,11 +202,6 @@ struct iwl_station_entry {
|
||||
struct iwl_link_quality_cmd *lq;
|
||||
};
|
||||
|
||||
struct iwl_station_priv_common {
|
||||
struct iwl_rxon_context *ctx;
|
||||
u8 sta_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* iwl_station_priv: Driver's private station information
|
||||
*
|
||||
@ -215,12 +210,13 @@ struct iwl_station_priv_common {
|
||||
* space.
|
||||
*/
|
||||
struct iwl_station_priv {
|
||||
struct iwl_station_priv_common common;
|
||||
struct iwl_rxon_context *ctx;
|
||||
struct iwl_lq_sta lq_sta;
|
||||
atomic_t pending_frames;
|
||||
bool client;
|
||||
bool asleep;
|
||||
u8 max_agg_bufsize;
|
||||
u8 sta_id;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -845,8 +841,9 @@ struct iwl_priv {
|
||||
|
||||
void (*pre_rx_handler)(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
int (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
|
||||
|
||||
@ -880,7 +877,7 @@ struct iwl_priv {
|
||||
u8 channel_count; /* # of channels */
|
||||
|
||||
/* thermal calibration */
|
||||
s32 temperature; /* degrees Kelvin */
|
||||
s32 temperature; /* Celsius */
|
||||
s32 last_temperature;
|
||||
|
||||
/* init calibration results */
|
||||
@ -958,6 +955,8 @@ struct iwl_priv {
|
||||
struct iwl_station_entry stations[IWLAGN_STATION_COUNT];
|
||||
unsigned long ucode_key_table;
|
||||
|
||||
u8 mac80211_registered;
|
||||
|
||||
/* Indication if ieee80211_ops->open has been called */
|
||||
u8 is_open;
|
||||
|
||||
@ -1031,7 +1030,7 @@ struct iwl_priv {
|
||||
struct delayed_work hw_roc_disable_work;
|
||||
enum nl80211_channel_type hw_roc_chantype;
|
||||
int hw_roc_duration;
|
||||
bool hw_roc_setup;
|
||||
bool hw_roc_setup, hw_roc_start_notified;
|
||||
|
||||
/* bt coex */
|
||||
u8 bt_enable_flag;
|
||||
|
@ -72,6 +72,7 @@
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-debug.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-io.h"
|
||||
|
||||
@ -138,7 +139,7 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* EEPROM related functions
|
||||
* generic NVM functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@ -214,6 +215,93 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
|
||||
{
|
||||
if (!priv->eeprom)
|
||||
return 0;
|
||||
return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
|
||||
}
|
||||
|
||||
int iwl_eeprom_check_version(struct iwl_priv *priv)
|
||||
{
|
||||
u16 eeprom_ver;
|
||||
u16 calib_ver;
|
||||
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
calib_ver = iwlagn_eeprom_calib_version(priv);
|
||||
|
||||
if (eeprom_ver < priv->cfg->eeprom_ver ||
|
||||
calib_ver < priv->cfg->eeprom_calib_ver)
|
||||
goto err;
|
||||
|
||||
IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
|
||||
eeprom_ver, calib_ver);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x "
|
||||
"CALIB=0x%x < 0x%x\n",
|
||||
eeprom_ver, priv->cfg->eeprom_ver,
|
||||
calib_ver, priv->cfg->eeprom_calib_ver);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
|
||||
int iwl_eeprom_check_sku(struct iwl_priv *priv)
|
||||
{
|
||||
u16 radio_cfg;
|
||||
|
||||
if (!priv->cfg->sku) {
|
||||
/* not using sku overwrite */
|
||||
priv->cfg->sku = iwl_eeprom_query16(priv, EEPROM_SKU_CAP);
|
||||
if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
||||
!priv->cfg->ht_params) {
|
||||
IWL_ERR(priv, "Invalid 11n configuration\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (!priv->cfg->sku) {
|
||||
IWL_ERR(priv, "Invalid device sku\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
IWL_INFO(priv, "Device SKU: 0X%x\n", priv->cfg->sku);
|
||||
|
||||
if (!priv->cfg->valid_tx_ant && !priv->cfg->valid_rx_ant) {
|
||||
/* not using .cfg overwrite */
|
||||
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
|
||||
priv->cfg->valid_tx_ant = EEPROM_RF_CFG_TX_ANT_MSK(radio_cfg);
|
||||
priv->cfg->valid_rx_ant = EEPROM_RF_CFG_RX_ANT_MSK(radio_cfg);
|
||||
if (!priv->cfg->valid_tx_ant || !priv->cfg->valid_rx_ant) {
|
||||
IWL_ERR(priv, "Invalid chain (0X%x, 0X%x)\n",
|
||||
priv->cfg->valid_tx_ant,
|
||||
priv->cfg->valid_rx_ant);
|
||||
return -EINVAL;
|
||||
}
|
||||
IWL_INFO(priv, "Valid Tx ant: 0X%x, Valid Rx ant: 0X%x\n",
|
||||
priv->cfg->valid_tx_ant, priv->cfg->valid_rx_ant);
|
||||
}
|
||||
/*
|
||||
* for some special cases,
|
||||
* EEPROM did not reflect the correct antenna setting
|
||||
* so overwrite the valid tx/rx antenna from .cfg
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
|
||||
{
|
||||
const u8 *addr = iwl_eeprom_query_addr(priv,
|
||||
EEPROM_MAC_ADDRESS);
|
||||
memcpy(mac, addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* OTP related functions
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode)
|
||||
{
|
||||
iwl_read32(bus(priv), CSR_OTP_GP_REG);
|
||||
@ -407,11 +495,152 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
|
||||
/******************************************************************************
|
||||
*
|
||||
* Tx Power related functions
|
||||
*
|
||||
******************************************************************************/
|
||||
/**
|
||||
* iwl_get_max_txpower_avg - get the highest tx power from all chains.
|
||||
* find the highest tx power from all chains for the channel
|
||||
*/
|
||||
static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
|
||||
int element, s8 *max_txpower_in_half_dbm)
|
||||
{
|
||||
if (!priv->eeprom)
|
||||
return 0;
|
||||
return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
|
||||
s8 max_txpower_avg = 0; /* (dBm) */
|
||||
|
||||
/* Take the highest tx power from any valid chains */
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) &&
|
||||
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_a_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) &&
|
||||
(enhanced_txpower[element].chain_b_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_b_max;
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) &&
|
||||
(enhanced_txpower[element].chain_c_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].chain_c_max;
|
||||
if (((priv->cfg->valid_tx_ant == ANT_AB) |
|
||||
(priv->cfg->valid_tx_ant == ANT_BC) |
|
||||
(priv->cfg->valid_tx_ant == ANT_AC)) &&
|
||||
(enhanced_txpower[element].mimo2_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo2_max;
|
||||
if ((priv->cfg->valid_tx_ant == ANT_ABC) &&
|
||||
(enhanced_txpower[element].mimo3_max > max_txpower_avg))
|
||||
max_txpower_avg = enhanced_txpower[element].mimo3_max;
|
||||
|
||||
/*
|
||||
* max. tx power in EEPROM is in 1/2 dBm format
|
||||
* convert from 1/2 dBm to dBm (round-up convert)
|
||||
* but we also do not want to loss 1/2 dBm resolution which
|
||||
* will impact performance
|
||||
*/
|
||||
*max_txpower_in_half_dbm = max_txpower_avg;
|
||||
return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
|
||||
}
|
||||
|
||||
static void
|
||||
iwl_eeprom_enh_txp_read_element(struct iwl_priv *priv,
|
||||
struct iwl_eeprom_enhanced_txpwr *txp,
|
||||
s8 max_txpower_avg)
|
||||
{
|
||||
int ch_idx;
|
||||
bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
|
||||
enum ieee80211_band band;
|
||||
|
||||
band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
|
||||
IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
|
||||
|
||||
for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
|
||||
struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
|
||||
|
||||
/* update matching channel or from common data only */
|
||||
if (txp->channel != 0 && ch_info->channel != txp->channel)
|
||||
continue;
|
||||
|
||||
/* update matching band only */
|
||||
if (band != ch_info->band)
|
||||
continue;
|
||||
|
||||
if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
|
||||
ch_info->max_power_avg = max_txpower_avg;
|
||||
ch_info->curr_txpow = max_txpower_avg;
|
||||
ch_info->scan_power = max_txpower_avg;
|
||||
}
|
||||
|
||||
if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
|
||||
ch_info->ht40_max_power_avg = max_txpower_avg;
|
||||
}
|
||||
}
|
||||
|
||||
#define EEPROM_TXP_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
|
||||
#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
|
||||
#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
|
||||
|
||||
#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
|
||||
? # x " " : "")
|
||||
|
||||
void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
|
||||
int idx, entries;
|
||||
__le16 *txp_len;
|
||||
s8 max_txp_avg, max_txp_avg_halfdbm;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
|
||||
|
||||
/* the length is in 16-bit words, but we want entries */
|
||||
txp_len = (__le16 *) iwl_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
|
||||
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
|
||||
|
||||
txp_array = (void *) iwl_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
|
||||
|
||||
for (idx = 0; idx < entries; idx++) {
|
||||
txp = &txp_array[idx];
|
||||
/* skip invalid entries */
|
||||
if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
|
||||
continue;
|
||||
|
||||
IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
|
||||
(txp->channel && (txp->flags &
|
||||
IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
|
||||
"Common " : (txp->channel) ?
|
||||
"Channel" : "Common",
|
||||
(txp->channel),
|
||||
TXP_CHECK_AND_PRINT(VALID),
|
||||
TXP_CHECK_AND_PRINT(BAND_52G),
|
||||
TXP_CHECK_AND_PRINT(OFDM),
|
||||
TXP_CHECK_AND_PRINT(40MHZ),
|
||||
TXP_CHECK_AND_PRINT(HT_AP),
|
||||
TXP_CHECK_AND_PRINT(RES1),
|
||||
TXP_CHECK_AND_PRINT(RES2),
|
||||
TXP_CHECK_AND_PRINT(COMMON_TYPE),
|
||||
txp->flags);
|
||||
IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
|
||||
"chain_B: 0X%02x chain_C: 0X%02x\n",
|
||||
txp->chain_a_max, txp->chain_b_max,
|
||||
txp->chain_c_max);
|
||||
IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
|
||||
"MIMO3: 0x%02x High 20_on_40: 0x%02x "
|
||||
"Low 20_on_40: 0x%02x\n",
|
||||
txp->mimo2_max, txp->mimo3_max,
|
||||
((txp->delta_20_in_40 & 0xf0) >> 4),
|
||||
(txp->delta_20_in_40 & 0x0f));
|
||||
|
||||
max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
|
||||
&max_txp_avg_halfdbm);
|
||||
|
||||
/*
|
||||
* Update the user limit values values to the highest
|
||||
* power supported by any channel
|
||||
*/
|
||||
if (max_txp_avg > priv->tx_power_user_lmt)
|
||||
priv->tx_power_user_lmt = max_txp_avg;
|
||||
if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
|
||||
priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
|
||||
|
||||
iwl_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -670,8 +899,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
|
||||
IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n",
|
||||
priv->channel_count);
|
||||
|
||||
priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
|
||||
priv->channel_count, GFP_KERNEL);
|
||||
priv->channel_info = kcalloc(priv->channel_count,
|
||||
sizeof(struct iwl_channel_info),
|
||||
GFP_KERNEL);
|
||||
if (!priv->channel_info) {
|
||||
IWL_ERR(priv, "Could not allocate channel_info\n");
|
||||
priv->channel_count = 0;
|
||||
|
@ -163,11 +163,19 @@ struct iwl_eeprom_enhanced_txpwr {
|
||||
} __packed;
|
||||
|
||||
/* calibration */
|
||||
struct iwl_eeprom_calib_hdr {
|
||||
u8 version;
|
||||
u8 pa_type;
|
||||
__le16 voltage;
|
||||
} __packed;
|
||||
|
||||
#define EEPROM_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
|
||||
#define EEPROM_XTAL ((2*0x128) | EEPROM_CALIB_ALL)
|
||||
|
||||
/* temperature */
|
||||
#define EEPROM_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
|
||||
#define EEPROM_KELVIN_TEMPERATURE ((2*0x12A) | EEPROM_CALIB_ALL)
|
||||
#define EEPROM_RAW_TEMPERATURE ((2*0x12B) | EEPROM_CALIB_ALL)
|
||||
|
||||
|
||||
/* agn links */
|
||||
#define EEPROM_LINK_HOST (2*0x64)
|
||||
|
@ -104,7 +104,6 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
|
||||
.len = { sizeof(struct iwl_led_cmd), },
|
||||
.data = { led_cmd, },
|
||||
.flags = CMD_ASYNC,
|
||||
.callback = NULL,
|
||||
};
|
||||
u32 reg;
|
||||
|
||||
|
@ -68,7 +68,7 @@
|
||||
#include "iwl-shared.h"
|
||||
#include "iwl-trans.h"
|
||||
#include "iwl-csr.h"
|
||||
#include "iwl-pci.h"
|
||||
#include "iwl-cfg.h"
|
||||
|
||||
/* PCI registers */
|
||||
#define PCI_CFG_RETRY_TIMEOUT 0x041
|
||||
@ -134,12 +134,6 @@ static void iwl_pci_apm_config(struct iwl_bus *bus)
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl_pci_set_drv_data(struct iwl_bus *bus, struct iwl_shared *shrd)
|
||||
{
|
||||
bus->shrd = shrd;
|
||||
pci_set_drvdata(IWL_BUS_GET_PCI_DEV(bus), shrd);
|
||||
}
|
||||
|
||||
static void iwl_pci_get_hw_id(struct iwl_bus *bus, char buf[],
|
||||
int buf_len)
|
||||
{
|
||||
@ -168,7 +162,6 @@ static u32 iwl_pci_read32(struct iwl_bus *bus, u32 ofs)
|
||||
static const struct iwl_bus_ops bus_ops_pci = {
|
||||
.get_pm_support = iwl_pci_is_pm_supported,
|
||||
.apm_config = iwl_pci_apm_config,
|
||||
.set_drv_data = iwl_pci_set_drv_data,
|
||||
.get_hw_id = iwl_pci_get_hw_id,
|
||||
.write8 = iwl_pci_write8,
|
||||
.write32 = iwl_pci_write32,
|
||||
@ -260,6 +253,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6005_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6005_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0xC020, iwl6005_2agn_sff_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0xC220, iwl6005_2agn_sff_cfg)},
|
||||
|
||||
/* 6x30 Series */
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl1030_bgn_cfg)},
|
||||
@ -392,6 +386,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
pci_bus = IWL_BUS_GET_PCI_BUS(bus);
|
||||
pci_bus->pci_dev = pdev;
|
||||
|
||||
pci_set_drvdata(pdev, bus);
|
||||
|
||||
/* W/A - seems to solve weird behavior. We need to remove this if we
|
||||
* don't want to stay in L1 all the time. This wastes a lot of power */
|
||||
pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
|
||||
@ -485,17 +481,18 @@ out_no_pci:
|
||||
|
||||
static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct iwl_shared *shrd = pci_get_drvdata(pdev);
|
||||
struct iwl_bus *bus = shrd->bus;
|
||||
struct iwl_bus *bus = pci_get_drvdata(pdev);
|
||||
struct iwl_pci_bus *pci_bus = IWL_BUS_GET_PCI_BUS(bus);
|
||||
struct pci_dev *pci_dev = IWL_BUS_GET_PCI_DEV(bus);
|
||||
struct iwl_shared *shrd = bus->shrd;
|
||||
|
||||
iwl_remove(shrd->priv);
|
||||
|
||||
pci_disable_msi(pci_bus->pci_dev);
|
||||
pci_iounmap(pci_bus->pci_dev, pci_bus->hw_base);
|
||||
pci_release_regions(pci_bus->pci_dev);
|
||||
pci_disable_device(pci_bus->pci_dev);
|
||||
pci_set_drvdata(pci_bus->pci_dev, NULL);
|
||||
pci_disable_msi(pci_dev);
|
||||
pci_iounmap(pci_dev, pci_bus->hw_base);
|
||||
pci_release_regions(pci_dev);
|
||||
pci_disable_device(pci_dev);
|
||||
pci_set_drvdata(pci_dev, NULL);
|
||||
|
||||
kfree(bus);
|
||||
}
|
||||
@ -505,7 +502,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
||||
static int iwl_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct iwl_shared *shrd = pci_get_drvdata(pdev);
|
||||
struct iwl_bus *bus = pci_get_drvdata(pdev);
|
||||
struct iwl_shared *shrd = bus->shrd;
|
||||
|
||||
/* Before you put code here, think about WoWLAN. You cannot check here
|
||||
* whether WoWLAN is enabled or not, and your code will run even if
|
||||
@ -518,7 +516,8 @@ static int iwl_pci_suspend(struct device *device)
|
||||
static int iwl_pci_resume(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct iwl_shared *shrd = pci_get_drvdata(pdev);
|
||||
struct iwl_bus *bus = pci_get_drvdata(pdev);
|
||||
struct iwl_shared *shrd = bus->shrd;
|
||||
|
||||
/* Before you put code here, think about WoWLAN. You cannot check here
|
||||
* whether WoWLAN is enabled or not, and your code will run even if
|
||||
|
@ -130,8 +130,9 @@ const char *get_cmd_string(u8 cmd)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
static void iwl_rx_reply_error(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_reply_error(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
@ -142,9 +143,11 @@ static void iwl_rx_reply_error(struct iwl_priv *priv,
|
||||
pkt->u.err_resp.cmd_id,
|
||||
le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num),
|
||||
le32_to_cpu(pkt->u.err_resp.error_info));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
|
||||
@ -156,7 +159,7 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
|
||||
|
||||
if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->shrd->status))
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
|
||||
rxon->channel = csa->channel;
|
||||
@ -169,11 +172,13 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
le16_to_cpu(csa->channel));
|
||||
iwl_chswitch_done(priv, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
|
||||
@ -181,15 +186,17 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
||||
if (!report->state) {
|
||||
IWL_DEBUG_11H(priv,
|
||||
"Spectrum Measure Notification: Start\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&priv->measure_report, report, sizeof(*report));
|
||||
priv->measurement_status |= MEASUREMENT_READY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -197,10 +204,12 @@ static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
|
||||
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
|
||||
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u32 __maybe_unused len =
|
||||
@ -209,10 +218,12 @@ static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
||||
"notification for %s:\n", len,
|
||||
get_cmd_string(pkt->hdr.cmd));
|
||||
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_rx_beacon_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_beacon_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
|
||||
@ -233,6 +244,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
|
||||
|
||||
if (!test_bit(STATUS_EXIT_PENDING, &priv->shrd->status))
|
||||
queue_work(priv->shrd->workqueue, &priv->beacon_update);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
|
||||
@ -475,8 +487,9 @@ iwl_accumulative_statistics(struct iwl_priv *priv,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
unsigned long stamp = jiffies;
|
||||
const int reg_recalib_period = 60;
|
||||
@ -530,7 +543,7 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
WARN_ONCE(1, "len %d doesn't match BT (%zu) or normal (%zu)\n",
|
||||
len, sizeof(struct iwl_bt_notif_statistics),
|
||||
sizeof(struct iwl_notif_statistics));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
change = common->temperature != priv->statistics.common.temperature ||
|
||||
@ -573,10 +586,12 @@ static void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
}
|
||||
if (priv->cfg->lib->temperature && change)
|
||||
priv->cfg->lib->temperature(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_rx_reply_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_reply_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
@ -591,13 +606,15 @@ static void iwl_rx_reply_statistics(struct iwl_priv *priv,
|
||||
#endif
|
||||
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
|
||||
}
|
||||
iwl_rx_statistics(priv, rxb);
|
||||
iwl_rx_statistics(priv, rxb, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Handle notification from uCode that card's power state is changing
|
||||
* due to software, hardware, or critical temperature RFKILL */
|
||||
static void iwl_rx_card_state_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_card_state_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
|
||||
@ -644,11 +661,13 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->shrd->status));
|
||||
else
|
||||
wake_up_interruptible(&priv->shrd->wait_command_queue);
|
||||
wake_up(&priv->shrd->wait_command_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -666,18 +685,21 @@ static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
|
||||
if (!test_bit(STATUS_SCANNING, &priv->shrd->status))
|
||||
iwl_init_sensitivity(priv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
|
||||
* This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
|
||||
static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_reply_rx_phy(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
priv->last_phy_res_valid = true;
|
||||
memcpy(&priv->last_phy_res, pkt->u.raw,
|
||||
sizeof(struct iwl_rx_phy_res));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -892,8 +914,9 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
|
||||
|
||||
/* Called for REPLY_RX (legacy ABG frames), or
|
||||
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
|
||||
static void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct ieee80211_hdr *header;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
@ -926,7 +949,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
} else {
|
||||
if (!priv->last_phy_res_valid) {
|
||||
IWL_ERR(priv, "MPDU frame without cached PHY data\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
phy_res = &priv->last_phy_res;
|
||||
amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
|
||||
@ -940,14 +963,14 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
|
||||
IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
|
||||
phy_res->cfg_phy_cnt);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
|
||||
!(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
|
||||
IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
|
||||
le32_to_cpu(rx_pkt_status));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This will be used in several places later */
|
||||
@ -1008,6 +1031,7 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
|
||||
iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
|
||||
rxb, &rx_status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1018,7 +1042,8 @@ static void iwl_rx_reply_rx(struct iwl_priv *priv,
|
||||
*/
|
||||
void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
||||
{
|
||||
void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
||||
int (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
handlers = priv->rx_handlers;
|
||||
|
||||
@ -1028,6 +1053,7 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
||||
handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
|
||||
handlers[PM_DEBUG_STATISTIC_NOTIFIC] = iwl_rx_pm_debug_statistics_notif;
|
||||
handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
|
||||
handlers[REPLY_ADD_STA] = iwl_add_sta_callback;
|
||||
|
||||
/*
|
||||
* The same handler is used for both the REPLY to a discrete
|
||||
@ -1065,9 +1091,11 @@ void iwl_setup_rx_handlers(struct iwl_priv *priv)
|
||||
|
||||
}
|
||||
|
||||
void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
int err = 0;
|
||||
|
||||
/*
|
||||
* Do the notification wait before RX handlers so
|
||||
@ -1102,11 +1130,12 @@ void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
* rx_handlers table. See iwl_setup_rx_handlers() */
|
||||
if (priv->rx_handlers[pkt->hdr.cmd]) {
|
||||
priv->rx_handlers_stats[pkt->hdr.cmd]++;
|
||||
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
|
||||
err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd);
|
||||
} else {
|
||||
/* No handling needed */
|
||||
IWL_DEBUG_RX(priv,
|
||||
"No handler needed for %s, 0x%02x\n",
|
||||
get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -114,6 +114,65 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
|
||||
priv->scan_request = NULL;
|
||||
}
|
||||
|
||||
static void iwl_process_scan_complete(struct iwl_priv *priv)
|
||||
{
|
||||
bool aborted;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
|
||||
if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Completed scan.\n");
|
||||
|
||||
cancel_delayed_work(&priv->scan_check);
|
||||
|
||||
aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
|
||||
if (aborted)
|
||||
IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
|
||||
|
||||
if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
|
||||
goto out_settings;
|
||||
}
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC) {
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
priv->hw_roc_channel = NULL;
|
||||
schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
|
||||
}
|
||||
|
||||
if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
|
||||
int err;
|
||||
|
||||
/* Check if mac80211 requested scan during our internal scan */
|
||||
if (priv->scan_request == NULL)
|
||||
goto out_complete;
|
||||
|
||||
/* If so request a new scan */
|
||||
err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
|
||||
priv->scan_request->channels[0]->band);
|
||||
if (err) {
|
||||
IWL_DEBUG_SCAN(priv,
|
||||
"failed to initiate pending scan: %d\n", err);
|
||||
aborted = true;
|
||||
goto out_complete;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
out_complete:
|
||||
iwl_complete_scan(priv, aborted);
|
||||
|
||||
out_settings:
|
||||
/* Can we still talk to firmware ? */
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
return;
|
||||
|
||||
iwlagn_post_scan(priv);
|
||||
}
|
||||
|
||||
void iwl_force_scan_end(struct iwl_priv *priv)
|
||||
{
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
@ -127,6 +186,7 @@ void iwl_force_scan_end(struct iwl_priv *priv)
|
||||
clear_bit(STATUS_SCANNING, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
|
||||
iwl_complete_scan(priv, true);
|
||||
}
|
||||
|
||||
@ -169,7 +229,7 @@ int iwl_scan_cancel(struct iwl_priv *priv)
|
||||
* @ms: amount of time to wait (in milliseconds) for scan to abort
|
||||
*
|
||||
*/
|
||||
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
|
||||
void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
|
||||
{
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(ms);
|
||||
|
||||
@ -181,16 +241,30 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
|
||||
|
||||
while (time_before_eq(jiffies, timeout)) {
|
||||
if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status))
|
||||
break;
|
||||
goto finished;
|
||||
msleep(20);
|
||||
}
|
||||
|
||||
return test_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
return;
|
||||
|
||||
finished:
|
||||
/*
|
||||
* Now STATUS_SCAN_HW is clear. This means that the
|
||||
* device finished, but the background work is going
|
||||
* to execute at best as soon as we release the mutex.
|
||||
* Since we need to be able to issue a new scan right
|
||||
* after this function returns, run the complete here.
|
||||
* The STATUS_SCAN_COMPLETE bit will then be cleared
|
||||
* and prevent the background work from "completing"
|
||||
* a possible new scan.
|
||||
*/
|
||||
iwl_process_scan_complete(priv);
|
||||
}
|
||||
|
||||
/* Service response to REPLY_SCAN_CMD (0x80) */
|
||||
static void iwl_rx_reply_scan(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_reply_scan(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -199,11 +273,13 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Service SCAN_START_NOTIFICATION (0x82) */
|
||||
static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_scan_start_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scanstart_notification *notif =
|
||||
@ -218,13 +294,19 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
|
||||
le32_to_cpu(notif->tsf_low),
|
||||
notif->status, notif->beacon_timer);
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC)
|
||||
if (priv->scan_type == IWL_SCAN_ROC &&
|
||||
!priv->hw_roc_start_notified) {
|
||||
ieee80211_ready_on_channel(priv->hw);
|
||||
priv->hw_roc_start_notified = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
|
||||
static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_scan_results_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
@ -233,20 +315,24 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan ch.res: "
|
||||
"%d [802.11%s] "
|
||||
"probe status: %u:%u "
|
||||
"(TSF: 0x%08X:%08X) - %d "
|
||||
"elapsed=%lu usec\n",
|
||||
notif->channel,
|
||||
notif->band ? "bg" : "a",
|
||||
notif->probe_status, notif->num_probe_not_sent,
|
||||
le32_to_cpu(notif->tsf_high),
|
||||
le32_to_cpu(notif->tsf_low),
|
||||
le32_to_cpu(notif->statistics[0]),
|
||||
le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
|
||||
static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
|
||||
@ -256,13 +342,20 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
||||
scan_notif->tsf_low,
|
||||
scan_notif->tsf_high, scan_notif->status);
|
||||
|
||||
/* The HW is no longer scanning */
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
|
||||
(priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
|
||||
jiffies_to_msecs(jiffies - priv->scan_start));
|
||||
|
||||
/*
|
||||
* When aborting, we run the scan completed background work inline
|
||||
* and the background work must then do nothing. The SCAN_COMPLETE
|
||||
* bit helps implement that logic and thus needs to be set before
|
||||
* queueing the work. Also, since the scan abort waits for SCAN_HW
|
||||
* to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW
|
||||
* to avoid a race there.
|
||||
*/
|
||||
set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
queue_work(priv->shrd->workqueue, &priv->scan_completed);
|
||||
|
||||
if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
|
||||
@ -286,6 +379,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
||||
queue_work(priv->shrd->workqueue,
|
||||
&priv->bt_traffic_change_work);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
|
||||
@ -299,9 +393,8 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
|
||||
iwl_rx_scan_complete_notif;
|
||||
}
|
||||
|
||||
inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
u8 n_probes)
|
||||
static u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band, u8 n_probes)
|
||||
{
|
||||
if (band == IEEE80211_BAND_5GHZ)
|
||||
return IWL_ACTIVE_DWELL_TIME_52 +
|
||||
@ -311,35 +404,481 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
|
||||
IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
|
||||
}
|
||||
|
||||
u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif)
|
||||
static u16 iwl_limit_dwell(struct iwl_priv *priv, u16 dwell_time)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
/*
|
||||
* If we're associated, we clamp the dwell time 98%
|
||||
* of the smallest beacon interval (minus 2 * channel
|
||||
* tune time)
|
||||
*/
|
||||
for_each_context(priv, ctx) {
|
||||
u16 value;
|
||||
|
||||
if (!iwl_is_associated_ctx(ctx))
|
||||
continue;
|
||||
value = ctx->beacon_int;
|
||||
if (!value)
|
||||
value = IWL_PASSIVE_DWELL_BASE;
|
||||
value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
|
||||
dwell_time = min(value, dwell_time);
|
||||
}
|
||||
|
||||
return dwell_time;
|
||||
}
|
||||
|
||||
static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band)
|
||||
{
|
||||
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
|
||||
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
|
||||
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
|
||||
|
||||
if (iwl_is_any_associated(priv)) {
|
||||
/*
|
||||
* If we're associated, we clamp the maximum passive
|
||||
* dwell time to be 98% of the smallest beacon interval
|
||||
* (minus 2 * channel tune time)
|
||||
*/
|
||||
for_each_context(priv, ctx) {
|
||||
u16 value;
|
||||
return iwl_limit_dwell(priv, passive);
|
||||
}
|
||||
|
||||
if (!iwl_is_associated_ctx(ctx))
|
||||
continue;
|
||||
value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
|
||||
if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
|
||||
value = IWL_PASSIVE_DWELL_BASE;
|
||||
value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
|
||||
passive = min(value, passive);
|
||||
}
|
||||
static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
u16 passive_dwell = 0;
|
||||
u16 active_dwell = 0;
|
||||
int added = 0;
|
||||
u16 channel = 0;
|
||||
|
||||
sband = iwl_get_hw_mode(priv, band);
|
||||
if (!sband) {
|
||||
IWL_ERR(priv, "invalid band\n");
|
||||
return added;
|
||||
}
|
||||
|
||||
return passive;
|
||||
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;
|
||||
|
||||
channel = iwl_get_single_channel_number(priv, band);
|
||||
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,
|
||||
struct ieee80211_vif *vif,
|
||||
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 = chan->hw_value;
|
||||
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;
|
||||
}
|
||||
|
||||
static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_SCAN_CMD,
|
||||
.len = { sizeof(struct iwl_scan_cmd), },
|
||||
.flags = CMD_SYNC,
|
||||
};
|
||||
struct iwl_scan_cmd *scan;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
u32 rate_flags = 0;
|
||||
u16 cmd_len;
|
||||
u16 rx_chain = 0;
|
||||
enum ieee80211_band band;
|
||||
u8 n_probes = 0;
|
||||
u8 rx_ant = hw_params(priv).valid_rx_ant;
|
||||
u8 rate;
|
||||
bool is_active = false;
|
||||
int chan_mod;
|
||||
u8 active_chains;
|
||||
u8 scan_tx_antennas = hw_params(priv).valid_tx_ant;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->shrd->mutex);
|
||||
|
||||
if (vif)
|
||||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
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");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
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 (priv->scan_type != IWL_SCAN_ROC &&
|
||||
iwl_is_any_associated(priv)) {
|
||||
u16 interval = 0;
|
||||
u32 extra;
|
||||
u32 suspend_time = 100;
|
||||
u32 scan_suspend_time = 100;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_ROC:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
interval = 0;
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
interval = vif->bss_conf.beacon_int;
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
} else if (priv->scan_type == IWL_SCAN_ROC) {
|
||||
scan->suspend_time = 0;
|
||||
scan->max_out_time = 0;
|
||||
scan->quiet_time = 0;
|
||||
scan->quiet_plcp_th = 0;
|
||||
}
|
||||
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
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");
|
||||
break;
|
||||
case IWL_SCAN_ROC:
|
||||
IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
scan->tx_cmd.sta_id = ctx->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->contexts[IWL_RXON_CTX_BSS].active.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;
|
||||
}
|
||||
/*
|
||||
* Internal scans are passive, so we can indiscriminately set
|
||||
* the BT ignore flag on 2.4 GHz since it applies to TX only.
|
||||
*/
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist)
|
||||
scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
rate = IWL_RATE_6M_PLCP;
|
||||
break;
|
||||
default:
|
||||
IWL_WARN(priv, "Invalid scan band\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* If active scanning is requested but a certain channel is
|
||||
* marked passive, we can do active scanning if we detect
|
||||
* transmissions.
|
||||
*
|
||||
* There is an issue with some firmware versions that triggers
|
||||
* a sysassert on a "good CRC threshold" of zero (== disabled),
|
||||
* on a radar channel even though this means that we should NOT
|
||||
* send probes.
|
||||
*
|
||||
* The "good CRC threshold" is the number of frames that we
|
||||
* need to receive during our dwell time on a channel before
|
||||
* sending out probes -- setting this to a huge value will
|
||||
* mean we never reach it, but at the same time work around
|
||||
* the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
|
||||
* here instead of IWL_GOOD_CRC_TH_DISABLED.
|
||||
*
|
||||
* This was fixed in later versions along with some other
|
||||
* scan changes, and the threshold behaves as a flag in those
|
||||
* versions.
|
||||
*/
|
||||
if (priv->new_scan_threshold_behaviour)
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_DISABLED;
|
||||
else
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_NEVER;
|
||||
|
||||
band = priv->scan_band;
|
||||
|
||||
if (priv->cfg->scan_rx_antennas[band])
|
||||
rx_ant = priv->cfg->scan_rx_antennas[band];
|
||||
|
||||
if (band == IEEE80211_BAND_2GHZ &&
|
||||
priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
/* transmit 2.4 GHz probes only on first antenna */
|
||||
scan_tx_antennas = first_antenna(scan_tx_antennas);
|
||||
}
|
||||
|
||||
priv->scan_tx_ant[band] = iwl_toggle_tx_ant(priv,
|
||||
priv->scan_tx_ant[band],
|
||||
scan_tx_antennas);
|
||||
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->shrd->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);
|
||||
}
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
priv->bt_full_concurrent) {
|
||||
/* operated as 1x1 in full concurrency mode */
|
||||
rx_ant = first_antenna(rx_ant);
|
||||
}
|
||||
|
||||
/* MIMO is not used here, but value is required */
|
||||
rx_chain |=
|
||||
hw_params(priv).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);
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_NORMAL:
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
vif->addr,
|
||||
priv->scan_request->ie,
|
||||
priv->scan_request->ie_len,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
break;
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
case IWL_SCAN_ROC:
|
||||
/* use bcast addr, will not be transmitted but must be valid */
|
||||
cmd_len = iwl_fill_probe_req(priv,
|
||||
(struct ieee80211_mgmt *)scan->data,
|
||||
iwl_bcast_addr, NULL, 0,
|
||||
IWL_MAX_SCAN_SIZE - sizeof(*scan));
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
scan->tx_cmd.len = cpu_to_le16(cmd_len);
|
||||
|
||||
scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
|
||||
RXON_FILTER_BCON_AWARE_MSK);
|
||||
|
||||
switch (priv->scan_type) {
|
||||
case IWL_SCAN_RADIO_RESET:
|
||||
scan->channel_count =
|
||||
iwl_get_single_channel_for_scan(priv, vif, band,
|
||||
(void *)&scan->data[cmd_len]);
|
||||
break;
|
||||
case IWL_SCAN_NORMAL:
|
||||
scan->channel_count =
|
||||
iwl_get_channels_for_scan(priv, vif, band,
|
||||
is_active, n_probes,
|
||||
(void *)&scan->data[cmd_len]);
|
||||
break;
|
||||
case IWL_SCAN_ROC: {
|
||||
struct iwl_scan_channel *scan_ch;
|
||||
int n_chan, i;
|
||||
u16 dwell;
|
||||
|
||||
dwell = iwl_limit_dwell(priv, priv->hw_roc_duration);
|
||||
n_chan = DIV_ROUND_UP(priv->hw_roc_duration, dwell);
|
||||
|
||||
scan->channel_count = n_chan;
|
||||
|
||||
scan_ch = (void *)&scan->data[cmd_len];
|
||||
|
||||
for (i = 0; i < n_chan; i++) {
|
||||
scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
|
||||
scan_ch->channel =
|
||||
cpu_to_le16(priv->hw_roc_channel->hw_value);
|
||||
|
||||
if (i == n_chan - 1)
|
||||
dwell = priv->hw_roc_duration - i * dwell;
|
||||
|
||||
scan_ch->active_dwell =
|
||||
scan_ch->passive_dwell = cpu_to_le16(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 (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
|
||||
scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
|
||||
else
|
||||
scan_ch->tx_gain = ((1 << 5) | (5 << 3));
|
||||
|
||||
scan_ch++;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (scan->channel_count == 0) {
|
||||
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
cmd.len[0] += le16_to_cpu(scan->tx_cmd.len) +
|
||||
scan->channel_count * sizeof(struct iwl_scan_channel);
|
||||
cmd.data[0] = scan;
|
||||
cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
|
||||
scan->len = cpu_to_le16(cmd.len[0]);
|
||||
|
||||
/* set scan bit here for PAN params */
|
||||
set_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
|
||||
ret = iwlagn_set_pan_params(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iwl_trans_send_cmd(trans(priv), &cmd);
|
||||
if (ret) {
|
||||
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
||||
iwlagn_set_pan_params(priv);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwl_init_scan_params(struct iwl_priv *priv)
|
||||
@ -415,31 +954,33 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
|
||||
if (test_bit(STATUS_SCANNING, &priv->shrd->status) &&
|
||||
priv->scan_type != IWL_SCAN_NORMAL) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* mac80211 will only ask for one band at a time */
|
||||
priv->scan_request = req;
|
||||
priv->scan_vif = vif;
|
||||
|
||||
/*
|
||||
* If an internal scan is in progress, just set
|
||||
* up the scan_request as per above.
|
||||
*/
|
||||
if (priv->scan_type != IWL_SCAN_NORMAL) {
|
||||
IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
|
||||
IWL_DEBUG_SCAN(priv,
|
||||
"SCAN request during internal scan - defer\n");
|
||||
priv->scan_request = req;
|
||||
priv->scan_vif = vif;
|
||||
ret = 0;
|
||||
} else
|
||||
} else {
|
||||
priv->scan_request = req;
|
||||
priv->scan_vif = vif;
|
||||
/*
|
||||
* mac80211 will only ask for one band at a time
|
||||
* so using channels[0] here is ok
|
||||
*/
|
||||
ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL,
|
||||
req->channels[0]->band);
|
||||
if (ret) {
|
||||
priv->scan_request = NULL;
|
||||
priv->scan_vif = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
|
||||
return ret;
|
||||
@ -557,61 +1098,10 @@ static void iwl_bg_abort_scan(struct work_struct *work)
|
||||
static void iwl_bg_scan_completed(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, scan_completed);
|
||||
bool aborted;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Completed scan.\n");
|
||||
|
||||
cancel_delayed_work(&priv->scan_check);
|
||||
container_of(work, struct iwl_priv, scan_completed);
|
||||
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
|
||||
aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
|
||||
if (aborted)
|
||||
IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
|
||||
|
||||
if (!test_and_clear_bit(STATUS_SCANNING, &priv->shrd->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
|
||||
goto out_settings;
|
||||
}
|
||||
|
||||
if (priv->scan_type == IWL_SCAN_ROC) {
|
||||
ieee80211_remain_on_channel_expired(priv->hw);
|
||||
priv->hw_roc_channel = NULL;
|
||||
schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
|
||||
}
|
||||
|
||||
if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
|
||||
int err;
|
||||
|
||||
/* Check if mac80211 requested scan during our internal scan */
|
||||
if (priv->scan_request == NULL)
|
||||
goto out_complete;
|
||||
|
||||
/* If so request a new scan */
|
||||
err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
|
||||
priv->scan_request->channels[0]->band);
|
||||
if (err) {
|
||||
IWL_DEBUG_SCAN(priv,
|
||||
"failed to initiate pending scan: %d\n", err);
|
||||
aborted = true;
|
||||
goto out_complete;
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
out_complete:
|
||||
iwl_complete_scan(priv, aborted);
|
||||
|
||||
out_settings:
|
||||
/* Can we still talk to firmware ? */
|
||||
if (!iwl_is_ready_rf(priv->shrd))
|
||||
goto out;
|
||||
|
||||
iwlagn_post_scan(priv);
|
||||
|
||||
out:
|
||||
iwl_process_scan_complete(priv);
|
||||
mutex_unlock(&priv->shrd->mutex);
|
||||
}
|
||||
|
||||
|
@ -72,8 +72,27 @@
|
||||
|
||||
#include "iwl-commands.h"
|
||||
|
||||
/*This files includes all the types / functions that are exported by the
|
||||
* upper layer to the bus and transport layer */
|
||||
/**
|
||||
* DOC: shared area - role and goal
|
||||
*
|
||||
* The shared area contains all the data exported by the upper layer to the
|
||||
* other layers. Since the bus and transport layer shouldn't dereference
|
||||
* iwl_priv, all the data needed by the upper layer and the transport / bus
|
||||
* layer must be here.
|
||||
* The shared area also holds pointer to all the other layers. This allows a
|
||||
* layer to call a function from another layer.
|
||||
*
|
||||
* NOTE: All the layers hold a pointer to the shared area which must be shrd.
|
||||
* A few macros assume that (_m)->shrd points to the shared area no matter
|
||||
* what _m is.
|
||||
*
|
||||
* gets notifications about enumeration, suspend, resume.
|
||||
* For the moment, the bus layer is not a linux kernel module as itself, and
|
||||
* the module_init function of the driver must call the bus specific
|
||||
* registration functions. These functions are listed at the end of this file.
|
||||
* For the moment, there is only one implementation of this interface: PCI-e.
|
||||
* This implementation is iwl-pci.c
|
||||
*/
|
||||
|
||||
struct iwl_cfg;
|
||||
struct iwl_bus;
|
||||
@ -90,6 +109,9 @@ extern struct iwl_mod_params iwlagn_mod_params;
|
||||
|
||||
/**
|
||||
* struct iwl_mod_params
|
||||
*
|
||||
* Holds the module parameters
|
||||
*
|
||||
* @sw_crypto: using hardware encryption, default = 0
|
||||
* @num_of_queues: number of tx queue, HW dependent
|
||||
* @disable_11n: 11n capabilities enabled, default = 0
|
||||
@ -134,20 +156,24 @@ struct iwl_mod_params {
|
||||
|
||||
/**
|
||||
* struct iwl_hw_params
|
||||
*
|
||||
* Holds the module parameters
|
||||
*
|
||||
* @max_txq_num: Max # Tx queues supported
|
||||
* @num_ampdu_queues: num of ampdu queues
|
||||
* @tx/rx_chains_num: Number of TX/RX chains
|
||||
* @valid_tx/rx_ant: usable antennas
|
||||
* @max_stations:
|
||||
* @ht40_channel: is 40MHz width possible in band 2.4
|
||||
* @beacon_time_tsf_bits: number of valid tsf bits for beacon time
|
||||
* @sku:
|
||||
* @tx_chains_num: Number of TX chains
|
||||
* @rx_chains_num: Number of RX chains
|
||||
* @valid_tx_ant: usable antennas for TX
|
||||
* @valid_rx_ant: usable antennas for RX
|
||||
* @max_stations: the maximal number of stations
|
||||
* @ht40_channel: is 40MHz width possible: BIT(IEEE80211_BAND_XXX)
|
||||
* @sku: sku read from EEPROM
|
||||
* @rx_page_order: Rx buffer page order
|
||||
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
|
||||
* BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
|
||||
* @sw_crypto: 0 for hw, 1 for sw
|
||||
* @max_xxx_size: for ucode uses
|
||||
* @ct_kill_threshold: temperature threshold
|
||||
* @max_inst_size: for ucode use
|
||||
* @max_data_size: for ucode use
|
||||
* @ct_kill_threshold: temperature threshold - in hw dependent unit
|
||||
* @ct_kill_exit_threshold: when to reeable the device - in hw dependent unit
|
||||
* relevant for 1000, 6000 and up
|
||||
* @wd_timeout: TX queues watchdog timeout
|
||||
* @calib_init_cfg: setup initial calibrations for the hw
|
||||
* @calib_rt_cfg: setup runtime calibrations for the hw
|
||||
@ -163,14 +189,12 @@ struct iwl_hw_params {
|
||||
u8 max_stations;
|
||||
u8 ht40_channel;
|
||||
bool shadow_reg_enable;
|
||||
u16 beacon_time_tsf_bits;
|
||||
u16 sku;
|
||||
u32 rx_page_order;
|
||||
u32 max_inst_size;
|
||||
u32 max_data_size;
|
||||
u32 ct_kill_threshold; /* value in hw-dependent units */
|
||||
u32 ct_kill_exit_threshold; /* value in hw-dependent units */
|
||||
/* for 1000, 6000 series and up */
|
||||
u32 ct_kill_threshold;
|
||||
u32 ct_kill_exit_threshold;
|
||||
unsigned int wd_timeout;
|
||||
|
||||
u32 calib_init_cfg;
|
||||
@ -179,28 +203,59 @@ struct iwl_hw_params {
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_ht_agg - aggregation status while waiting for block-ack
|
||||
* @txq_id: Tx queue used for Tx attempt
|
||||
* @wait_for_ba: Expect block-ack before next Tx reply
|
||||
* @rate_n_flags: Rate at which Tx was attempted
|
||||
* enum iwl_agg_state
|
||||
*
|
||||
* If REPLY_TX indicates that aggregation was attempted, driver must wait
|
||||
* for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info
|
||||
* until block ack arrives.
|
||||
* The state machine of the BA agreement establishment / tear down.
|
||||
* These states relate to a specific RA / TID.
|
||||
*
|
||||
* @IWL_AGG_OFF: aggregation is not used
|
||||
* @IWL_AGG_ON: aggregation session is up
|
||||
* @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
|
||||
* HW queue to be empty from packets for this RA /TID.
|
||||
* @IWL_EMPTYING_HW_QUEUE_DELBA: tearing down a BA session - waiting for the
|
||||
* HW queue to be empty from packets for this RA /TID.
|
||||
*/
|
||||
struct iwl_ht_agg {
|
||||
u16 txq_id;
|
||||
u16 wait_for_ba;
|
||||
u32 rate_n_flags;
|
||||
#define IWL_AGG_OFF 0
|
||||
#define IWL_AGG_ON 1
|
||||
#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
|
||||
#define IWL_EMPTYING_HW_QUEUE_DELBA 3
|
||||
u8 state;
|
||||
enum iwl_agg_state {
|
||||
IWL_AGG_OFF = 0,
|
||||
IWL_AGG_ON,
|
||||
IWL_EMPTYING_HW_QUEUE_ADDBA,
|
||||
IWL_EMPTYING_HW_QUEUE_DELBA,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_ht_agg - aggregation state machine
|
||||
|
||||
* This structs holds the states for the BA agreement establishment and tear
|
||||
* down. It also holds the state during the BA session itself. This struct is
|
||||
* duplicated for each RA / TID.
|
||||
|
||||
* @rate_n_flags: Rate at which Tx was attempted. Holds the data between the
|
||||
* Tx response (REPLY_TX), and the block ack notification
|
||||
* (REPLY_COMPRESSED_BA).
|
||||
* @state: state of the BA agreement establishment / tear down.
|
||||
* @txq_id: Tx queue used by the BA session - used by the transport layer.
|
||||
* Needed by the upper layer for debugfs only.
|
||||
* @wait_for_ba: Expect block-ack before next Tx reply
|
||||
*/
|
||||
struct iwl_ht_agg {
|
||||
u32 rate_n_flags;
|
||||
enum iwl_agg_state state;
|
||||
u16 txq_id;
|
||||
bool wait_for_ba;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_tid_data - one for each RA / TID
|
||||
|
||||
* This structs holds the states for each RA / TID.
|
||||
|
||||
* @seq_number: the next WiFi sequence number to use
|
||||
* @tfds_in_queue: number of packets sent to the HW queues.
|
||||
* Exported for debugfs only
|
||||
* @agg: aggregation state machine
|
||||
*/
|
||||
struct iwl_tid_data {
|
||||
u16 seq_number; /* agn only */
|
||||
u16 seq_number;
|
||||
u16 tfds_in_queue;
|
||||
struct iwl_ht_agg agg;
|
||||
};
|
||||
@ -246,12 +301,6 @@ struct iwl_shared {
|
||||
spinlock_t sta_lock;
|
||||
struct mutex mutex;
|
||||
|
||||
/*these 2 shouldn't really be here, but they are needed for
|
||||
* iwl_queue_stop, which is called from the upper layer too
|
||||
*/
|
||||
u8 mac80211_registered;
|
||||
struct ieee80211_hw *hw;
|
||||
|
||||
struct iwl_tid_data tid_data[IWLAGN_STATION_COUNT][IWL_MAX_TID_COUNT];
|
||||
|
||||
wait_queue_head_t wait_command_queue;
|
||||
@ -371,16 +420,14 @@ enum iwl_rxon_context_id {
|
||||
NUM_IWL_RXON_CTX
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int iwl_suspend(struct iwl_priv *priv);
|
||||
int iwl_resume(struct iwl_priv *priv);
|
||||
#endif /* !CONFIG_PM */
|
||||
|
||||
int iwl_probe(struct iwl_bus *bus, const struct iwl_trans_ops *trans_ops,
|
||||
struct iwl_cfg *cfg);
|
||||
void __devexit iwl_remove(struct iwl_priv * priv);
|
||||
struct iwl_device_cmd;
|
||||
int __must_check iwl_rx_dispatch(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
void iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
||||
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
|
||||
void iwl_start_tx_ba_trans_ready(struct iwl_priv *priv,
|
||||
enum iwl_rxon_context_id ctx,
|
||||
@ -390,20 +437,26 @@ void iwl_stop_tx_ba_trans_ready(struct iwl_priv *priv,
|
||||
u8 sta_id, u8 tid);
|
||||
void iwl_set_hw_rfkill_state(struct iwl_priv *priv, bool state);
|
||||
void iwl_nic_config(struct iwl_priv *priv);
|
||||
void iwl_free_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
||||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
int iwl_apm_init(struct iwl_priv *priv);
|
||||
void iwlagn_fw_error(struct iwl_priv *priv, bool ondemand);
|
||||
const char *get_cmd_string(u8 cmd);
|
||||
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
|
||||
|
||||
void iwl_stop_sw_queue(struct iwl_priv *priv, u8 ac);
|
||||
void iwl_wake_sw_queue(struct iwl_priv *priv, u8 ac);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
void iwl_reset_traffic_log(struct iwl_priv *priv);
|
||||
#endif /* CONFIG_IWLWIFI_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid);
|
||||
void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||
enum iwl_rxon_context_id ctxid);
|
||||
#else
|
||||
static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid)
|
||||
static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv,
|
||||
enum iwl_rxon_context_id ctxid)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@ -436,6 +489,7 @@ static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv, u8 ctxid)
|
||||
#define STATUS_FW_ERROR 17
|
||||
#define STATUS_DEVICE_ENABLED 18
|
||||
#define STATUS_CHANNEL_SWITCH_PENDING 19
|
||||
#define STATUS_SCAN_COMPLETE 20
|
||||
|
||||
static inline int iwl_is_ready(struct iwl_shared *shrd)
|
||||
{
|
||||
|
@ -59,8 +59,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
|
||||
|
||||
static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *addsta,
|
||||
struct iwl_rx_packet *pkt,
|
||||
bool sync)
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
u8 sta_id = addsta->sta.sta_id;
|
||||
unsigned long flags;
|
||||
@ -123,15 +122,14 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_add_sta_callback(struct iwl_shared *shrd,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct iwl_rx_packet *pkt)
|
||||
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_addsta_cmd *addsta =
|
||||
(struct iwl_addsta_cmd *)cmd->cmd.payload;
|
||||
|
||||
iwl_process_add_sta_resp(shrd->priv, addsta, pkt, false);
|
||||
(struct iwl_addsta_cmd *) cmd->payload;
|
||||
|
||||
return iwl_process_add_sta_resp(priv, addsta, pkt);
|
||||
}
|
||||
|
||||
static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
|
||||
@ -147,7 +145,6 @@ static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
|
||||
int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *sta, u8 flags)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = NULL;
|
||||
int ret = 0;
|
||||
u8 data[sizeof(*sta)];
|
||||
struct iwl_host_cmd cmd = {
|
||||
@ -160,9 +157,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
|
||||
sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : "");
|
||||
|
||||
if (flags & CMD_ASYNC)
|
||||
cmd.callback = iwl_add_sta_callback;
|
||||
else {
|
||||
if (!(flags & CMD_ASYNC)) {
|
||||
cmd.flags |= CMD_WANT_SKB;
|
||||
might_sleep();
|
||||
}
|
||||
@ -172,14 +167,16 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
|
||||
if (ret || (flags & CMD_ASYNC))
|
||||
return ret;
|
||||
/*else the command was successfully sent in SYNC mode, need to free
|
||||
* the reply page */
|
||||
|
||||
if (ret == 0) {
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
|
||||
}
|
||||
iwl_free_pages(priv->shrd, cmd.reply_page);
|
||||
|
||||
return ret;
|
||||
if (cmd.handler_status)
|
||||
IWL_ERR(priv, "%s - error in the CMD response %d", __func__,
|
||||
cmd.handler_status);
|
||||
|
||||
return cmd.handler_status;
|
||||
}
|
||||
|
||||
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
|
||||
@ -305,7 +302,7 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
station->ctxid = ctx->ctxid;
|
||||
|
||||
if (sta) {
|
||||
struct iwl_station_priv_common *sta_priv;
|
||||
struct iwl_station_priv *sta_priv;
|
||||
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
sta_priv->ctx = ctx;
|
||||
@ -821,7 +818,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
|
||||
@ -829,7 +826,7 @@ int iwl_mac_sta_remove(struct ieee80211_hw *hw,
|
||||
mutex_lock(&priv->shrd->mutex);
|
||||
IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
|
||||
sta->addr);
|
||||
ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
|
||||
ret = iwl_remove_station(priv, sta_priv->sta_id, sta->addr);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error removing station %pM\n",
|
||||
sta->addr);
|
||||
|
@ -61,6 +61,9 @@ u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
|
||||
struct iwl_link_quality_cmd *lq, u8 flags, bool init);
|
||||
void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwl_add_sta_callback(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb,
|
||||
struct iwl_device_cmd *cmd);
|
||||
|
||||
|
||||
/**
|
||||
* iwl_clear_driver_stations - clear knowledge of all stations from driver
|
||||
@ -102,7 +105,7 @@ static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
||||
if (WARN_ON(!sta))
|
||||
return IWL_INVALID_STATION;
|
||||
|
||||
return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
|
||||
return ((struct iwl_station_priv *)sta->drv_priv)->sta_id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -118,16 +118,6 @@ struct iwl_dma_ptr {
|
||||
struct iwl_cmd_meta {
|
||||
/* only for SYNC commands, iff the reply skb is wanted */
|
||||
struct iwl_host_cmd *source;
|
||||
/*
|
||||
* only for ASYNC commands
|
||||
* (which is somewhat stupid -- look at iwl-sta.c for instance
|
||||
* which duplicates a bunch of code because the callback isn't
|
||||
* invoked for SYNC commands, if it were and its result passed
|
||||
* through it would be simpler...)
|
||||
*/
|
||||
void (*callback)(struct iwl_shared *shrd,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct iwl_rx_packet *pkt);
|
||||
|
||||
u32 flags;
|
||||
|
||||
@ -285,10 +275,8 @@ int iwlagn_txq_attach_buf_to_tfd(struct iwl_trans *trans,
|
||||
dma_addr_t addr, u16 len, u8 reset);
|
||||
int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id);
|
||||
int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
int __must_check iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id,
|
||||
u32 flags, u16 len, const void *data);
|
||||
void iwl_tx_cmd_complete(struct iwl_trans *trans,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
struct iwl_rx_mem_buffer *rxb, int handler_status);
|
||||
void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
|
||||
struct iwl_tx_queue *txq,
|
||||
u16 byte_cnt);
|
||||
@ -307,7 +295,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans,
|
||||
enum iwl_rxon_context_id ctx,
|
||||
int sta_id, int tid, int frame_limit);
|
||||
void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
|
||||
int index);
|
||||
int index, enum dma_data_direction dma_dir);
|
||||
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
|
||||
struct sk_buff_head *skbs);
|
||||
int iwl_queue_space(const struct iwl_queue *q);
|
||||
@ -375,12 +363,9 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (unlikely(!trans->shrd->mac80211_registered))
|
||||
return;
|
||||
|
||||
if (test_and_clear_bit(hwq, trans_pcie->queue_stopped))
|
||||
if (atomic_dec_return(&trans_pcie->queue_stop_count[ac]) <= 0)
|
||||
ieee80211_wake_queue(trans->shrd->hw, ac);
|
||||
iwl_wake_sw_queue(priv(trans), ac);
|
||||
}
|
||||
|
||||
static inline void iwl_stop_queue(struct iwl_trans *trans,
|
||||
@ -392,12 +377,9 @@ static inline void iwl_stop_queue(struct iwl_trans *trans,
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
if (unlikely(!trans->shrd->mac80211_registered))
|
||||
return;
|
||||
|
||||
if (!test_and_set_bit(hwq, trans_pcie->queue_stopped))
|
||||
if (atomic_inc_return(&trans_pcie->queue_stop_count[ac]) > 0)
|
||||
ieee80211_stop_queue(trans->shrd->hw, ac);
|
||||
iwl_stop_sw_queue(priv(trans), ac);
|
||||
}
|
||||
|
||||
#ifdef ieee80211_stop_queue
|
@ -34,7 +34,7 @@
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-trans-int-pcie.h"
|
||||
#include "iwl-trans-pcie-int.h"
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
@ -372,12 +372,15 @@ static void iwl_rx_handle(struct iwl_trans *trans)
|
||||
struct iwl_trans_pcie *trans_pcie =
|
||||
IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rx_queue *rxq = &trans_pcie->rxq;
|
||||
struct iwl_tx_queue *txq = &trans_pcie->txq[trans->shrd->cmd_queue];
|
||||
struct iwl_device_cmd *cmd;
|
||||
u32 r, i;
|
||||
int reclaim;
|
||||
unsigned long flags;
|
||||
u8 fill_rx = 0;
|
||||
u32 count = 8;
|
||||
int total_empty;
|
||||
int index, cmd_index;
|
||||
|
||||
/* uCode's read index (stored in shared DRAM) indicates the last Rx
|
||||
* buffer that the driver may process (last buffer filled by ucode). */
|
||||
@ -397,7 +400,8 @@ static void iwl_rx_handle(struct iwl_trans *trans)
|
||||
fill_rx = 1;
|
||||
|
||||
while (i != r) {
|
||||
int len;
|
||||
int len, err;
|
||||
u16 sequence;
|
||||
|
||||
rxb = rxq->queue[i];
|
||||
|
||||
@ -437,7 +441,27 @@ static void iwl_rx_handle(struct iwl_trans *trans)
|
||||
(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
|
||||
(pkt->hdr.cmd != REPLY_TX);
|
||||
|
||||
iwl_rx_dispatch(priv(trans), rxb);
|
||||
sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
index = SEQ_TO_INDEX(sequence);
|
||||
cmd_index = get_cmd_index(&txq->q, index);
|
||||
|
||||
if (reclaim)
|
||||
cmd = txq->cmd[cmd_index];
|
||||
else
|
||||
cmd = NULL;
|
||||
|
||||
/* warn if this is cmd response / notification and the uCode
|
||||
* didn't set the SEQ_RX_FRAME for a frame that is
|
||||
* uCode-originated
|
||||
* If you saw this code after the second half of 2012, then
|
||||
* please remove it
|
||||
*/
|
||||
WARN(pkt->hdr.cmd != REPLY_TX && reclaim == false &&
|
||||
(!(pkt->hdr.sequence & SEQ_RX_FRAME)),
|
||||
"reclaim is false, SEQ_RX_FRAME unset: %s\n",
|
||||
get_cmd_string(pkt->hdr.cmd));
|
||||
|
||||
err = iwl_rx_dispatch(priv(trans), rxb, cmd);
|
||||
|
||||
/*
|
||||
* XXX: After here, we should always check rxb->page
|
||||
@ -452,7 +476,7 @@ static void iwl_rx_handle(struct iwl_trans *trans)
|
||||
* iwl_trans_send_cmd()
|
||||
* as we reclaim the driver command queue */
|
||||
if (rxb->page)
|
||||
iwl_tx_cmd_complete(trans, rxb);
|
||||
iwl_tx_cmd_complete(trans, rxb, err);
|
||||
else
|
||||
IWL_WARN(trans, "Claim null rxb?\n");
|
||||
}
|
||||
@ -645,7 +669,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
|
||||
*/
|
||||
clear_bit(STATUS_READY, &trans->shrd->status);
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
|
||||
wake_up_interruptible(&priv->shrd->wait_command_queue);
|
||||
wake_up(&priv->shrd->wait_command_queue);
|
||||
IWL_ERR(trans, "RF is used by WiMAX\n");
|
||||
return;
|
||||
}
|
||||
@ -1086,7 +1110,7 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
||||
handled |= CSR_INT_BIT_FH_TX;
|
||||
/* Wake up uCode load routine, now that load is complete */
|
||||
priv(trans)->ucode_write_complete = 1;
|
||||
wake_up_interruptible(&trans->shrd->wait_command_queue);
|
||||
wake_up(&trans->shrd->wait_command_queue);
|
||||
}
|
||||
|
||||
if (inta & ~handled) {
|
@ -38,7 +38,7 @@
|
||||
#include "iwl-io.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-trans-int-pcie.h"
|
||||
#include "iwl-trans-pcie-int.h"
|
||||
|
||||
#define IWL_TX_CRC_SIZE 4
|
||||
#define IWL_TX_DELIMITER_SIZE 4
|
||||
@ -59,13 +59,15 @@ void iwl_trans_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
|
||||
u8 sta_id = 0;
|
||||
u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
|
||||
__le16 bc_ent;
|
||||
struct iwl_tx_cmd *tx_cmd =
|
||||
(struct iwl_tx_cmd *) txq->cmd[txq->q.write_ptr]->payload;
|
||||
|
||||
scd_bc_tbl = trans_pcie->scd_bc_tbls.addr;
|
||||
|
||||
WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
|
||||
|
||||
sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
|
||||
sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
|
||||
sta_id = tx_cmd->sta_id;
|
||||
sec_ctl = tx_cmd->sec_ctl;
|
||||
|
||||
switch (sec_ctl & TX_CMD_SEC_MSK) {
|
||||
case TX_CMD_SEC_CCM:
|
||||
@ -207,17 +209,17 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta,
|
||||
* @trans - transport private data
|
||||
* @txq - tx queue
|
||||
* @index - the index of the TFD to be freed
|
||||
*@dma_dir - the direction of the DMA mapping
|
||||
*
|
||||
* Does NOT advance any TFD circular buffer read/write indexes
|
||||
* Does NOT free the TFD itself (which is within circular buffer)
|
||||
*/
|
||||
void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
|
||||
int index)
|
||||
int index, enum dma_data_direction dma_dir)
|
||||
{
|
||||
struct iwl_tfd *tfd_tmp = txq->tfds;
|
||||
|
||||
iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index],
|
||||
DMA_TO_DEVICE);
|
||||
iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir);
|
||||
|
||||
/* free SKB */
|
||||
if (txq->skbs) {
|
||||
@ -225,9 +227,12 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq,
|
||||
|
||||
skb = txq->skbs[index];
|
||||
|
||||
/* can be called from irqs-disabled context */
|
||||
/* Can be called from irqs-disabled context
|
||||
* If skb is not NULL, it means that the whole queue is being
|
||||
* freed and that the queue is not empty - free the skb
|
||||
*/
|
||||
if (skb) {
|
||||
dev_kfree_skb_any(skb);
|
||||
iwl_free_skb(priv(trans), skb);
|
||||
txq->skbs[index] = NULL;
|
||||
}
|
||||
}
|
||||
@ -350,11 +355,13 @@ static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_trans *trans,
|
||||
int read_ptr = txq->q.read_ptr;
|
||||
u8 sta_id = 0;
|
||||
__le16 bc_ent;
|
||||
struct iwl_tx_cmd *tx_cmd =
|
||||
(struct iwl_tx_cmd *) txq->cmd[txq->q.read_ptr]->payload;
|
||||
|
||||
WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
|
||||
|
||||
if (txq_id != trans->shrd->cmd_queue)
|
||||
sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
|
||||
sta_id = tx_cmd->sta_id;
|
||||
|
||||
bc_ent = cpu_to_le16(1 | (sta_id << 12));
|
||||
scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
|
||||
@ -759,8 +766,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */
|
||||
if (cmd->flags & CMD_WANT_SKB)
|
||||
out_meta->source = cmd;
|
||||
if (cmd->flags & CMD_ASYNC)
|
||||
out_meta->callback = cmd->callback;
|
||||
|
||||
/* set up the header */
|
||||
|
||||
@ -772,7 +777,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
|
||||
/* and copy the data that needs to be copied */
|
||||
|
||||
cmd_dest = &out_cmd->cmd.payload[0];
|
||||
cmd_dest = out_cmd->payload;
|
||||
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
|
||||
if (!cmd->len[i])
|
||||
continue;
|
||||
@ -891,12 +896,15 @@ static void iwl_hcmd_queue_reclaim(struct iwl_trans *trans, int txq_id,
|
||||
/**
|
||||
* iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
|
||||
* @rxb: Rx buffer to reclaim
|
||||
* @handler_status: return value of the handler of the command
|
||||
* (put in setup_rx_handlers)
|
||||
*
|
||||
* If an Rx buffer has an async callback associated with it the callback
|
||||
* will be executed. The attached skb (if present) will only be freed
|
||||
* if the callback returns 1
|
||||
*/
|
||||
void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb)
|
||||
void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb,
|
||||
int handler_status)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
@ -933,9 +941,9 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb)
|
||||
/* Input error checking is done when commands are added to queue. */
|
||||
if (meta->flags & CMD_WANT_SKB) {
|
||||
meta->source->reply_page = (unsigned long)rxb_addr(rxb);
|
||||
meta->source->handler_status = handler_status;
|
||||
rxb->page = NULL;
|
||||
} else if (meta->callback)
|
||||
meta->callback(trans->shrd, cmd, pkt);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&trans->hcmd_lock, flags);
|
||||
|
||||
@ -945,7 +953,7 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb)
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status);
|
||||
IWL_DEBUG_INFO(trans, "Clearing HCMD_ACTIVE for command %s\n",
|
||||
get_cmd_string(cmd->hdr.cmd));
|
||||
wake_up_interruptible(&trans->shrd->wait_command_queue);
|
||||
wake_up(&trans->shrd->wait_command_queue);
|
||||
}
|
||||
|
||||
meta->flags = 0;
|
||||
@ -955,30 +963,6 @@ void iwl_tx_cmd_complete(struct iwl_trans *trans, struct iwl_rx_mem_buffer *rxb)
|
||||
|
||||
#define HOST_COMPLETE_TIMEOUT (2 * HZ)
|
||||
|
||||
static void iwl_generic_cmd_callback(struct iwl_shared *shrd,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(shrd->trans, "Bad return from %s (0x%08X)\n",
|
||||
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
switch (cmd->hdr.cmd) {
|
||||
case REPLY_TX_LINK_QUALITY_CMD:
|
||||
case SENSITIVITY_CMD:
|
||||
IWL_DEBUG_HC_DUMP(shrd->trans, "back from %s (0x%08X)\n",
|
||||
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
|
||||
break;
|
||||
default:
|
||||
IWL_DEBUG_HC(shrd->trans, "back from %s (0x%08X)\n",
|
||||
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
{
|
||||
int ret;
|
||||
@ -987,9 +971,6 @@ static int iwl_send_cmd_async(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
if (WARN_ON(cmd->flags & CMD_WANT_SKB))
|
||||
return -EINVAL;
|
||||
|
||||
/* Assign a generic callback if one is not provided */
|
||||
if (!cmd->callback)
|
||||
cmd->callback = iwl_generic_cmd_callback;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &trans->shrd->status))
|
||||
return -EBUSY;
|
||||
@ -1011,10 +992,6 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
|
||||
lockdep_assert_held(&trans->shrd->mutex);
|
||||
|
||||
/* A synchronous command can not have a callback set. */
|
||||
if (WARN_ON(cmd->callback))
|
||||
return -EINVAL;
|
||||
|
||||
IWL_DEBUG_INFO(trans, "Attempting to send sync command %s\n",
|
||||
get_cmd_string(cmd->id));
|
||||
|
||||
@ -1031,7 +1008,7 @@ static int iwl_send_cmd_sync(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = wait_event_interruptible_timeout(trans->shrd->wait_command_queue,
|
||||
ret = wait_event_timeout(trans->shrd->wait_command_queue,
|
||||
!test_bit(STATUS_HCMD_ACTIVE, &trans->shrd->status),
|
||||
HOST_COMPLETE_TIMEOUT);
|
||||
if (!ret) {
|
||||
@ -1098,19 +1075,6 @@ int iwl_trans_pcie_send_cmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||
return iwl_send_cmd_sync(trans, cmd);
|
||||
}
|
||||
|
||||
int iwl_trans_pcie_send_cmd_pdu(struct iwl_trans *trans, u8 id, u32 flags,
|
||||
u16 len, const void *data)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = id,
|
||||
.len = { len, },
|
||||
.data = { data, },
|
||||
.flags = flags,
|
||||
};
|
||||
|
||||
return iwl_trans_pcie_send_cmd(trans, &cmd);
|
||||
}
|
||||
|
||||
/* Frees buffers until index _not_ inclusive */
|
||||
int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
|
||||
struct sk_buff_head *skbs)
|
||||
@ -1121,6 +1085,10 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
|
||||
int last_to_free;
|
||||
int freed = 0;
|
||||
|
||||
/* This function is not meant to release cmd queue*/
|
||||
if (WARN_ON(txq_id == trans->shrd->cmd_queue))
|
||||
return 0;
|
||||
|
||||
/*Since we free until index _not_ inclusive, the one before index is
|
||||
* the last we will free. This one must be used */
|
||||
last_to_free = iwl_queue_dec_wrap(index, q->n_bd);
|
||||
@ -1153,7 +1121,7 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index,
|
||||
|
||||
iwlagn_txq_inval_byte_cnt_tbl(trans, txq);
|
||||
|
||||
iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr);
|
||||
iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr, DMA_TO_DEVICE);
|
||||
freed++;
|
||||
}
|
||||
return freed;
|
1989
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
Normal file
1989
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -97,15 +97,7 @@ enum {
|
||||
*/
|
||||
struct iwl_device_cmd {
|
||||
struct iwl_cmd_header hdr; /* uCode API */
|
||||
union {
|
||||
u32 flags;
|
||||
u8 val8;
|
||||
u16 val16;
|
||||
u32 val32;
|
||||
struct iwl_tx_cmd tx;
|
||||
struct iwl6000_channel_switch_cmd chswitch;
|
||||
u8 payload[DEF_CMD_PAYLOAD_SIZE];
|
||||
} __packed cmd;
|
||||
u8 payload[DEF_CMD_PAYLOAD_SIZE];
|
||||
} __packed;
|
||||
|
||||
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
|
||||
@ -120,6 +112,8 @@ enum iwl_hcmd_dataflag {
|
||||
* struct iwl_host_cmd - Host command to the uCode
|
||||
* @data: array of chunks that composes the data of the host command
|
||||
* @reply_page: pointer to the page that holds the response to the host command
|
||||
* @handler_status: return value of the handler of the command
|
||||
* (put in setup_rx_handlers) - valid for SYNC mode only
|
||||
* @callback:
|
||||
* @flags: can be CMD_* note CMD_WANT_SKB is incompatible withe CMD_ASYNC
|
||||
* @len: array of the lenths of the chunks in data
|
||||
@ -129,9 +123,8 @@ enum iwl_hcmd_dataflag {
|
||||
struct iwl_host_cmd {
|
||||
const void *data[IWL_MAX_CMD_TFDS];
|
||||
unsigned long reply_page;
|
||||
void (*callback)(struct iwl_shared *shrd,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct iwl_rx_packet *pkt);
|
||||
int handler_status;
|
||||
|
||||
u32 flags;
|
||||
u16 len[IWL_MAX_CMD_TFDS];
|
||||
u8 dataflags[IWL_MAX_CMD_TFDS];
|
||||
@ -151,7 +144,6 @@ struct iwl_host_cmd {
|
||||
* @wake_any_queue: wake all the queues of a specfic context IWL_RXON_CTX_*
|
||||
* @stop_device:stops the whole device (embedded CPU put to reset)
|
||||
* @send_cmd:send a host command
|
||||
* @send_cmd_pdu:send a host command: flags can be CMD_*
|
||||
* @tx: send an skb
|
||||
* @reclaim: free packet until ssn. Returns a list of freed packets.
|
||||
* @tx_agg_alloc: allocate resources for a TX BA session
|
||||
@ -178,14 +170,14 @@ struct iwl_trans_ops {
|
||||
void (*stop_device)(struct iwl_trans *trans);
|
||||
void (*tx_start)(struct iwl_trans *trans);
|
||||
|
||||
void (*wake_any_queue)(struct iwl_trans *trans, u8 ctx);
|
||||
void (*wake_any_queue)(struct iwl_trans *trans,
|
||||
enum iwl_rxon_context_id ctx);
|
||||
|
||||
int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
|
||||
int (*send_cmd_pdu)(struct iwl_trans *trans, u8 id, u32 flags, u16 len,
|
||||
const void *data);
|
||||
int (*tx)(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id);
|
||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||
u8 sta_id);
|
||||
void (*reclaim)(struct iwl_trans *trans, int sta_id, int tid,
|
||||
int txq_id, int ssn, u32 status,
|
||||
struct sk_buff_head *skbs);
|
||||
@ -209,9 +201,10 @@ struct iwl_trans_ops {
|
||||
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
|
||||
int (*check_stuck_queue)(struct iwl_trans *trans, int q);
|
||||
int (*wait_tx_queue_empty)(struct iwl_trans *trans);
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
int (*suspend)(struct iwl_trans *trans);
|
||||
int (*resume)(struct iwl_trans *trans);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@ -255,7 +248,8 @@ static inline void iwl_trans_tx_start(struct iwl_trans *trans)
|
||||
trans->ops->tx_start(trans);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans, u8 ctx)
|
||||
static inline void iwl_trans_wake_any_queue(struct iwl_trans *trans,
|
||||
enum iwl_rxon_context_id ctx)
|
||||
{
|
||||
trans->ops->wake_any_queue(trans, ctx);
|
||||
}
|
||||
@ -267,14 +261,12 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
|
||||
return trans->ops->send_cmd(trans, cmd);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
|
||||
u32 flags, u16 len, const void *data)
|
||||
{
|
||||
return trans->ops->send_cmd_pdu(trans, id, flags, len, data);
|
||||
}
|
||||
int iwl_trans_send_cmd_pdu(struct iwl_trans *trans, u8 id,
|
||||
u32 flags, u16 len, const void *data);
|
||||
|
||||
static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
struct iwl_device_cmd *dev_cmd, u8 ctx, u8 sta_id)
|
||||
struct iwl_device_cmd *dev_cmd, enum iwl_rxon_context_id ctx,
|
||||
u8 sta_id)
|
||||
{
|
||||
return trans->ops->tx(trans, skb, dev_cmd, ctx, sta_id);
|
||||
}
|
||||
@ -339,6 +331,7 @@ static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
|
||||
return trans->ops->dbgfs_register(trans, dir);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static inline int iwl_trans_suspend(struct iwl_trans *trans)
|
||||
{
|
||||
return trans->ops->suspend(trans);
|
||||
@ -348,6 +341,7 @@ static inline int iwl_trans_resume(struct iwl_trans *trans)
|
||||
{
|
||||
return trans->ops->resume(trans);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************************************
|
||||
* Transport layers implementations
|
||||
|
@ -695,7 +695,7 @@ static void lbs_scan_worker(struct work_struct *work)
|
||||
tlv = scan_cmd->tlvbuffer;
|
||||
|
||||
/* add SSID TLV */
|
||||
if (priv->scan_req->n_ssids)
|
||||
if (priv->scan_req->n_ssids && priv->scan_req->ssids[0].ssid_len > 0)
|
||||
tlv += lbs_add_ssid_tlv(tlv,
|
||||
priv->scan_req->ssids[0].ssid,
|
||||
priv->scan_req->ssids[0].ssid_len);
|
||||
@ -736,7 +736,6 @@ static void lbs_scan_worker(struct work_struct *work)
|
||||
cfg80211_scan_done(priv->scan_req, false);
|
||||
|
||||
priv->scan_req = NULL;
|
||||
priv->last_scan = jiffies;
|
||||
}
|
||||
|
||||
/* Restart network */
|
||||
@ -1302,24 +1301,26 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
|
||||
lbs_deb_enter(LBS_DEB_CFG80211);
|
||||
|
||||
if (!sme->bssid) {
|
||||
/* Run a scan if one isn't in-progress already and if the last
|
||||
* scan was done more than 2 seconds ago.
|
||||
struct cfg80211_scan_request *creq;
|
||||
|
||||
/*
|
||||
* Scan for the requested network after waiting for existing
|
||||
* scans to finish.
|
||||
*/
|
||||
if (priv->scan_req == NULL &&
|
||||
time_after(jiffies, priv->last_scan + (2 * HZ))) {
|
||||
struct cfg80211_scan_request *creq;
|
||||
lbs_deb_assoc("assoc: waiting for existing scans\n");
|
||||
wait_event_interruptible_timeout(priv->scan_q,
|
||||
(priv->scan_req == NULL),
|
||||
(15 * HZ));
|
||||
|
||||
creq = _new_connect_scan_req(wiphy, sme);
|
||||
if (!creq) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
lbs_deb_assoc("assoc: scanning for compatible AP\n");
|
||||
_internal_start_scan(priv, true, creq);
|
||||
creq = _new_connect_scan_req(wiphy, sme);
|
||||
if (!creq) {
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Wait for any in-progress scan to complete */
|
||||
lbs_deb_assoc("assoc: scanning for compatible AP\n");
|
||||
_internal_start_scan(priv, true, creq);
|
||||
|
||||
lbs_deb_assoc("assoc: waiting for scan to complete\n");
|
||||
wait_event_interruptible_timeout(priv->scan_q,
|
||||
(priv->scan_req == NULL),
|
||||
|
@ -179,7 +179,6 @@ struct lbs_private {
|
||||
wait_queue_head_t scan_q;
|
||||
/* Whether the scan was initiated internally and not by cfg80211 */
|
||||
bool internal_scan;
|
||||
unsigned long last_scan;
|
||||
};
|
||||
|
||||
extern struct cmd_confirm_sleep confirm_sleep;
|
||||
|
@ -768,6 +768,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
|
||||
struct mwifiex_bss_info bss_info;
|
||||
int ie_len;
|
||||
u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)];
|
||||
enum ieee80211_band band;
|
||||
|
||||
if (mwifiex_get_bss_info(priv, &bss_info))
|
||||
return -1;
|
||||
@ -780,9 +781,10 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
|
||||
bss_info.ssid.ssid_len);
|
||||
ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
|
||||
|
||||
band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
|
||||
chan = __ieee80211_get_channel(priv->wdev->wiphy,
|
||||
ieee80211_channel_to_frequency(bss_info.bss_chan,
|
||||
priv->curr_bss_params.band));
|
||||
band));
|
||||
|
||||
cfg80211_inform_bss(priv->wdev->wiphy, chan,
|
||||
bss_info.bssid, 0, WLAN_CAPABILITY_IBSS,
|
||||
@ -1219,6 +1221,9 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
|
||||
/* We are using custom domains */
|
||||
wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
|
||||
|
||||
/* Reserve space for bss band information */
|
||||
wdev->wiphy->bss_priv_size = sizeof(u8);
|
||||
|
||||
wdev->wiphy->reg_notifier = mwifiex_reg_notifier;
|
||||
|
||||
/* Set struct mwifiex_private pointer in wiphy_priv */
|
||||
|
@ -90,6 +90,9 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter,
|
||||
cmd_node->data_buf = NULL;
|
||||
cmd_node->wait_q_enabled = false;
|
||||
|
||||
if (cmd_node->cmd_skb)
|
||||
skb_trim(cmd_node->cmd_skb, 0);
|
||||
|
||||
if (cmd_node->resp_skb) {
|
||||
dev_kfree_skb_any(cmd_node->resp_skb);
|
||||
cmd_node->resp_skb = NULL;
|
||||
|
@ -958,7 +958,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *,
|
||||
int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
|
||||
u8 *bssid, s32 rssi, u8 *ie_buf,
|
||||
size_t ie_len, u16 beacon_period,
|
||||
u16 cap_info_bitmap,
|
||||
u16 cap_info_bitmap, u8 band,
|
||||
struct mwifiex_bssdescriptor *bss_desc);
|
||||
int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
|
||||
struct mwifiex_bssdescriptor *bss_entry,
|
||||
|
@ -532,7 +532,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
|
||||
|
||||
sband = priv->wdev->wiphy->bands[band];
|
||||
|
||||
for (i = 0; (i < sband->n_channels) ; i++, chan_idx++) {
|
||||
for (i = 0; (i < sband->n_channels) ; i++) {
|
||||
ch = &sband->channels[i];
|
||||
if (ch->flags & IEEE80211_CHAN_DISABLED)
|
||||
continue;
|
||||
@ -563,6 +563,7 @@ mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
|
||||
scan_chan_list[chan_idx].chan_scan_mode_bitmap
|
||||
|= MWIFIEX_DISABLE_CHAN_FILT;
|
||||
}
|
||||
chan_idx++;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1463,9 +1464,9 @@ int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
|
||||
}
|
||||
|
||||
static int
|
||||
mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
|
||||
u8 *bssid, s32 rssi, const u8 *ie_buf,
|
||||
size_t ie_len, u16 beacon_period, u16 cap_info_bitmap)
|
||||
mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
|
||||
s32 rssi, const u8 *ie_buf, size_t ie_len,
|
||||
u16 beacon_period, u16 cap_info_bitmap, u8 band)
|
||||
{
|
||||
struct mwifiex_bssdescriptor *bss_desc = NULL;
|
||||
int ret;
|
||||
@ -1488,7 +1489,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
|
||||
|
||||
ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie,
|
||||
ie_len, beacon_period,
|
||||
cap_info_bitmap, bss_desc);
|
||||
cap_info_bitmap, band, bss_desc);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
@ -1532,6 +1533,11 @@ done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mwifiex_free_bss_priv(struct cfg80211_bss *bss)
|
||||
{
|
||||
kfree(bss->priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the command response of scan.
|
||||
*
|
||||
@ -1570,6 +1576,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||
struct chan_band_param_set *chan_band;
|
||||
u8 is_bgscan_resp;
|
||||
unsigned long flags;
|
||||
struct cfg80211_bss *bss;
|
||||
|
||||
is_bgscan_resp = (le16_to_cpu(resp->command)
|
||||
== HostCmd_CMD_802_11_BG_SCAN_QUERY);
|
||||
@ -1751,10 +1758,12 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||
chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
|
||||
|
||||
if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
|
||||
cfg80211_inform_bss(priv->wdev->wiphy, chan,
|
||||
bssid, network_tsf, cap_info_bitmap,
|
||||
beacon_period, ie_buf, ie_len, rssi,
|
||||
GFP_KERNEL);
|
||||
bss = cfg80211_inform_bss(priv->wdev->wiphy,
|
||||
chan, bssid, network_tsf,
|
||||
cap_info_bitmap, beacon_period,
|
||||
ie_buf, ie_len, rssi, GFP_KERNEL);
|
||||
*(u8 *)bss->priv = band;
|
||||
bss->free_priv = mwifiex_free_bss_priv;
|
||||
|
||||
if (priv->media_connected && !memcmp(bssid,
|
||||
priv->curr_bss_params.bss_descriptor
|
||||
@ -1762,7 +1771,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||
mwifiex_update_curr_bss_params(priv,
|
||||
bssid, rssi, ie_buf,
|
||||
ie_len, beacon_period,
|
||||
cap_info_bitmap);
|
||||
cap_info_bitmap, band);
|
||||
}
|
||||
} else {
|
||||
dev_dbg(adapter->dev, "missing BSS channel IE\n");
|
||||
|
@ -148,7 +148,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
|
||||
int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
|
||||
u8 *bssid, s32 rssi, u8 *ie_buf,
|
||||
size_t ie_len, u16 beacon_period,
|
||||
u16 cap_info_bitmap,
|
||||
u16 cap_info_bitmap, u8 band,
|
||||
struct mwifiex_bssdescriptor *bss_desc)
|
||||
{
|
||||
int ret;
|
||||
@ -159,6 +159,7 @@ int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
|
||||
bss_desc->beacon_buf_size = ie_len;
|
||||
bss_desc->beacon_period = beacon_period;
|
||||
bss_desc->cap_info_bitmap = cap_info_bitmap;
|
||||
bss_desc->bss_band = band;
|
||||
if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
|
||||
dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
|
||||
bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
|
||||
@ -203,6 +204,7 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
|
||||
beacon_ie = kmemdup(bss->information_elements,
|
||||
bss->len_beacon_ies, GFP_KERNEL);
|
||||
if (!beacon_ie) {
|
||||
kfree(bss_desc);
|
||||
dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -210,7 +212,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
|
||||
ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
|
||||
beacon_ie, bss->len_beacon_ies,
|
||||
bss->beacon_interval,
|
||||
bss->capability, bss_desc);
|
||||
bss->capability,
|
||||
*(u8 *)bss->priv, bss_desc);
|
||||
if (ret)
|
||||
goto done;
|
||||
}
|
||||
@ -652,6 +655,7 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
|
||||
u16 curr_chan = 0;
|
||||
struct cfg80211_bss *bss = NULL;
|
||||
struct ieee80211_channel *chan;
|
||||
enum ieee80211_band band;
|
||||
|
||||
memset(&bss_info, 0, sizeof(bss_info));
|
||||
|
||||
@ -688,9 +692,9 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
|
||||
goto done;
|
||||
}
|
||||
|
||||
band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
|
||||
chan = __ieee80211_get_channel(priv->wdev->wiphy,
|
||||
ieee80211_channel_to_frequency(channel,
|
||||
priv->curr_bss_params.band));
|
||||
ieee80211_channel_to_frequency(channel, band));
|
||||
|
||||
/* Find the BSS we want using available scan results */
|
||||
bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
|
||||
@ -867,10 +871,10 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
|
||||
ret = mwifiex_rate_ioctl_cfg(priv, rate);
|
||||
|
||||
if (!ret) {
|
||||
if (rate && rate->is_rate_auto)
|
||||
if (rate->is_rate_auto)
|
||||
rate->rate = mwifiex_index_to_data_rate(priv->tx_rate,
|
||||
priv->tx_htinfo);
|
||||
else if (rate)
|
||||
else
|
||||
rate->rate = priv->data_rate;
|
||||
} else {
|
||||
ret = -1;
|
||||
|
@ -1239,7 +1239,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry,
|
||||
* call, we must decrease the higher 32bits with 1 to get
|
||||
* to correct value.
|
||||
*/
|
||||
tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw);
|
||||
tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw, NULL);
|
||||
rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME);
|
||||
rx_high = upper_32_bits(tsf);
|
||||
|
||||
@ -1673,7 +1673,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
u64 tsf;
|
||||
|
@ -1966,7 +1966,8 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* IEEE80211 stack callback functions.
|
||||
*/
|
||||
static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
u64 tsf;
|
||||
|
@ -4466,7 +4466,7 @@ int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_conf_tx);
|
||||
|
||||
u64 rt2800_get_tsf(struct ieee80211_hw *hw)
|
||||
u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
u64 tsf;
|
||||
|
@ -199,7 +199,7 @@ void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, u32 *iv32,
|
||||
int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value);
|
||||
int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
u64 rt2800_get_tsf(struct ieee80211_hw *hw);
|
||||
u64 rt2800_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
||||
int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn,
|
||||
|
@ -2940,7 +2940,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 rt61pci_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
u64 tsf;
|
||||
|
@ -2279,7 +2279,7 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 rt73usb_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
u64 tsf;
|
||||
|
@ -669,7 +669,8 @@ static void rtl8180_stop(struct ieee80211_hw *dev)
|
||||
rtl8180_free_tx_ring(dev, i);
|
||||
}
|
||||
|
||||
static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
|
||||
static u64 rtl8180_get_tsf(struct ieee80211_hw *dev,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl8180_priv *priv = dev->priv;
|
||||
|
||||
@ -701,7 +702,7 @@ static void rtl8180_beacon_work(struct work_struct *work)
|
||||
* TODO: make hardware update beacon timestamp
|
||||
*/
|
||||
mgmt = (struct ieee80211_mgmt *)skb->data;
|
||||
mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev));
|
||||
mgmt->u.beacon.timestamp = cpu_to_le64(rtl8180_get_tsf(dev, vif));
|
||||
|
||||
/* TODO: use actual beacon queue */
|
||||
skb_set_queue_mapping(skb, 0);
|
||||
|
@ -1277,7 +1277,7 @@ static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 rtl8187_get_tsf(struct ieee80211_hw *dev)
|
||||
static u64 rtl8187_get_tsf(struct ieee80211_hw *dev, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
|
||||
|
@ -775,7 +775,7 @@ out:
|
||||
mutex_unlock(&rtlpriv->locks.conf_mutex);
|
||||
}
|
||||
|
||||
static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
|
||||
static u64 rtl_op_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
u64 tsf;
|
||||
@ -784,7 +784,8 @@ static u64 rtl_op_get_tsf(struct ieee80211_hw *hw)
|
||||
return tsf;
|
||||
}
|
||||
|
||||
static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
static void rtl_op_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u64 tsf)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
@ -794,7 +795,8 @@ static void rtl_op_set_tsf(struct ieee80211_hw *hw, u64 tsf)
|
||||
rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_CORRECT_TSF, (u8 *) (&bibss));
|
||||
}
|
||||
|
||||
static void rtl_op_reset_tsf(struct ieee80211_hw *hw)
|
||||
static void rtl_op_reset_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
u8 tmp = 0;
|
||||
|
@ -133,6 +133,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
|
||||
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
|
||||
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
|
||||
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
|
||||
if (!rtlpriv->psc.inactiveps)
|
||||
pr_info("rtl8192ce: Power Save off (module option)\n");
|
||||
if (!rtlpriv->psc.fwctrl_lps)
|
||||
pr_info("rtl8192ce: FW Power Save off (module option)\n");
|
||||
rtlpriv->psc.reg_fwctrl_lps = 3;
|
||||
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
|
||||
/* for ASPM, you can close aspm through
|
||||
@ -356,10 +360,10 @@ module_param_named(swenc, rtl92ce_mod_params.sw_crypto, bool, 0444);
|
||||
module_param_named(ips, rtl92ce_mod_params.inactiveps, bool, 0444);
|
||||
module_param_named(swlps, rtl92ce_mod_params.swctrl_lps, bool, 0444);
|
||||
module_param_named(fwlps, rtl92ce_mod_params.fwctrl_lps, bool, 0444);
|
||||
MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
|
||||
MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
|
||||
MODULE_PARM_DESC(fwlps, "using linked fw control power save "
|
||||
"(default 1 is open)\n");
|
||||
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
|
||||
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
|
||||
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
|
||||
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
|
||||
|
||||
static struct pci_driver rtl92ce_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
|
@ -537,12 +537,6 @@ do { \
|
||||
memset(__pdesc, 0, _size); \
|
||||
} while (0);
|
||||
|
||||
#define RX_HAL_IS_CCK_RATE(_pdesc)\
|
||||
(_pdesc->rxmcs == DESC92_RATE1M || \
|
||||
_pdesc->rxmcs == DESC92_RATE2M || \
|
||||
_pdesc->rxmcs == DESC92_RATE5_5M || \
|
||||
_pdesc->rxmcs == DESC92_RATE11M)
|
||||
|
||||
struct rx_fwinfo_92c {
|
||||
u8 gain_trsw[4];
|
||||
u8 pwdb_all;
|
||||
|
@ -87,12 +87,6 @@ void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter);
|
||||
|
||||
u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw);
|
||||
|
||||
#define RX_HAL_IS_CCK_RATE(_pdesc)\
|
||||
(GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE1M ||\
|
||||
GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE2M ||\
|
||||
GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\
|
||||
GET_RX_DESC_RX_MCS(_pdesc) == DESC92_RATE11M)
|
||||
|
||||
struct rx_fwinfo_92c {
|
||||
u8 gain_trsw[4];
|
||||
u8 pwdb_all;
|
||||
|
@ -150,6 +150,10 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
|
||||
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
|
||||
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
|
||||
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
|
||||
if (!rtlpriv->psc.inactiveps)
|
||||
pr_info("rtl8192ce: Power Save off (module option)\n");
|
||||
if (!rtlpriv->psc.fwctrl_lps)
|
||||
pr_info("rtl8192ce: FW Power Save off (module option)\n");
|
||||
rtlpriv->psc.reg_fwctrl_lps = 3;
|
||||
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
|
||||
/* for ASPM, you can close aspm through
|
||||
@ -376,10 +380,10 @@ module_param_named(swenc, rtl92de_mod_params.sw_crypto, bool, 0444);
|
||||
module_param_named(ips, rtl92de_mod_params.inactiveps, bool, 0444);
|
||||
module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444);
|
||||
module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444);
|
||||
MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
|
||||
MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
|
||||
MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1"
|
||||
" is open)\n");
|
||||
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
|
||||
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
|
||||
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
|
||||
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
|
||||
|
||||
static struct pci_driver rtl92de_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
|
@ -537,12 +537,6 @@ do { \
|
||||
memset((void *)__pdesc, 0, _size); \
|
||||
} while (0);
|
||||
|
||||
#define RX_HAL_IS_CCK_RATE(_pdesc)\
|
||||
(_pdesc->rxmcs == DESC92_RATE1M || \
|
||||
_pdesc->rxmcs == DESC92_RATE2M || \
|
||||
_pdesc->rxmcs == DESC92_RATE5_5M || \
|
||||
_pdesc->rxmcs == DESC92_RATE11M)
|
||||
|
||||
/* For 92D early mode */
|
||||
#define SET_EARLYMODE_PKTNUM(__paddr, __value) \
|
||||
SET_BITS_OFFSET_LE(__paddr, 0, 3, __value)
|
||||
|
@ -459,7 +459,7 @@ do { \
|
||||
#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \
|
||||
SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
|
||||
|
||||
#define RX_HAL_IS_CCK_RATE(_pdesc)\
|
||||
#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
|
||||
(GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \
|
||||
GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE2M || \
|
||||
GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE5_5M ||\
|
||||
|
@ -164,6 +164,10 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
|
||||
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
|
||||
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
|
||||
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
|
||||
if (!rtlpriv->psc.inactiveps)
|
||||
pr_info("rtl8192ce: Power Save off (module option)\n");
|
||||
if (!rtlpriv->psc.fwctrl_lps)
|
||||
pr_info("rtl8192ce: FW Power Save off (module option)\n");
|
||||
rtlpriv->psc.reg_fwctrl_lps = 3;
|
||||
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
|
||||
/* for ASPM, you can close aspm through
|
||||
@ -378,6 +382,7 @@ MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids);
|
||||
|
||||
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
|
||||
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
|
||||
MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless");
|
||||
MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin");
|
||||
@ -386,11 +391,10 @@ module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444);
|
||||
module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444);
|
||||
module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444);
|
||||
module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444);
|
||||
MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
|
||||
MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
|
||||
MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is "
|
||||
"open)\n");
|
||||
|
||||
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
|
||||
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
|
||||
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
|
||||
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
|
||||
|
||||
static struct pci_driver rtl92se_driver = {
|
||||
.name = KBUILD_MODNAME,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user