“9e50ab91d025afc17ca14a1764be2e1d0c24245d”上不存在“README.md”
提交 ba6e5eb1 编写于 作者: J John W. Linville

Merge branch 'master' of...

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
......@@ -1230,7 +1230,7 @@ F: Documentation/aoe/
F: drivers/block/aoe/
ATHEROS ATH GENERIC UTILITIES
M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/ath/*
......@@ -1238,7 +1238,7 @@ F: drivers/net/wireless/ath/*
ATHEROS ATH5K WIRELESS DRIVER
M: Jiri Slaby <jirislaby@gmail.com>
M: Nick Kossifidis <mickflemm@gmail.com>
M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
M: Bob Copeland <me@bobcopeland.com>
L: linux-wireless@vger.kernel.org
L: ath5k-devel@lists.ath5k.org
......@@ -1247,10 +1247,10 @@ S: Maintained
F: drivers/net/wireless/ath/ath5k/
ATHEROS ATH9K WIRELESS DRIVER
M: "Luis R. Rodriguez" <lrodriguez@atheros.com>
M: Jouni Malinen <jmalinen@atheros.com>
M: Vasanthakumar Thiagarajan <vasanth@atheros.com>
M: Senthil Balasubramanian <senthilkumar@atheros.com>
M: "Luis R. Rodriguez" <mcgrof@qca.qualcomm.com>
M: Jouni Malinen <jouni@qca.qualcomm.com>
M: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
M: Senthil Balasubramanian <senthilb@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
L: ath9k-devel@lists.ath9k.org
W: http://wireless.kernel.org/en/users/Drivers/ath9k
......@@ -1278,7 +1278,7 @@ F: drivers/input/misc/ati_remote2.c
ATLX ETHERNET DRIVERS
M: Jay Cliburn <jcliburn@gmail.com>
M: Chris Snook <chris.snook@gmail.com>
M: Jie Yang <jie.yang@atheros.com>
M: Jie Yang <yangjie@qca.qualcomm.com>
L: netdev@vger.kernel.org
W: http://sourceforge.net/projects/atl1
W: http://atl1.sourceforge.net
......@@ -4503,6 +4503,17 @@ W: http://www.qlogic.com
S: Supported
F: drivers/net/ethernet/qlogic/netxen/
NFC SUBSYSTEM
M: Lauro Ramos Venancio <lauro.venancio@openbossa.org>
M: Aloisio Almeida Jr <aloisio.almeida@openbossa.org>
M: Samuel Ortiz <sameo@linux.intel.com>
L: linux-wireless@vger.kernel.org
S: Maintained
F: net/nfc/
F: include/linux/nfc.h
F: include/net/nfc.h
F: drivers/nfc/
NFS, SUNRPC, AND LOCKD CLIENTS
M: Trond Myklebust <Trond.Myklebust@netapp.com>
L: linux-nfs@vger.kernel.org
......
......@@ -90,6 +90,24 @@ void bcma_pmu_swreg_init(struct bcma_drv_cc *cc)
}
}
/* Disable to allow reading SPROM. Don't know the adventages of enabling it. */
void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable)
{
struct bcma_bus *bus = cc->core->bus;
u32 val;
val = bcma_cc_read32(cc, BCMA_CC_CHIPCTL);
if (enable) {
val |= BCMA_CHIPCTL_4331_EXTPA_EN;
if (bus->chipinfo.pkg == 9 || bus->chipinfo.pkg == 11)
val |= BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
} else {
val &= ~BCMA_CHIPCTL_4331_EXTPA_EN;
val &= ~BCMA_CHIPCTL_4331_EXTPA_ON_GPIO2_5;
}
bcma_cc_write32(cc, BCMA_CC_CHIPCTL, val);
}
void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
{
struct bcma_bus *bus = cc->core->bus;
......@@ -99,7 +117,7 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7);
break;
case 0x4331:
pr_err("Enabling Ext PA lines not implemented\n");
/* BCM4331 workaround is SPROM-related, we put it in sprom.c */
break;
case 43224:
if (bus->chipinfo.rev == 0) {
......
......@@ -281,7 +281,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
/* get & parse master ports */
for (i = 0; i < ports[0]; i++) {
u32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
s32 mst_port_d = bcma_erom_get_mst_port(bus, eromptr);
if (mst_port_d < 0)
return -EILSEQ;
}
......
......@@ -152,6 +152,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
if (!sprom)
return -ENOMEM;
if (bus->chipinfo.id == 0x4331)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false);
/* Most cards have SPROM moved by additional offset 0x30 (48 dwords).
* According to brcm80211 this applies to cards with PCIe rev >= 6
* TODO: understand this condition and use it */
......@@ -159,6 +162,9 @@ int bcma_sprom_get(struct bcma_bus *bus)
BCMA_CC_SPROM_PCIE6;
bcma_sprom_read(bus, offset, sprom);
if (bus->chipinfo.id == 0x4331)
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
err = bcma_sprom_valid(sprom);
if (err)
goto out;
......
......@@ -303,17 +303,13 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
int restore,
int power_off)
bool power_off)
{
u8 i;
u32 val;
if (ah->is_pciexpress != true || ah->aspm_enabled != true)
return;
/* Nothing to do on restore for 11N */
if (!restore) {
if (!power_off /* !restore */) {
if (AR_SREV_9280_20_OR_LATER(ah)) {
/*
* AR9280 2.0 or later chips use SerDes values from the
......
......@@ -636,7 +636,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
{0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
{0x0000a204, 0x000036c0, 0x000036c4, 0x000036c4, 0x000036c0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
{0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
......
......@@ -839,20 +839,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_capabilities *pCap = &ah->caps;
int val;
bool txiqcal_done = false;
val = REG_READ(ah, AR_ENT_OTP);
ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val);
/* Configure rx/tx chains before running AGC/TxiQ cals */
if (val & AR_ENT_OTP_CHAIN2_DISABLE)
ar9003_hw_set_chain_masks(ah, 0x3, 0x3);
else
ar9003_hw_set_chain_masks(ah, pCap->rx_chainmask,
pCap->tx_chainmask);
/* Do Tx IQ Calibration */
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
......@@ -887,9 +875,6 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
if (txiqcal_done)
ar9003_hw_tx_iq_cal_post_proc(ah);
/* Revert chainmasks to their original values before NF cal */
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
ath9k_hw_start_nfcal(ah, true);
/* Initialize list pointers */
......
......@@ -21,6 +21,7 @@
#include "ar9340_initvals.h"
#include "ar9330_1p1_initvals.h"
#include "ar9330_1p2_initvals.h"
#include "ar9580_1p0_initvals.h"
/* General hardware code for the AR9003 hadware family */
......@@ -253,6 +254,56 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ar9485_1_1_pcie_phy_clkreq_disable_L1,
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
2);
} else if (AR_SREV_9580(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9580_1p0_mac_core,
ARRAY_SIZE(ar9580_1p0_mac_core), 2);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9580_1p0_mac_postamble,
ARRAY_SIZE(ar9580_1p0_mac_postamble), 5);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9580_1p0_baseband_core,
ARRAY_SIZE(ar9580_1p0_baseband_core), 2);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9580_1p0_baseband_postamble,
ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9580_1p0_radio_core,
ARRAY_SIZE(ar9580_1p0_radio_core), 2);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9580_1p0_radio_postamble,
ARRAY_SIZE(ar9580_1p0_radio_postamble), 5);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9580_1p0_soc_preamble,
ARRAY_SIZE(ar9580_1p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9580_1p0_soc_postamble,
ARRAY_SIZE(ar9580_1p0_soc_postamble), 5);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5);
INIT_INI_ARRAY(&ah->iniModesAdditional,
ar9580_1p0_modes_fast_clock,
ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
3);
} else {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
......@@ -348,6 +399,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
ar9485_modes_lowest_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
......@@ -375,6 +431,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
ar9485Modes_high_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p2,
......@@ -402,6 +463,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
ar9485Modes_low_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p2,
......@@ -429,6 +495,11 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
ar9485Modes_high_power_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
5);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_power_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
5);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_power_tx_gain_table_2p2,
......@@ -463,6 +534,11 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_rx_gain_table),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2,
......@@ -490,6 +566,11 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p2,
......@@ -516,14 +597,10 @@ static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
* register as the other analog registers. Hence the 9 writes.
*/
static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
int restore,
int power_off)
bool power_off)
{
if (ah->is_pciexpress != true || ah->aspm_enabled != true)
return;
/* Nothing to do on restore for 11N */
if (!restore) {
if (!power_off /* !restore */) {
/* set bit 19 to allow forcing of pcie core into L1 state */
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
......
......@@ -253,8 +253,6 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
return -EIO;
}
if (status & AR_TxOpExceeded)
ts->ts_status |= ATH9K_TXERR_XTXOP;
ts->ts_rateindex = MS(status, AR_FinalTxIdx);
ts->ts_seqnum = MS(status, AR_SeqNum);
ts->tid = MS(status, AR_TxTid);
......@@ -264,6 +262,8 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_status = 0;
ts->ts_flags = 0;
if (status & AR_TxOpExceeded)
ts->ts_status |= ATH9K_TXERR_XTXOP;
status = ACCESS_ONCE(ads->status2);
ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
......@@ -415,36 +415,12 @@ static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds,
static void ar9003_hw_set11n_aggr_first(struct ath_hw *ah, void *ds,
u32 aggrLen)
{
#define FIRST_DESC_NDELIMS 60
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
ads->ctl12 |= (AR_IsAggr | AR_MoreAggr);
if (ah->ent_mode & AR_ENT_OTP_MPSD) {
u32 ctl17, ndelim;
/*
* Add delimiter when using RTS/CTS with aggregation
* and non enterprise AR9003 card
*/
ctl17 = ads->ctl17;
ndelim = MS(ctl17, AR_PadDelim);
if (ndelim < FIRST_DESC_NDELIMS) {
aggrLen += (FIRST_DESC_NDELIMS - ndelim) * 4;
ndelim = FIRST_DESC_NDELIMS;
}
ctl17 &= ~AR_AggrLen;
ctl17 |= SM(aggrLen, AR_AggrLen);
ctl17 &= ~AR_PadDelim;
ctl17 |= SM(ndelim, AR_PadDelim);
ads->ctl17 = ctl17;
} else {
ads->ctl17 &= ~AR_AggrLen;
ads->ctl17 |= SM(aggrLen, AR_AggrLen);
}
ads->ctl17 &= ~AR_AggrLen;
ads->ctl17 |= SM(aggrLen, AR_AggrLen);
}
static void ar9003_hw_set11n_aggr_middle(struct ath_hw *ah, void *ds,
......
......@@ -482,7 +482,7 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
(REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
/* Enable 11n HT, 20 MHz */
phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 | AR_PHY_GC_WALSH |
phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 |
AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
/* Configure baseband for dynamic 20/40 operation */
......@@ -540,7 +540,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
udelay(synthDelay + BASE_ACTIVATE_DELAY);
}
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
{
switch (rx) {
case 0x5:
......
......@@ -1124,6 +1124,4 @@
#define AR_PHY_CL_TAB_CL_GAIN_MOD 0x1f
#define AR_PHY_CL_TAB_CL_GAIN_MOD_S 0
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
#endif /* AR9003_PHY_H */
此差异已折叠。
......@@ -558,8 +558,7 @@ struct ath_ant_comb {
#define SC_OP_BT_PRIORITY_DETECTED BIT(12)
#define SC_OP_BT_SCAN BIT(13)
#define SC_OP_ANI_RUN BIT(14)
#define SC_OP_ENABLE_APM BIT(15)
#define SC_OP_PRIM_STA_VIF BIT(16)
#define SC_OP_PRIM_STA_VIF BIT(15)
/* Powersave flags */
#define PS_WAIT_FOR_BEACON BIT(0)
......@@ -664,7 +663,6 @@ extern int led_blink;
extern bool is_ath9k_unloaded;
irqreturn_t ath_isr(int irq, void *dev);
void ath9k_init_crypto(struct ath_softc *sc);
int ath9k_init_device(u16 devid, struct ath_softc *sc,
const struct ath_bus_ops *bus_ops);
void ath9k_deinit_device(struct ath_softc *sc);
......
......@@ -82,7 +82,6 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
int16_t *nfarray)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
struct ath_nf_limits *limit;
struct ath9k_nfcal_hist *h;
bool high_nf_mid = false;
......@@ -94,7 +93,7 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
continue;
h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
......
......@@ -169,6 +169,32 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
}
EXPORT_SYMBOL(ath9k_cmn_update_txpow);
void ath9k_cmn_init_crypto(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
int i = 0;
/* Get the hardware key cache size. */
common->keymax = AR_KEYTABLE_SIZE;
/*
* Check whether the separate key cache entries
* are required to handle both tx+rx MIC keys.
* With split mic keys the number of stations is limited
* to 27 otherwise 59.
*/
if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
/*
* Reset the key cache since some parts do not
* reset the contents on initial power up.
*/
for (i = 0; i < common->keymax; i++)
ath_hw_keyreset(common, (u16) i);
}
EXPORT_SYMBOL(ath9k_cmn_init_crypto);
static int __init ath9k_cmn_init(void)
{
return 0;
......
......@@ -62,3 +62,4 @@ void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
enum ath_stomp_type stomp_type);
void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
u16 new_txpow, u16 *txpower);
void ath9k_cmn_init_crypto(struct ath_hw *ah);
......@@ -1163,6 +1163,59 @@ static const struct file_operations fops_regdump = {
.llseek = default_llseek,/* read accesses f_pos */
};
static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
u32 len = 0, size = 1500;
u32 i, j;
ssize_t retval = 0;
char *buf;
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
u8 nread;
buf = kzalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
len += snprintf(buf + len, size - len,
"Channel Noise Floor : %d\n", ah->noise);
len += snprintf(buf + len, size - len,
"Chain | privNF | # Readings | NF Readings\n");
for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
continue;
nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
len += snprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
i, h[i].privNF, nread);
for (j = 0; j < nread; j++)
len += snprintf(buf + len, size - len,
" %d", h[i].nfCalBuffer[j]);
len += snprintf(buf + len, size - len, "\n");
}
if (len > size)
len = size;
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
kfree(buf);
return retval;
}
static const struct file_operations fops_dump_nfcal = {
.read = read_file_dump_nfcal,
.open = ath9k_debugfs_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
......@@ -1262,6 +1315,8 @@ int ath9k_init_debug(struct ath_hw *ah)
&ah->config.cwm_ignore_extcca);
debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_regdump);
debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dump_nfcal);
debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_base_eeprom);
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
......
......@@ -572,25 +572,6 @@ static int ath9k_init_queues(struct ath9k_htc_priv *priv)
return -EINVAL;
}
static void ath9k_init_crypto(struct ath9k_htc_priv *priv)
{
struct ath_common *common = ath9k_hw_common(priv->ah);
int i = 0;
/* Get the hardware key cache size. */
common->keymax = AR_KEYTABLE_SIZE;
if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
/*
* Reset the key cache since some parts do not
* reset the contents on initial power up.
*/
for (i = 0; i < common->keymax; i++)
ath_hw_keyreset(common, (u16) i);
}
static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv)
{
if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
......@@ -720,7 +701,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
for (i = 0; i < ATH9K_HTC_MAX_BCN_VIF; i++)
priv->cur_beacon_conf.bslot[i] = NULL;
ath9k_init_crypto(priv);
ath9k_cmn_init_crypto(ah);
ath9k_init_channels_rates(priv);
ath9k_init_misc(priv);
......
......@@ -1736,6 +1736,22 @@ static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw,
return ret;
}
static int ath9k_htc_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;
stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
stats->dot11RTSFailureCount = mib_stats->rts_bad;
stats->dot11FCSErrorCount = mib_stats->fcs_bad;
stats->dot11RTSSuccessCount = mib_stats->rts_good;
return 0;
}
struct ieee80211_ops ath9k_htc_ops = {
.tx = ath9k_htc_tx,
.start = ath9k_htc_start,
......@@ -1759,4 +1775,5 @@ struct ieee80211_ops ath9k_htc_ops = {
.rfkill_poll = ath9k_htc_rfkill_poll_state,
.set_coverage_class = ath9k_htc_set_coverage_class,
.set_bitrate_mask = ath9k_htc_set_bitrate_mask,
.get_stats = ath9k_htc_get_stats,
};
......@@ -22,10 +22,12 @@
/* Hardware core and driver accessible callbacks */
static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah,
int restore,
int power_off)
bool power_off)
{
ath9k_hw_ops(ah)->config_pci_powersave(ah, restore, power_off);
if (ah->aspm_enabled != true)
return;
ath9k_hw_ops(ah)->config_pci_powersave(ah, power_off);
}
static inline void ath9k_hw_rxena(struct ath_hw *ah)
......
......@@ -603,10 +603,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_mode_regs(ah);
if (ah->is_pciexpress)
ath9k_hw_aspm_init(ah);
else
if (!ah->is_pciexpress)
ath9k_hw_disablepcie(ah);
if (!AR_SREV_9300_20_OR_LATER(ah))
......@@ -621,6 +618,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (r)
return r;
if (ah->is_pciexpress)
ath9k_hw_aspm_init(ah);
r = ath9k_hw_init_macaddr(ah);
if (r) {
ath_err(common, "Failed to initialize MAC address\n");
......@@ -663,6 +663,7 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR9300_DEVID_AR9485_PCIE:
case AR9300_DEVID_AR9330:
case AR9300_DEVID_AR9340:
case AR9300_DEVID_AR9580:
break;
default:
if (common->bus_ops->ath_bus_type == ATH_USB)
......@@ -996,7 +997,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
slottime = 21;
sifstime = 64;
} else {
eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS);
eifs = REG_READ(ah, AR_D_GBL_IFS_EIFS)/common->clockrate;
reg = REG_READ(ah, AR_USEC);
rx_lat = MS(reg, AR_USEC_RX_LAT);
tx_lat = MS(reg, AR_USEC_TX_LAT);
......
......@@ -45,6 +45,7 @@
#define AR9300_DEVID_PCIE 0x0030
#define AR9300_DEVID_AR9340 0x0031
#define AR9300_DEVID_AR9485_PCIE 0x0032
#define AR9300_DEVID_AR9580 0x0033
#define AR9300_DEVID_AR9330 0x0035
#define AR5416_AR9100_DEVID 0x000b
......@@ -606,8 +607,7 @@ struct ath_hw_private_ops {
*/
struct ath_hw_ops {
void (*config_pci_powersave)(struct ath_hw *ah,
int restore,
int power_off);
bool power_off);
void (*rx_enable)(struct ath_hw *ah);
void (*set_desc_link)(void *ds, u32 link);
bool (*calibrate)(struct ath_hw *ah,
......@@ -1037,10 +1037,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
void ath9k_hw_proc_mib_event(struct ath_hw *ah);
void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
#define ATH_PCIE_CAP_LINK_CTRL 0x70
#define ATH_PCIE_CAP_LINK_L0S 1
#define ATH_PCIE_CAP_LINK_L1 2
#define ATH9K_CLOCK_RATE_CCK 22
#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
......
......@@ -404,31 +404,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
return error;
}
void ath9k_init_crypto(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int i = 0;
/* Get the hardware key cache size. */
common->keymax = AR_KEYTABLE_SIZE;
/*
* Reset the key cache since some parts do not
* reset the contents on initial power up.
*/
for (i = 0; i < common->keymax; i++)
ath_hw_keyreset(common, (u16) i);
/*
* Check whether the separate key cache entries
* are required to handle both tx+rx MIC keys.
* With split mic keys the number of stations is limited
* to 27 otherwise 59.
*/
if (sc->sc_ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
}
static int ath9k_init_btcoex(struct ath_softc *sc)
{
struct ath_txq *txq;
......@@ -630,7 +605,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
if (ret)
goto err_btcoex;
ath9k_init_crypto(sc);
ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_init_misc(sc);
return 0;
......
......@@ -345,21 +345,8 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
}
memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
qi->tqi_type = type;
if (qinfo == NULL) {
qi->tqi_qflags =
TXQ_FLAG_TXOKINT_ENABLE
| TXQ_FLAG_TXERRINT_ENABLE
| TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
qi->tqi_aifs = INIT_AIFS;
qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
qi->tqi_cwmax = INIT_CWMAX;
qi->tqi_shretry = INIT_SH_RETRY;
qi->tqi_lgretry = INIT_LG_RETRY;
qi->tqi_physCompBuf = 0;
} else {
qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
(void) ath9k_hw_set_txq_props(ah, q, qinfo);
}
qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
(void) ath9k_hw_set_txq_props(ah, q, qinfo);
return q;
}
......@@ -564,7 +551,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
EXPORT_SYMBOL(ath9k_hw_resettxqueue);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
struct ath_rx_status *rs, u64 tsf)
struct ath_rx_status *rs)
{
struct ar5416_desc ads;
struct ar5416_desc *adsp = AR5416DESC(ds);
......
......@@ -687,7 +687,7 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
struct ath_rx_status *rs, u64 tsf);
struct ath_rx_status *rs);
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags);
bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
......
......@@ -565,7 +565,6 @@ void ath_ani_calibrate(unsigned long data)
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_node *an;
struct ath_hw *ah = sc->sc_ah;
an = (struct ath_node *)sta->drv_priv;
#ifdef CONFIG_ATH9K_DEBUGFS
......@@ -574,9 +573,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
spin_unlock(&sc->nodes_lock);
an->sta = sta;
#endif
if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
sc->sc_flags |= SC_OP_ENABLE_APM;
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
......@@ -826,11 +822,9 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & ATH9K_INT_TXURN)
ath9k_hw_updatetxtriglevel(ah, true);
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
if (status & ATH9K_INT_RXEOL) {
ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
ath9k_hw_set_interrupts(ah, ah->imask);
}
if (status & ATH9K_INT_RXEOL) {
ah->imask &= ~(ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
ath9k_hw_set_interrupts(ah, ah->imask);
}
if (status & ATH9K_INT_MIB) {
......@@ -888,7 +882,7 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
spin_lock_bh(&sc->sc_pcu_lock);
atomic_set(&ah->intr_ref_cnt, -1);
ath9k_hw_configpcipowersave(ah, 0, 0);
ath9k_hw_configpcipowersave(ah, false);
if (!ah->curchan)
ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
......@@ -969,7 +963,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath9k_hw_phy_disable(ah);
ath9k_hw_configpcipowersave(ah, 1, 1);
ath9k_hw_configpcipowersave(ah, true);
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
......@@ -1069,7 +1063,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
init_channel = ath9k_cmn_get_curchannel(hw, ah);
/* Reset SERDES registers */
ath9k_hw_configpcipowersave(ah, 0, 0);
ath9k_hw_configpcipowersave(ah, false);
/*
* The basic interface to setting the hardware in a good
......@@ -1145,8 +1139,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
AR_STOMP_LOW_WLAN_WGHT);
ath9k_hw_btcoex_enable(ah);
if (common->bus_ops->bt_coex_prep)
common->bus_ops->bt_coex_prep(common);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_resume(sc);
}
......@@ -1680,6 +1672,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
struct ath9k_channel old_chan;
int pos = curchan->hw_value;
int old_pos = -1;
unsigned long flags;
......@@ -1696,14 +1689,24 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
"Set channel: %d MHz type: %d\n",
curchan->center_freq, conf->channel_type);
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
curchan, conf->channel_type);
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
ath_update_survey_stats(sc);
spin_unlock_irqrestore(&common->cc_lock, flags);
/*
* Preserve the current channel values, before updating
* the same channel
*/
if (old_pos == pos) {
memcpy(&old_chan, &sc->sc_ah->channels[pos],
sizeof(struct ath9k_channel));
ah->curchan = &old_chan;
}
ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
curchan, conf->channel_type);
/*
* If the operating channel changes, change the survey in-use flags
* along with it.
......@@ -2400,6 +2403,20 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
return sc->beacon.tx_last;
}
static int ath9k_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath9k_mib_stats *mib_stats = &ah->ah_mibStats;
stats->dot11ACKFailureCount = mib_stats->ackrcv_bad;
stats->dot11RTSFailureCount = mib_stats->rts_bad;
stats->dot11FCSErrorCount = mib_stats->fcs_bad;
stats->dot11RTSSuccessCount = mib_stats->rts_good;
return 0;
}
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
......@@ -2424,5 +2441,6 @@ struct ieee80211_ops ath9k_ops = {
.set_coverage_class = ath9k_set_coverage_class,
.flush = ath9k_flush,
.tx_frames_pending = ath9k_tx_frames_pending,
.tx_last_beacon = ath9k_tx_last_beacon,
.tx_last_beacon = ath9k_tx_last_beacon,
.get_stats = ath9k_get_stats,
};
......@@ -32,9 +32,11 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = {
{ PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */
{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */
{ 0 }
};
/* return bus cachesize in 4B word units */
static void ath_pci_read_cachesize(struct ath_common *common, int *csz)
{
......@@ -88,23 +90,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
return true;
}
/*
* Bluetooth coexistance requires disabling ASPM.
*/
static void ath_pci_bt_coex_prep(struct ath_common *common)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
struct pci_dev *pdev = to_pci_dev(sc->dev);
u8 aspm;
if (!pci_is_pcie(pdev))
return;
pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);
aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1);
pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
}
static void ath_pci_extn_synch_enable(struct ath_common *common)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
......@@ -116,6 +101,7 @@ static void ath_pci_extn_synch_enable(struct ath_common *common)
pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
}
/* Need to be called after we discover btcoex capabilities */
static void ath_pci_aspm_init(struct ath_common *common)
{
struct ath_softc *sc = (struct ath_softc *) common->priv;
......@@ -125,19 +111,38 @@ static void ath_pci_aspm_init(struct ath_common *common)
int pos;
u8 aspm;
if (!pci_is_pcie(pdev))
pos = pci_pcie_cap(pdev);
if (!pos)
return;
parent = pdev->bus->self;
if (WARN_ON(!parent))
if (!parent)
return;
if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) {
/* Bluetooth coexistance requires disabling ASPM. */
pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);
/*
* Both upstream and downstream PCIe components should
* have the same ASPM settings.
*/
pos = pci_pcie_cap(parent);
pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm);
return;
}
pos = pci_pcie_cap(parent);
pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
ah->aspm_enabled = true;
/* Initialize PCIe PM and SERDES registers. */
ath9k_hw_configpcipowersave(ah, 0, 0);
ath9k_hw_configpcipowersave(ah, false);
}
}
......@@ -145,7 +150,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
.ath_bus_type = ATH_PCI,
.read_cachesize = ath_pci_read_cachesize,
.eeprom_read = ath_pci_eeprom_read,
.bt_coex_prep = ath_pci_bt_coex_prep,
.extn_synch_en = ath_pci_extn_synch_enable,
.aspm_init = ath_pci_aspm_init,
};
......@@ -338,7 +342,7 @@ static int ath_pci_resume(struct device *device)
* semi-random values after suspend/resume.
*/
ath9k_ps_wakeup(sc);
ath9k_init_crypto(sc);
ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_ps_restore(sc);
sc->ps_idle = true;
......
......@@ -603,7 +603,8 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
struct ath_rate_priv *ath_rc_priv,
const struct ath_rate_table *rate_table,
int *is_probing)
int *is_probing,
bool legacy)
{
u32 best_thruput, this_thruput, now_msec;
u8 rate, next_rate, best_rate, maxindex, minindex;
......@@ -624,6 +625,8 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
u8 per_thres;
rate = ath_rc_priv->valid_rate_index[index];
if (legacy && !(rate_table->info[rate].rate_flags & RC_LEGACY))
continue;
if (rate > ath_rc_priv->rate_max_phy)
continue;
......@@ -767,7 +770,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
struct ieee80211_tx_rate *rates = tx_info->control.rates;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
u8 try_per_rate, i = 0, rix;
u8 try_per_rate, i = 0, rix, high_rix;
int is_probe = 0;
if (rate_control_send_low(sta, priv_sta, txrc))
......@@ -786,7 +789,9 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
try_per_rate = 4;
rate_table = ath_rc_priv->rate_table;
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
&is_probe, false);
high_rix = rix;
/*
* If we're in HT mode and both us and our peer supports LDPC.
......@@ -822,10 +827,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
}
/* Fill in the other rates for multirate retry */
for ( ; i < 4; i++) {
/* Use twice the number of tries for the last MRR segment. */
if (i + 1 == 4)
try_per_rate = 8;
for ( ; i < 3; i++) {
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
/* All other rates in the series have RTS enabled */
......@@ -833,6 +835,24 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
try_per_rate, rix, 1);
}
/* Use twice the number of tries for the last MRR segment. */
try_per_rate = 8;
/*
* Use a legacy rate as last retry to ensure that the frame
* is tried in both MCS and legacy rates.
*/
if ((rates[2].flags & IEEE80211_TX_RC_MCS) &&
(!(tx_info->flags & IEEE80211_TX_CTL_AMPDU) ||
(ath_rc_priv->per[high_rix] > 45)))
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table,
&is_probe, true);
else
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
/* All other rates in the series have RTS enabled */
ath_rc_rate_set_series(rate_table, &rates[i], txrc,
try_per_rate, rix, 1);
/*
* NB:Change rate series to enable aggregation when operating
* at lower MCS rates. When first rate in series is MCS2
......
......@@ -761,7 +761,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
ret = ath9k_hw_rxprocdesc(ah, ds, rs, 0);
ret = ath9k_hw_rxprocdesc(ah, ds, rs);
if (ret == -EINPROGRESS) {
struct ath_rx_status trs;
struct ath_buf *tbf;
......@@ -787,7 +787,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
*/
tds = tbf->bf_desc;
ret = ath9k_hw_rxprocdesc(ah, tds, &trs, 0);
ret = ath9k_hw_rxprocdesc(ah, tds, &trs);
if (ret == -EINPROGRESS)
return NULL;
}
......@@ -824,7 +824,8 @@ static bool ath9k_rx_accept(struct ath_common *common,
is_mc = !!is_multicast_ether_addr(hdr->addr1);
is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
test_bit(rx_stats->rs_keyix, common->tkip_keymap);
strip_mic = is_valid_tkip && !(rx_stats->rs_status &
strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
!(rx_stats->rs_status &
(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC));
if (!rx_stats->rs_datalen)
......@@ -1978,5 +1979,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
spin_unlock_bh(&sc->rx.rxbuflock);
if (!(ah->imask & ATH9K_INT_RXEOL)) {
ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
ath9k_hw_set_interrupts(ah, ah->imask);
}
return 0;
}
......@@ -793,6 +793,8 @@
#define AR_SREV_REVISION_9485_10 0
#define AR_SREV_REVISION_9485_11 1
#define AR_SREV_VERSION_9340 0x300
#define AR_SREV_VERSION_9580 0x1C0
#define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
......@@ -893,6 +895,18 @@
(AR_SREV_9285_12_OR_LATER(_ah) && \
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
#define AR_SREV_9580(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9580_10))
#define AR_SREV_9580_10(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9580) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9580_10))
/* NOTE: When adding chips newer than Peacock, add chip check here */
#define AR_SREV_9580_10_OR_LATER(_ah) \
(AR_SREV_9580(_ah))
enum ath_usb_dev {
AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
......
......@@ -571,6 +571,25 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_reset(sc, false);
}
static bool ath_lookup_legacy(struct ath_buf *bf)
{
struct sk_buff *skb;
struct ieee80211_tx_info *tx_info;
struct ieee80211_tx_rate *rates;
int i;
skb = bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
rates = tx_info->control.rates;
for (i = 3; i >= 0; i--) {
if (!(rates[i].flags & IEEE80211_TX_RC_MCS))
return true;
}
return false;
}
static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ath_atx_tid *tid)
{
......@@ -644,8 +663,10 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
* meet the minimum required mpdudensity.
*/
static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
struct ath_buf *bf, u16 frmlen)
struct ath_buf *bf, u16 frmlen,
bool first_subfrm)
{
#define FIRST_DESC_NDELIMS 60
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols;
......@@ -667,6 +688,13 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
ndelim += ATH_AGGR_ENCRYPTDELIM;
/*
* Add delimiter when using RTS/CTS with aggregation
* and non enterprise AR9003 card
*/
if (first_subfrm)
ndelim = max(ndelim, FIRST_DESC_NDELIMS);
/*
* Convert desired mpdu density from microeconds to bytes based
* on highest rate in rate series (i.e. first rate) to determine
......@@ -741,7 +769,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
al_delta = ATH_AGGR_DELIM_SZ + fi->framelen;
if (nframes &&
(aggr_limit < (al + bpad + al_delta + prev_al))) {
((aggr_limit < (al + bpad + al_delta + prev_al)) ||
ath_lookup_legacy(bf))) {
status = ATH_AGGR_LIMITED;
break;
}
......@@ -756,7 +785,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
status = ATH_AGGR_LIMITED;
break;
}
nframes++;
/* add padding for previous frame to aggregation length */
al += bpad + al_delta;
......@@ -765,9 +793,11 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
* Get the delimiters needed to meet the MPDU
* density for this node.
*/
ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen);
ndelim = ath_compute_num_delims(sc, tid, bf_first, fi->framelen,
!nframes);
bpad = PADBYTES(al_delta) + (ndelim << 2);
nframes++;
bf->bf_next = NULL;
ath9k_hw_set_desc_link(sc->sc_ah, bf->bf_desc, 0);
......@@ -1574,9 +1604,9 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_channel *curchan = ah->curchan;
if ((sc->sc_flags & SC_OP_ENABLE_APM) &&
(curchan->channelFlags & CHANNEL_5GHZ) &&
(chainmask == 0x7) && (rate < 0x90))
if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) &&
(curchan->channelFlags & CHANNEL_5GHZ) &&
(chainmask == 0x7) && (rate < 0x90))
return 0x3;
else
return chainmask;
......
......@@ -39,3 +39,17 @@ config CARL9170_WPC
bool
depends on CARL9170 && (INPUT = y || INPUT = CARL9170)
default y
config CARL9170_HWRNG
bool "Random number generator"
depends on CARL9170 && (HW_RANDOM = y || HW_RANDOM = CARL9170)
default n
help
Provides a hardware random number generator to the kernel.
SECURITY WARNING: It's relatively easy to eavesdrop all
generated random numbers from the transport stream with
usbmon [software] or special usb sniffer hardware.
Say N, unless your setup[i.e.: embedded system] has no
other rng source and you can afford to take the risk.
......@@ -43,6 +43,7 @@
#include <linux/firmware.h>
#include <linux/completion.h>
#include <linux/spinlock.h>
#include <linux/hw_random.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <linux/usb.h>
......@@ -151,6 +152,7 @@ struct carl9170_sta_tid {
#define CARL9170_TX_TIMEOUT 2500
#define CARL9170_JANITOR_DELAY 128
#define CARL9170_QUEUE_STUCK_TIMEOUT 5500
#define CARL9170_STAT_WORK 30000
#define CARL9170_NUM_TX_AGG_MAX 30
......@@ -282,6 +284,7 @@ struct ar9170 {
bool rx_stream;
bool tx_stream;
bool rx_filter;
bool hw_counters;
unsigned int mem_blocks;
unsigned int mem_block_size;
unsigned int rx_size;
......@@ -331,11 +334,21 @@ struct ar9170 {
/* PHY */
struct ieee80211_channel *channel;
unsigned int num_channels;
int noise[4];
unsigned int chan_fail;
unsigned int total_chan_fail;
u8 heavy_clip;
u8 ht_settings;
struct {
u64 active; /* usec */
u64 cca; /* usec */
u64 tx_time; /* usec */
u64 rx_total;
u64 rx_overrun;
} tally;
struct delayed_work stat_work;
struct survey_info *survey;
/* power calibration data */
u8 power_5G_leg[4];
......@@ -437,6 +450,17 @@ struct ar9170 {
unsigned int off_override;
bool state;
} ps;
#ifdef CONFIG_CARL9170_HWRNG
# define CARL9170_HWRNG_CACHE_SIZE CARL9170_MAX_CMD_PAYLOAD_LEN
struct {
struct hwrng rng;
bool initialized;
char name[30 + 1];
u16 cache[CARL9170_HWRNG_CACHE_SIZE / sizeof(u16)];
unsigned int cache_idx;
} rng;
#endif /* CONFIG_CARL9170_HWRNG */
};
enum carl9170_ps_off_override_reasons {
......
......@@ -36,6 +36,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <asm/div64.h>
#include "carl9170.h"
#include "cmd.h"
......@@ -165,6 +166,39 @@ int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
return __carl9170_exec_cmd(ar, cmd, true);
}
int carl9170_collect_tally(struct ar9170 *ar)
{
struct carl9170_tally_rsp tally;
struct survey_info *info;
unsigned int tick;
int err;
err = carl9170_exec_cmd(ar, CARL9170_CMD_TALLY, 0, NULL,
sizeof(tally), (u8 *)&tally);
if (err)
return err;
tick = le32_to_cpu(tally.tick);
if (tick) {
ar->tally.active += le32_to_cpu(tally.active) / tick;
ar->tally.cca += le32_to_cpu(tally.cca) / tick;
ar->tally.tx_time += le32_to_cpu(tally.tx_time) / tick;
ar->tally.rx_total += le32_to_cpu(tally.rx_total);
ar->tally.rx_overrun += le32_to_cpu(tally.rx_overrun);
if (ar->channel) {
info = &ar->survey[ar->channel->hw_value];
info->channel_time = ar->tally.active;
info->channel_time_busy = ar->tally.cca;
info->channel_time_tx = ar->tally.tx_time;
do_div(info->channel_time, 1000);
do_div(info->channel_time_busy, 1000);
do_div(info->channel_time_tx, 1000);
}
}
return 0;
}
int carl9170_powersave(struct ar9170 *ar, const bool ps)
{
struct carl9170_cmd *cmd;
......
......@@ -50,6 +50,7 @@ int carl9170_echo_test(struct ar9170 *ar, u32 v);
int carl9170_reboot(struct ar9170 *ar);
int carl9170_mac_reset(struct ar9170 *ar);
int carl9170_powersave(struct ar9170 *ar, const bool power_on);
int carl9170_collect_tally(struct ar9170 *ar);
int carl9170_bcn_ctrl(struct ar9170 *ar, const unsigned int vif_id,
const u32 mode, const u32 addr, const u32 len);
......
......@@ -266,6 +266,9 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
FIF_PROMISC_IN_BSS;
}
if (SUPP(CARL9170FW_HW_COUNTERS))
ar->fw.hw_counters = true;
if (SUPP(CARL9170FW_WOL))
device_set_wakeup_enable(&ar->udev->dev, true);
......
......@@ -55,6 +55,7 @@ enum carl9170_cmd_oids {
CARL9170_CMD_READ_TSF = 0x06,
CARL9170_CMD_RX_FILTER = 0x07,
CARL9170_CMD_WOL = 0x08,
CARL9170_CMD_TALLY = 0x09,
/* CAM */
CARL9170_CMD_EKEY = 0x10,
......@@ -286,6 +287,15 @@ struct carl9170_tsf_rsp {
} __packed;
#define CARL9170_TSF_RSP_SIZE 8
struct carl9170_tally_rsp {
__le32 active;
__le32 cca;
__le32 tx_time;
__le32 rx_total;
__le32 rx_overrun;
__le32 tick;
} __packed;
struct carl9170_rsp {
struct carl9170_cmd_head hdr;
......@@ -300,6 +310,7 @@ struct carl9170_rsp {
struct carl9170_gpio gpio;
struct carl9170_tsf_rsp tsf;
struct carl9170_psm psm;
struct carl9170_tally_rsp tally;
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
} __packed;
} __packed __aligned(4);
......
......@@ -413,6 +413,9 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED);
ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
ieee80211_wake_queues(ar->hw);
err = 0;
......@@ -423,6 +426,7 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
static void carl9170_cancel_worker(struct ar9170 *ar)
{
cancel_delayed_work_sync(&ar->stat_work);
cancel_delayed_work_sync(&ar->tx_janitor);
#ifdef CONFIG_CARL9170_LEDS
cancel_delayed_work_sync(&ar->led_work);
......@@ -794,6 +798,43 @@ static void carl9170_ps_work(struct work_struct *work)
mutex_unlock(&ar->mutex);
}
static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise)
{
int err;
if (noise) {
err = carl9170_get_noisefloor(ar);
if (err)
return err;
}
if (ar->fw.hw_counters) {
err = carl9170_collect_tally(ar);
if (err)
return err;
}
if (flush)
memset(&ar->tally, 0, sizeof(ar->tally));
return 0;
}
static void carl9170_stat_work(struct work_struct *work)
{
struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work);
int err;
mutex_lock(&ar->mutex);
err = carl9170_update_survey(ar, false, true);
mutex_unlock(&ar->mutex);
if (err)
return;
ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
}
static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
{
......@@ -828,11 +869,19 @@ static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
if (err)
goto out;
err = carl9170_update_survey(ar, true, false);
if (err)
goto out;
err = carl9170_set_channel(ar, hw->conf.channel,
hw->conf.channel_type, CARL9170_RFI_NONE);
if (err)
goto out;
err = carl9170_update_survey(ar, false, true);
if (err)
goto out;
err = carl9170_set_dyn_sifs_ack(ar);
if (err)
goto out;
......@@ -1419,24 +1468,159 @@ static int carl9170_register_wps_button(struct ar9170 *ar)
}
#endif /* CONFIG_CARL9170_WPC */
static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
#ifdef CONFIG_CARL9170_HWRNG
static int carl9170_rng_get(struct ar9170 *ar)
{
struct ar9170 *ar = hw->priv;
#define RW (CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32))
#define RB (CARL9170_MAX_CMD_PAYLOAD_LEN)
static const __le32 rng_load[RW] = {
[0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)};
u32 buf[RW];
unsigned int i, off = 0, transfer, count;
int err;
if (idx != 0)
return -ENOENT;
BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN);
if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized)
return -EAGAIN;
count = ARRAY_SIZE(ar->rng.cache);
while (count) {
err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
RB, (u8 *) rng_load,
RB, (u8 *) buf);
if (err)
return err;
transfer = min_t(unsigned int, count, RW);
for (i = 0; i < transfer; i++)
ar->rng.cache[off + i] = buf[i];
off += transfer;
count -= transfer;
}
ar->rng.cache_idx = 0;
#undef RW
#undef RB
return 0;
}
static int carl9170_rng_read(struct hwrng *rng, u32 *data)
{
struct ar9170 *ar = (struct ar9170 *)rng->priv;
int ret = -EIO;
mutex_lock(&ar->mutex);
err = carl9170_get_noisefloor(ar);
if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) {
ret = carl9170_rng_get(ar);
if (ret) {
mutex_unlock(&ar->mutex);
return ret;
}
}
*data = ar->rng.cache[ar->rng.cache_idx++];
mutex_unlock(&ar->mutex);
if (err)
return sizeof(u16);
}
static void carl9170_unregister_hwrng(struct ar9170 *ar)
{
if (ar->rng.initialized) {
hwrng_unregister(&ar->rng.rng);
ar->rng.initialized = false;
}
}
static int carl9170_register_hwrng(struct ar9170 *ar)
{
int err;
snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name),
"%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy));
ar->rng.rng.name = ar->rng.name;
ar->rng.rng.data_read = carl9170_rng_read;
ar->rng.rng.priv = (unsigned long)ar;
if (WARN_ON(ar->rng.initialized))
return -EALREADY;
err = hwrng_register(&ar->rng.rng);
if (err) {
dev_err(&ar->udev->dev, "Failed to register the random "
"number generator (%d)\n", err);
return err;
}
ar->rng.initialized = true;
err = carl9170_rng_get(ar);
if (err) {
carl9170_unregister_hwrng(ar);
return err;
}
return 0;
}
#endif /* CONFIG_CARL9170_HWRNG */
static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
struct ar9170 *ar = hw->priv;
struct ieee80211_channel *chan;
struct ieee80211_supported_band *band;
int err, b, i;
chan = ar->channel;
if (!chan)
return -ENODEV;
if (idx == chan->hw_value) {
mutex_lock(&ar->mutex);
err = carl9170_update_survey(ar, false, true);
mutex_unlock(&ar->mutex);
if (err)
return err;
}
for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
band = ar->hw->wiphy->bands[b];
if (!band)
continue;
for (i = 0; i < band->n_channels; i++) {
if (band->channels[i].hw_value == idx) {
chan = &band->channels[i];
goto found;
}
}
}
return -ENOENT;
found:
memcpy(survey, &ar->survey[idx], sizeof(*survey));
survey->channel = ar->channel;
survey->channel = chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = ar->noise[0];
if (ar->channel == chan)
survey->filled |= SURVEY_INFO_IN_USE;
if (ar->fw.hw_counters) {
survey->filled |= SURVEY_INFO_CHANNEL_TIME |
SURVEY_INFO_CHANNEL_TIME_BUSY |
SURVEY_INFO_CHANNEL_TIME_TX;
}
return 0;
}
......@@ -1569,6 +1753,7 @@ void *carl9170_alloc(size_t priv_size)
INIT_WORK(&ar->ping_work, carl9170_ping_work);
INIT_WORK(&ar->restart_work, carl9170_restart_work);
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work);
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
INIT_LIST_HEAD(&ar->tx_ampdu_list);
rcu_assign_pointer(ar->tx_ampdu_iter,
......@@ -1652,6 +1837,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
struct ath_regulatory *regulatory = &ar->common.regulatory;
unsigned int rx_streams, tx_streams, tx_params = 0;
int bands = 0;
int chans = 0;
if (ar->eeprom.length == cpu_to_le16(0xffff))
return -ENODATA;
......@@ -1675,14 +1861,24 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
&carl9170_band_2GHz;
chans += carl9170_band_2GHz.n_channels;
bands++;
}
if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
&carl9170_band_5GHz;
chans += carl9170_band_5GHz.n_channels;
bands++;
}
if (!bands)
return -EINVAL;
ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL);
if (!ar->survey)
return -ENOMEM;
ar->num_channels = chans;
/*
* I measured this, a bandswitch takes roughly
* 135 ms and a frequency switch about 80.
......@@ -1701,7 +1897,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
/* second part of wiphy init */
SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
return bands ? 0 : -EINVAL;
return 0;
}
static int carl9170_reg_notifier(struct wiphy *wiphy,
......@@ -1785,6 +1981,12 @@ int carl9170_register(struct ar9170 *ar)
goto err_unreg;
#endif /* CONFIG_CARL9170_WPC */
#ifdef CONFIG_CARL9170_HWRNG
err = carl9170_register_hwrng(ar);
if (err)
goto err_unreg;
#endif /* CONFIG_CARL9170_HWRNG */
dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",
wiphy_name(ar->hw->wiphy));
......@@ -1817,6 +2019,10 @@ void carl9170_unregister(struct ar9170 *ar)
}
#endif /* CONFIG_CARL9170_WPC */
#ifdef CONFIG_CARL9170_HWRNG
carl9170_unregister_hwrng(ar);
#endif /* CONFIG_CARL9170_HWRNG */
carl9170_cancel_worker(ar);
cancel_work_sync(&ar->restart_work);
......@@ -1834,6 +2040,9 @@ void carl9170_free(struct ar9170 *ar)
kfree(ar->mem_bitmap);
ar->mem_bitmap = NULL;
kfree(ar->survey);
ar->survey = NULL;
mutex_destroy(&ar->mutex);
ieee80211_free_hw(ar->hw);
......
......@@ -578,11 +578,10 @@ static int carl9170_init_phy(struct ar9170 *ar, enum ieee80211_band band)
if (err)
return err;
/* XXX: remove magic! */
if (is_2ghz)
err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5163);
else
err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC, 0x5143);
if (!ar->fw.hw_counters) {
err = carl9170_write_reg(ar, AR9170_PWR_REG_PLL_ADDAC,
is_2ghz ? 0x5163 : 0x5143);
}
return err;
}
......@@ -1574,6 +1573,9 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
}
if (ar->channel)
ar->survey[ar->channel->hw_value].noise = ar->noise[0];
return 0;
}
......@@ -1766,10 +1768,6 @@ int carl9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel,
ar->chan_fail = 0;
}
err = carl9170_get_noisefloor(ar);
if (err)
return err;
if (ar->heavy_clip) {
err = carl9170_write_reg(ar, AR9170_PHY_REG_HEAVY_CLIP_ENABLE,
0x200 | ar->heavy_clip);
......
#ifndef __CARL9170_SHARED_VERSION_H
#define __CARL9170_SHARED_VERSION_H
#define CARL9170FW_VERSION_YEAR 11
#define CARL9170FW_VERSION_MONTH 6
#define CARL9170FW_VERSION_DAY 30
#define CARL9170FW_VERSION_MONTH 8
#define CARL9170FW_VERSION_DAY 15
#define CARL9170FW_VERSION_GIT "1.9.4"
#endif /* __CARL9170_SHARED_VERSION_H */
......@@ -169,13 +169,3 @@ config B43_DEBUG
Say N, if you are a distributor or user building a release kernel
for production use.
Only say Y, if you are debugging a problem in the b43 driver sourcecode.
config B43_FORCE_PIO
bool "Force usage of PIO instead of DMA"
depends on B43 && B43_DEBUG
---help---
This will disable DMA and always enable PIO instead.
Say N!
This is only for debugging the PIO engine code. You do
_NOT_ want to enable this.
......@@ -17,11 +17,6 @@
#include "phy_common.h"
/* The unique identifier of the firmware that's officially supported by
* this driver version. */
#define B43_SUPPORTED_FIRMWARE_ID "FW13"
#ifdef CONFIG_B43_DEBUG
# define B43_DEBUG 1
#else
......@@ -594,6 +589,7 @@ struct b43_dma {
struct b43_dmaring *rx_ring;
u32 translation; /* Routing bits */
bool translation_in_low; /* Should translation bit go into low addr? */
bool parity; /* Check for parity */
};
......@@ -694,6 +690,12 @@ struct b43_firmware_file {
enum b43_firmware_file_type type;
};
enum b43_firmware_hdr_format {
B43_FW_HDR_598,
B43_FW_HDR_410,
B43_FW_HDR_351,
};
/* Pointers to the firmware data and meta information about it. */
struct b43_firmware {
/* Microcode */
......@@ -710,6 +712,9 @@ struct b43_firmware {
/* Firmware patchlevel */
u16 patch;
/* Format of header used by firmware */
enum b43_firmware_hdr_format hdr_format;
/* Set to true, if we are using an opensource firmware.
* Use this to check for proprietary vs opensource. */
bool opensource;
......@@ -875,7 +880,7 @@ struct b43_wl {
struct b43_leds leds;
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
u8 pio_scratchspace[118] __attribute__((__aligned__(8)));
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
};
......@@ -965,12 +970,6 @@ static inline bool b43_using_pio_transfers(struct b43_wldev *dev)
return dev->__using_pio_transfers;
}
#ifdef CONFIG_B43_FORCE_PIO
# define B43_PIO_DEFAULT 1
#else
# define B43_PIO_DEFAULT 0
#endif
/* Message printing */
void b43info(struct b43_wl *wl, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
......
......@@ -47,6 +47,38 @@
* into separate slots. */
#define TX_SLOTS_PER_FRAME 2
static u32 b43_dma_address(struct b43_dma *dma, dma_addr_t dmaaddr,
enum b43_addrtype addrtype)
{
u32 uninitialized_var(addr);
switch (addrtype) {
case B43_DMA_ADDR_LOW:
addr = lower_32_bits(dmaaddr);
if (dma->translation_in_low) {
addr &= ~SSB_DMA_TRANSLATION_MASK;
addr |= dma->translation;
}
break;
case B43_DMA_ADDR_HIGH:
addr = upper_32_bits(dmaaddr);
if (!dma->translation_in_low) {
addr &= ~SSB_DMA_TRANSLATION_MASK;
addr |= dma->translation;
}
break;
case B43_DMA_ADDR_EXT:
if (dma->translation_in_low)
addr = lower_32_bits(dmaaddr);
else
addr = upper_32_bits(dmaaddr);
addr &= SSB_DMA_TRANSLATION_MASK;
addr >>= SSB_DMA_TRANSLATION_SHIFT;
break;
}
return addr;
}
/* 32bit DMA ops. */
static
......@@ -77,10 +109,9 @@ static void op32_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma32) - descbase);
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
addr |= ring->dev->dma.translation;
addr = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
ctl = bufsize & B43_DMA32_DCTL_BYTECNT;
if (slot == ring->nr_slots - 1)
ctl |= B43_DMA32_DCTL_DTABLEEND;
......@@ -170,11 +201,10 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
slot = (int)(&(desc->dma64) - descbase);
B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
addrlo = (u32) (dmaaddr & 0xFFFFFFFF);
addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
addrhi |= ring->dev->dma.translation;
addrlo = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_LOW);
addrhi = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_HIGH);
addrext = b43_dma_address(&ring->dev->dma, dmaaddr, B43_DMA_ADDR_EXT);
if (slot == ring->nr_slots - 1)
ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
if (start)
......@@ -658,41 +688,37 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
int err = 0;
u32 value;
u32 addrext;
u32 trans = ring->dev->dma.translation;
bool parity = ring->dev->dma.parity;
u32 addrlo;
u32 addrhi;
if (ring->tx) {
if (ring->type == B43_DMA_64BIT) {
u64 ringbase = (u64) (ring->dmabase);
addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA64_TXENABLE;
value |= (addrext << B43_DMA64_TXADDREXT_SHIFT)
& B43_DMA64_TXADDREXT_MASK;
if (!parity)
value |= B43_DMA64_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA64_TXCTL, value);
b43_dma_write(ring, B43_DMA64_TXRINGLO,
(ringbase & 0xFFFFFFFF));
b43_dma_write(ring, B43_DMA64_TXRINGHI,
((ringbase >> 32) &
~SSB_DMA_TRANSLATION_MASK)
| trans);
b43_dma_write(ring, B43_DMA64_TXRINGLO, addrlo);
b43_dma_write(ring, B43_DMA64_TXRINGHI, addrhi);
} else {
u32 ringbase = (u32) (ring->dmabase);
addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
value = B43_DMA32_TXENABLE;
value |= (addrext << B43_DMA32_TXADDREXT_SHIFT)
& B43_DMA32_TXADDREXT_MASK;
if (!parity)
value |= B43_DMA32_TXPARITYDISABLE;
b43_dma_write(ring, B43_DMA32_TXCTL, value);
b43_dma_write(ring, B43_DMA32_TXRING,
(ringbase & ~SSB_DMA_TRANSLATION_MASK)
| trans);
b43_dma_write(ring, B43_DMA32_TXRING, addrlo);
}
} else {
err = alloc_initial_descbuffers(ring);
......@@ -700,9 +726,10 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
goto out;
if (ring->type == B43_DMA_64BIT) {
u64 ringbase = (u64) (ring->dmabase);
addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
addrhi = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_HIGH);
addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT);
value |= B43_DMA64_RXENABLE;
value |= (addrext << B43_DMA64_RXADDREXT_SHIFT)
......@@ -710,19 +737,15 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
if (!parity)
value |= B43_DMA64_RXPARITYDISABLE;
b43_dma_write(ring, B43_DMA64_RXCTL, value);
b43_dma_write(ring, B43_DMA64_RXRINGLO,
(ringbase & 0xFFFFFFFF));
b43_dma_write(ring, B43_DMA64_RXRINGHI,
((ringbase >> 32) &
~SSB_DMA_TRANSLATION_MASK)
| trans);
b43_dma_write(ring, B43_DMA64_RXRINGLO, addrlo);
b43_dma_write(ring, B43_DMA64_RXRINGHI, addrhi);
b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc64));
} else {
u32 ringbase = (u32) (ring->dmabase);
addrext = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_EXT);
addrlo = b43_dma_address(&ring->dev->dma, ringbase, B43_DMA_ADDR_LOW);
addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT);
value |= B43_DMA32_RXENABLE;
value |= (addrext << B43_DMA32_RXADDREXT_SHIFT)
......@@ -730,9 +753,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
if (!parity)
value |= B43_DMA32_RXPARITYDISABLE;
b43_dma_write(ring, B43_DMA32_RXCTL, value);
b43_dma_write(ring, B43_DMA32_RXRING,
(ringbase & ~SSB_DMA_TRANSLATION_MASK)
| trans);
b43_dma_write(ring, B43_DMA32_RXRING, addrlo);
b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
sizeof(struct b43_dmadesc32));
}
......@@ -872,8 +893,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
ring->current_slot = -1;
} else {
if (ring->index == 0) {
ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE;
ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET;
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
ring->rx_buffersize = B43_DMA0_RX_FW598_BUFSIZE;
ring->frameoffset = B43_DMA0_RX_FW598_FO;
break;
case B43_FW_HDR_410:
case B43_FW_HDR_351:
ring->rx_buffersize = B43_DMA0_RX_FW351_BUFSIZE;
ring->frameoffset = B43_DMA0_RX_FW351_FO;
break;
}
} else
B43_WARN_ON(1);
}
......@@ -1066,6 +1096,25 @@ static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask)
return 0;
}
/* Some hardware with 64-bit DMA seems to be bugged and looks for translation
* bit in low address word instead of high one.
*/
static bool b43_dma_translation_in_low_word(struct b43_wldev *dev,
enum b43_dmatype type)
{
if (type != B43_DMA_64BIT)
return 1;
#ifdef CONFIG_B43_SSB
if (dev->dev->bus_type == B43_BUS_SSB &&
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
!(dev->dev->sdev->bus->host_pci->is_pcie &&
ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64))
return 1;
#endif
return 0;
}
int b43_dma_init(struct b43_wldev *dev)
{
struct b43_dma *dma = &dev->dma;
......@@ -1091,6 +1140,7 @@ int b43_dma_init(struct b43_wldev *dev)
break;
#endif
}
dma->translation_in_low = b43_dma_translation_in_low_word(dev, type);
dma->parity = true;
#ifdef CONFIG_B43_BCMA
......
......@@ -162,12 +162,15 @@ struct b43_dmadesc_generic {
/* Misc DMA constants */
#define B43_DMA_RINGMEMSIZE PAGE_SIZE
#define B43_DMA0_RX_FRAMEOFFSET 30
/* Offset of frame with actual data */
#define B43_DMA0_RX_FW598_FO 38
#define B43_DMA0_RX_FW351_FO 30
/* DMA engine tuning knobs */
#define B43_TXRING_SLOTS 256
#define B43_RXRING_SLOTS 64
#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
#define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
#define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
/* Pointer poison */
#define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM))
......@@ -212,6 +215,12 @@ enum b43_dmatype {
B43_DMA_64BIT = 64,
};
enum b43_addrtype {
B43_DMA_ADDR_LOW,
B43_DMA_ADDR_HIGH,
B43_DMA_ADDR_EXT,
};
struct b43_dmaring {
/* Lowlevel DMA ops. */
const struct b43_dma_ops *ops;
......
......@@ -66,7 +66,6 @@ MODULE_AUTHOR("Michael Buesch");
MODULE_AUTHOR("Gábor Stefanik");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43/ucode11.fw");
MODULE_FIRMWARE("b43/ucode13.fw");
MODULE_FIRMWARE("b43/ucode14.fw");
......@@ -108,7 +107,7 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT;
module_param_named(verbose, b43_modparam_verbose, int, 0644);
MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug");
static int b43_modparam_pio = B43_PIO_DEFAULT;
static int b43_modparam_pio = 0;
module_param_named(pio, b43_modparam_pio, int, 0644);
MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
......@@ -320,6 +319,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
static int b43_wireless_core_start(struct b43_wldev *dev);
static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *conf,
u32 changed);
static int b43_ratelimit(struct b43_wl *wl)
{
......@@ -2510,6 +2513,12 @@ static int b43_upload_microcode(struct b43_wldev *dev)
}
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
if (dev->fw.rev >= 598)
dev->fw.hdr_format = B43_FW_HDR_598;
else if (dev->fw.rev >= 410)
dev->fw.hdr_format = B43_FW_HDR_410;
else
dev->fw.hdr_format = B43_FW_HDR_351;
dev->fw.opensource = (fwdate == 0xFFFF);
/* Default to use-all-queues. */
......@@ -2557,7 +2566,7 @@ static int b43_upload_microcode(struct b43_wldev *dev)
dev->fw.rev, dev->fw.patch);
wiphy->hw_version = dev->dev->core_id;
if (b43_is_old_txhdr_format(dev)) {
if (dev->fw.hdr_format == B43_FW_HDR_351) {
/* We're over the deadline, but we keep support for old fw
* until it turns out to be in major conflict with something new. */
b43warn(dev->wl, "You are using an old firmware image. "
......@@ -2943,6 +2952,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
case B43_PHYTYPE_G:
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
case B43_PHYTYPE_HT:
b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
......@@ -3778,14 +3788,24 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
struct ieee80211_conf *conf = &hw->conf;
int antenna;
int err = 0;
bool reload_bss = false;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
/* Switch the band (if necessary). This might change the active core. */
err = b43_switch_band(wl, conf->channel);
if (err)
goto out_unlock_mutex;
dev = wl->current_dev;
/* Need to reload all settings if the core changed */
if (dev != wl->current_dev) {
dev = wl->current_dev;
changed = ~0;
reload_bss = true;
}
phy = &dev->phy;
if (conf_is_ht(conf))
......@@ -3846,6 +3866,9 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
out_unlock_mutex:
mutex_unlock(&wl->mutex);
if (wl->vif && reload_bss)
b43_op_bss_info_changed(hw, wl->vif, &wl->vif->bss_conf, ~0);
return err;
}
......@@ -3934,7 +3957,8 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_BEACON_INT &&
(b43_is_mode(wl, NL80211_IFTYPE_AP) ||
b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) &&
conf->beacon_int)
b43_set_beacon_int(dev, conf->beacon_int);
if (changed & BSS_CHANGED_BASIC_RATES)
......@@ -4629,8 +4653,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
if (b43_bus_host_is_pcmcia(dev->dev) ||
b43_bus_host_is_sdio(dev->dev) ||
dev->use_pio) {
b43_bus_host_is_sdio(dev->dev)) {
dev->__using_pio_transfers = 1;
err = b43_pio_init(dev);
} else if (dev->use_pio) {
b43warn(dev->wl, "Forced PIO by use_pio module parameter. "
"This should not be needed and will result in lower "
"performance.\n");
dev->__using_pio_transfers = 1;
err = b43_pio_init(dev);
} else {
......@@ -4702,6 +4731,9 @@ static int b43_op_add_interface(struct ieee80211_hw *hw,
out_mutex_unlock:
mutex_unlock(&wl->mutex);
if (err == 0)
b43_op_bss_info_changed(hw, vif, &vif->bss_conf, ~0);
return err;
}
......@@ -4772,6 +4804,9 @@ static int b43_op_start(struct ieee80211_hw *hw)
out_mutex_unlock:
mutex_unlock(&wl->mutex);
/* reload configuration */
b43_op_config(hw, ~0);
return err;
}
......@@ -4928,10 +4963,18 @@ static void b43_chip_reset(struct work_struct *work)
if (err)
wl->current_dev = NULL; /* Failed to init the dev. */
mutex_unlock(&wl->mutex);
if (err)
if (err) {
b43err(wl, "Controller restart FAILED\n");
else
b43info(wl, "Controller restarted\n");
return;
}
/* reload configuration */
b43_op_config(wl->hw, ~0);
if (wl->vif)
b43_op_bss_info_changed(wl->hw, wl->vif, &wl->vif->bss_conf, ~0);
b43info(wl, "Controller restarted\n");
}
static int b43_setup_bands(struct b43_wldev *dev,
......@@ -5416,8 +5459,7 @@ static void b43_print_driverinfo(void)
feat_sdio = "S";
#endif
printk(KERN_INFO "Broadcom 43xx driver loaded "
"[ Features: %s%s%s%s%s, Firmware-ID: "
B43_SUPPORTED_FIRMWARE_ID " ]\n",
"[ Features: %s%s%s%s%s ]\n",
feat_pci, feat_pcmcia, feat_nphy,
feat_leds, feat_sdio);
}
......
......@@ -448,6 +448,38 @@ bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type)
channel_type == NL80211_CHAN_HT40PLUS);
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
void b43_phy_force_clock(struct b43_wldev *dev, bool force)
{
u32 tmp;
WARN_ON(dev->phy.type != B43_PHYTYPE_N &&
dev->phy.type != B43_PHYTYPE_HT);
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
if (force)
tmp |= BCMA_IOCTL_FGC;
else
tmp &= ~BCMA_IOCTL_FGC;
bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
break;
#endif
#ifdef CONFIG_B43_SSB
case B43_BUS_SSB:
tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
if (force)
tmp |= SSB_TMSLOW_FGC;
else
tmp &= ~SSB_TMSLOW_FGC;
ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
break;
#endif
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/Cordic */
struct b43_c32 b43_cordic(int theta)
{
......
......@@ -444,6 +444,8 @@ void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on);
bool b43_channel_type_is_40mhz(enum nl80211_channel_type channel_type);
void b43_phy_force_clock(struct b43_wldev *dev, bool force);
struct b43_c32 b43_cordic(int theta);
#endif /* LINUX_B43_PHY_COMMON_H_ */
......@@ -151,6 +151,92 @@ static void b43_radio_2059_init(struct b43_wldev *dev)
b43_radio_mask(dev, 0x11, ~0x0008);
}
/**************************************************
* Various PHY ops
**************************************************/
static void b43_phy_ht_zero_extg(struct b43_wldev *dev)
{
u8 i, j;
u16 base[] = { 0x40, 0x60, 0x80 };
for (i = 0; i < ARRAY_SIZE(base); i++) {
for (j = 0; j < 4; j++)
b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0);
}
for (i = 0; i < ARRAY_SIZE(base); i++)
b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0);
}
/* Some unknown AFE (Analog Frondned) op */
static void b43_phy_ht_afe_unk1(struct b43_wldev *dev)
{
u8 i;
const u16 ctl_regs[3][2] = {
{ B43_PHY_HT_AFE_CTL1, B43_PHY_HT_AFE_CTL2 },
{ B43_PHY_HT_AFE_CTL3, B43_PHY_HT_AFE_CTL4 },
{ B43_PHY_HT_AFE_CTL5, B43_PHY_HT_AFE_CTL6},
};
for (i = 0; i < 3; i++) {
/* TODO: verify masks&sets */
b43_phy_set(dev, ctl_regs[i][1], 0x4);
b43_phy_set(dev, ctl_regs[i][0], 0x4);
b43_phy_mask(dev, ctl_regs[i][1], ~0x1);
b43_phy_set(dev, ctl_regs[i][0], 0x1);
b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0);
b43_phy_mask(dev, ctl_regs[i][0], ~0x4);
}
}
static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq)
{
u8 i;
u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3);
b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq);
for (i = 0; i < 200; i++) {
if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) {
i = 0;
break;
}
msleep(1);
}
if (i)
b43err(dev->wl, "Forcing RF sequence timeout\n");
b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
}
static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
{
clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES);
clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES);
clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES);
}
static void b43_phy_ht_bphy_init(struct b43_wldev *dev)
{
unsigned int i;
u16 val;
val = 0x1E1F;
for (i = 0; i < 16; i++) {
b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
val -= 0x202;
}
val = 0x3E3F;
for (i = 0; i < 16; i++) {
b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
val -= 0x202;
}
b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
}
/**************************************************
* Channel switching ops.
**************************************************/
......@@ -255,8 +341,125 @@ static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
static int b43_phy_ht_op_init(struct b43_wldev *dev)
{
u16 tmp;
u16 clip_state[3];
b43_phy_ht_tables_init(dev);
b43_phy_mask(dev, 0x0be, ~0x2);
b43_phy_set(dev, 0x23f, 0x7ff);
b43_phy_set(dev, 0x240, 0x7ff);
b43_phy_set(dev, 0x241, 0x7ff);
b43_phy_ht_zero_extg(dev);
b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3);
b43_phy_write(dev, B43_PHY_HT_AFE_CTL1, 0);
b43_phy_write(dev, B43_PHY_HT_AFE_CTL3, 0);
b43_phy_write(dev, B43_PHY_HT_AFE_CTL5, 0);
b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20);
b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20);
b43_phy_write(dev, 0x20d, 0xb8);
b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8);
b43_phy_write(dev, 0x70, 0x50);
b43_phy_write(dev, 0x1ff, 0x30);
if (0) /* TODO: condition */
; /* TODO: PHY op on reg 0x217 */
b43_phy_read(dev, 0xb0); /* TODO: what for? */
b43_phy_set(dev, 0xb0, 0x1);
b43_phy_set(dev, 0xb1, 0x91);
b43_phy_write(dev, 0x32f, 0x0003);
b43_phy_write(dev, 0x077, 0x0010);
b43_phy_write(dev, 0x0b4, 0x0258);
b43_phy_mask(dev, 0x17e, ~0x4000);
b43_phy_write(dev, 0x0b9, 0x0072);
b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f);
b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f);
b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f);
b43_phy_ht_afe_unk1(dev);
b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111,
0x777, 0x111, 0x111, 0x777, 0x111, 0x111);
b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777);
b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777);
b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02);
b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02);
b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02);
b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4,
0x8e, 0x96, 0x96, 0x96);
b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4,
0x8f, 0x9f, 0x9f, 0x9f);
b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4,
0x8f, 0x9f, 0x9f, 0x9f);
b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2);
b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2);
b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2);
b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e);
b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e);
b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46);
b43_phy_maskset(dev, 0x0283, 0xff00, 0x40);
b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4,
0x09, 0x0e, 0x13, 0x18);
b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4,
0x09, 0x0e, 0x13, 0x18);
/* TODO: Did wl mean 2 instead of 40? */
b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4,
0x09, 0x0e, 0x13, 0x18);
b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd);
b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd);
b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd);
b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1);
b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1);
b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1);
b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1);
/* Copy some tables entries */
tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144));
b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp);
tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154));
b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp);
tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164));
b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp);
/* Reset CCA */
b43_phy_force_clock(dev, true);
tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG);
b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA);
b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA);
b43_phy_force_clock(dev, false);
b43_mac_phy_clock_set(dev, true);
b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX);
b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
/* TODO: PHY op on reg 0xb0 */
/* TODO: Should we restore it? Or store it in global PHY info? */
b43_phy_ht_read_clip_detection(dev, clip_state);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
b43_phy_ht_bphy_init(dev);
b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0),
B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late);
return 0;
}
......
......@@ -4,7 +4,11 @@
#include "phy_common.h"
#define B43_PHY_HT_BBCFG 0x001 /* BB config */
#define B43_PHY_HT_BBCFG_RSTCCA 0x4000 /* Reset CCA */
#define B43_PHY_HT_BBCFG_RSTRX 0x8000 /* Reset RX */
#define B43_PHY_HT_BANDCTL 0x009 /* Band control */
#define B43_PHY_HT_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */
#define B43_PHY_HT_TABLE_ADDR 0x072 /* Table address */
#define B43_PHY_HT_TABLE_DATALO 0x073 /* Table data low */
#define B43_PHY_HT_TABLE_DATAHI 0x074 /* Table data high */
......@@ -15,6 +19,21 @@
#define B43_PHY_HT_BW5 0x1D2
#define B43_PHY_HT_BW6 0x1D3
#define B43_PHY_HT_C1_CLIP1THRES B43_PHY_OFDM(0x00E)
#define B43_PHY_HT_C2_CLIP1THRES B43_PHY_OFDM(0x04E)
#define B43_PHY_HT_C3_CLIP1THRES B43_PHY_OFDM(0x08E)
#define B43_PHY_HT_RF_SEQ_MODE B43_PHY_EXTG(0x000)
#define B43_PHY_HT_RF_SEQ_TRIG B43_PHY_EXTG(0x003)
#define B43_PHY_HT_RF_SEQ_TRIG_RX2TX 0x0001 /* RX2TX */
#define B43_PHY_HT_RF_SEQ_TRIG_TX2RX 0x0002 /* TX2RX */
#define B43_PHY_HT_RF_SEQ_TRIG_UPGH 0x0004 /* Update gain H */
#define B43_PHY_HT_RF_SEQ_TRIG_UPGL 0x0008 /* Update gain L */
#define B43_PHY_HT_RF_SEQ_TRIG_UPGU 0x0010 /* Update gain U */
#define B43_PHY_HT_RF_SEQ_TRIG_RST2RX 0x0020 /* Reset to RX */
#define B43_PHY_HT_RF_SEQ_STATUS B43_PHY_EXTG(0x004)
/* Values for the status are the same as for the trigger */
#define B43_PHY_HT_RF_CTL1 B43_PHY_EXTG(0x010)
#define B43_PHY_HT_AFE_CTL1 B43_PHY_EXTG(0x110)
......
......@@ -27,26 +27,233 @@
#include "tables_phy_lcn.h"
#include "main.h"
/**************************************************
* Radio 2064.
**************************************************/
static void b43_radio_2064_init(struct b43_wldev *dev)
{
b43_radio_write(dev, 0x09c, 0x0020);
b43_radio_write(dev, 0x105, 0x0008);
b43_radio_write(dev, 0x032, 0x0062);
b43_radio_write(dev, 0x033, 0x0019);
b43_radio_write(dev, 0x090, 0x0010);
b43_radio_write(dev, 0x010, 0x0000);
b43_radio_write(dev, 0x060, 0x007f);
b43_radio_write(dev, 0x061, 0x0072);
b43_radio_write(dev, 0x062, 0x007f);
b43_radio_write(dev, 0x01d, 0x0002);
b43_radio_write(dev, 0x01e, 0x0006);
b43_phy_write(dev, 0x4ea, 0x4688);
b43_phy_maskset(dev, 0x4eb, ~0x7, 0x2);
b43_phy_mask(dev, 0x4eb, ~0x01c0);
b43_phy_maskset(dev, 0x4eb, 0xff00, 0x19);
b43_lcntab_write(dev, B43_LCNTAB16(0x00, 0x55), 0);
b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
b43_radio_set(dev, 0x004, 0x40);
b43_radio_set(dev, 0x120, 0x10);
b43_radio_set(dev, 0x078, 0x80);
b43_radio_set(dev, 0x129, 0x2);
b43_radio_set(dev, 0x057, 0x1);
b43_radio_set(dev, 0x05b, 0x2);
/* TODO: wait for some bit to be set */
b43_radio_read(dev, 0x05c);
b43_radio_mask(dev, 0x05b, (u16) ~0xff02);
b43_radio_mask(dev, 0x057, (u16) ~0xff01);
b43_phy_write(dev, 0x933, 0x2d6b);
b43_phy_write(dev, 0x934, 0x2d6b);
b43_phy_write(dev, 0x935, 0x2d6b);
b43_phy_write(dev, 0x936, 0x2d6b);
b43_phy_write(dev, 0x937, 0x016b);
b43_radio_mask(dev, 0x057, (u16) ~0xff02);
b43_radio_write(dev, 0x0c2, 0x006f);
}
/**************************************************
* Various PHY ops
**************************************************/
static void b43_phy_lcn_afe_set_unset(struct b43_wldev *dev)
{
u16 afe_ctl2 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL2);
u16 afe_ctl1 = b43_phy_read(dev, B43_PHY_LCN_AFE_CTL1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 | 0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 | 0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2 & ~0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1 & ~0x1);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL2, afe_ctl2);
b43_phy_write(dev, B43_PHY_LCN_AFE_CTL1, afe_ctl1);
}
static void b43_phy_lcn_clean_0x18_table(struct b43_wldev *dev)
{
u8 i;
for (i = 0; i < 0x80; i++)
b43_lcntab_write(dev, B43_LCNTAB32(0x18, i), 0x80000);
}
static void b43_phy_lcn_clear_0x07_table(struct b43_wldev *dev)
{
u8 i;
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x340);
for (i = 0; i < 30; i++) {
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
}
b43_phy_write(dev, B43_PHY_LCN_TABLE_ADDR, (0x7 << 10) | 0x80);
for (i = 0; i < 64; i++) {
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATAHI, 0);
b43_phy_write(dev, B43_PHY_LCN_TABLE_DATALO, 0);
}
}
/**************************************************
* Basic PHY ops.
**************************************************/
static int b43_phy_lcn_op_allocate(struct b43_wldev *dev)
{
struct b43_phy_lcn *phy_lcn;
phy_lcn = kzalloc(sizeof(*phy_lcn), GFP_KERNEL);
if (!phy_lcn)
return -ENOMEM;
dev->phy.lcn = phy_lcn;
return 0;
}
static void b43_phy_lcn_op_free(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_lcn *phy_lcn = phy->lcn;
kfree(phy_lcn);
phy->lcn = NULL;
}
static void b43_phy_lcn_op_prepare_structs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_lcn *phy_lcn = phy->lcn;
memset(phy_lcn, 0, sizeof(*phy_lcn));
}
static int b43_phy_lcn_op_init(struct b43_wldev *dev)
{
b43_phy_set(dev, 0x44a, 0x80);
b43_phy_mask(dev, 0x44a, 0x7f);
b43_phy_set(dev, 0x6d1, 0x80);
b43_phy_write(dev, 0x6d0, 0x7);
b43_phy_lcn_afe_set_unset(dev);
b43_phy_write(dev, 0x60a, 0xa0);
b43_phy_write(dev, 0x46a, 0x19);
b43_phy_maskset(dev, 0x663, 0xFF00, 0x64);
b43_phy_lcn_tables_init(dev);
/* TODO: various tables ops here */
b43_phy_lcn_clean_0x18_table(dev);
/* TODO: some ops here */
b43_phy_lcn_clear_0x07_table(dev);
if (dev->phy.radio_ver == 0x2064)
b43_radio_2064_init(dev);
else
B43_WARN_ON(1);
return 0;
}
static void b43_phy_lcn_op_software_rfkill(struct b43_wldev *dev,
bool blocked)
{
if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
b43err(dev->wl, "MAC not suspended\n");
if (blocked) {
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL2, ~0x7c00);
b43_phy_set(dev, B43_PHY_LCN_RF_CTL1, 0x1f00);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL5, ~0x7f00);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL4, ~0x2);
b43_phy_set(dev, B43_PHY_LCN_RF_CTL3, 0x808);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL7, ~0x8);
b43_phy_set(dev, B43_PHY_LCN_RF_CTL6, 0x8);
} else {
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL1, ~0x1f00);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL3, ~0x808);
b43_phy_mask(dev, B43_PHY_LCN_RF_CTL6, ~0x8);
}
}
static void b43_phy_lcn_op_switch_analog(struct b43_wldev *dev, bool on)
{
if (on) {
b43_phy_mask(dev, B43_PHY_LCN_AFE_CTL1, ~0x7);
} else {
b43_phy_set(dev, B43_PHY_LCN_AFE_CTL2, 0x7);
b43_phy_set(dev, B43_PHY_LCN_AFE_CTL1, 0x7);
}
}
static unsigned int b43_phy_lcn_op_get_default_chan(struct b43_wldev *dev)
{
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
return 1;
return 36;
}
static enum b43_txpwr_result
b43_phy_lcn_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
{
return B43_TXPWR_RES_DONE;
}
static void b43_phy_lcn_op_adjust_txpower(struct b43_wldev *dev)
{
}
/**************************************************
* PHY ops struct.
**************************************************/
const struct b43_phy_operations b43_phyops_lcn = {
/*
.allocate = b43_phy_lcn_op_allocate,
.free = b43_phy_lcn_op_free,
.prepare_structs = b43_phy_lcn_op_prepare_structs,
.init = b43_phy_lcn_op_init,
/*
.phy_read = b43_phy_lcn_op_read,
.phy_write = b43_phy_lcn_op_write,
.phy_maskset = b43_phy_lcn_op_maskset,
.radio_read = b43_phy_lcn_op_radio_read,
.radio_write = b43_phy_lcn_op_radio_write,
*/
.software_rfkill = b43_phy_lcn_op_software_rfkill,
.switch_analog = b43_phy_lcn_op_switch_analog,
/*
.switch_channel = b43_phy_lcn_op_switch_channel,
*/
.get_default_chan = b43_phy_lcn_op_get_default_chan,
.recalc_txpower = b43_phy_lcn_op_recalc_txpower,
.adjust_txpower = b43_phy_lcn_op_adjust_txpower,
*/
};
......@@ -4,6 +4,20 @@
#include "phy_common.h"
#define B43_PHY_LCN_AFE_CTL1 B43_PHY_OFDM(0x03B)
#define B43_PHY_LCN_AFE_CTL2 B43_PHY_OFDM(0x03C)
#define B43_PHY_LCN_RF_CTL1 B43_PHY_OFDM(0x04C)
#define B43_PHY_LCN_RF_CTL2 B43_PHY_OFDM(0x04D)
#define B43_PHY_LCN_TABLE_ADDR B43_PHY_OFDM(0x055) /* Table address */
#define B43_PHY_LCN_TABLE_DATALO B43_PHY_OFDM(0x056) /* Table data low */
#define B43_PHY_LCN_TABLE_DATAHI B43_PHY_OFDM(0x057) /* Table data high */
#define B43_PHY_LCN_RF_CTL3 B43_PHY_OFDM(0x0B0)
#define B43_PHY_LCN_RF_CTL4 B43_PHY_OFDM(0x0B1)
#define B43_PHY_LCN_RF_CTL5 B43_PHY_OFDM(0x0B7)
#define B43_PHY_LCN_RF_CTL6 B43_PHY_OFDM(0x0F9)
#define B43_PHY_LCN_RF_CTL7 B43_PHY_OFDM(0x0FA)
struct b43_phy_lcn {
};
......@@ -11,4 +25,4 @@ struct b43_phy_lcn {
struct b43_phy_operations;
extern const struct b43_phy_operations b43_phyops_lcn;
#endif /* B43_PHY_LCN_H_ */
\ No newline at end of file
#endif /* B43_PHY_LCN_H_ */
......@@ -600,49 +600,17 @@ static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
{
u32 tmp;
if (dev->phy.type != B43_PHYTYPE_N)
return;
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
if (force)
tmp |= BCMA_IOCTL_FGC;
else
tmp &= ~BCMA_IOCTL_FGC;
bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
break;
#endif
#ifdef CONFIG_B43_SSB
case B43_BUS_SSB:
tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
if (force)
tmp |= SSB_TMSLOW_FGC;
else
tmp &= ~SSB_TMSLOW_FGC;
ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
break;
#endif
}
}
/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
static void b43_nphy_reset_cca(struct b43_wldev *dev)
{
u16 bbcfg;
b43_nphy_bmac_clock_fgc(dev, 1);
b43_phy_force_clock(dev, 1);
bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
udelay(1);
b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
b43_nphy_bmac_clock_fgc(dev, 0);
b43_phy_force_clock(dev, 0);
b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
}
......@@ -3715,11 +3683,11 @@ int b43_phy_initn(struct b43_wldev *dev)
b43_nphy_workarounds(dev);
/* Reset CCA, in init code it differs a little from standard way */
b43_nphy_bmac_clock_fgc(dev, 1);
b43_phy_force_clock(dev, 1);
tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
b43_nphy_bmac_clock_fgc(dev, 0);
b43_phy_force_clock(dev, 0);
b43_mac_phy_clock_set(dev, true);
......
......@@ -611,7 +611,7 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
struct b43_wldev *dev = q->dev;
struct b43_wl *wl = dev->wl;
u16 len;
u32 macstat;
u32 macstat = 0;
unsigned int i, padding;
struct sk_buff *skb;
const char *err_msg = NULL;
......@@ -676,7 +676,15 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
goto rx_error;
}
macstat = le32_to_cpu(rxhdr->mac_status);
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
macstat = le32_to_cpu(rxhdr->format_598.mac_status);
break;
case B43_FW_HDR_410:
case B43_FW_HDR_351:
macstat = le32_to_cpu(rxhdr->format_351.mac_status);
break;
}
if (macstat & B43_RX_MAC_FCSERR) {
if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
/* Drop frames with failed FCS. */
......
......@@ -574,6 +574,42 @@ static const u32 b43_httab_0x24[] = {
0x005d0582, 0x005805d6, 0x0053062e, 0x004e068c,
};
/* Some late-init table */
const u32 b43_httab_0x1a_0xc0_late[] = {
0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
0x10390038, 0x10390035, 0x1031003a, 0x10310036,
0x10310033, 0x1029003a, 0x10290037, 0x10290034,
0x10290031, 0x10210039, 0x10210036, 0x10210033,
0x10210030, 0x1019003c, 0x10190039, 0x10190036,
0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
0x10190028, 0x1011003a, 0x10110036, 0x10110033,
0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
0x10110027, 0x10110024, 0x10110022, 0x10110020,
0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
0x10090029, 0x10090027, 0x10090025, 0x10090023,
0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
0x1009001a, 0x10090018, 0x10090017, 0x10090016,
0x10090015, 0x10090013, 0x10090012, 0x10090011,
0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
0x10090008, 0x10090008, 0x10090007, 0x10090007,
0x10090007, 0x10090006, 0x10090006, 0x10090005,
0x10090005, 0x10090005, 0x10090005, 0x10090004,
0x10090004, 0x10090004, 0x10090004, 0x10090003,
0x10090003, 0x10090003, 0x10090003, 0x10090003,
0x10090003, 0x10090002, 0x10090002, 0x10090002,
0x10090002, 0x10090002, 0x10090002, 0x10090002,
0x10090002, 0x10090002, 0x10090001, 0x10090001,
0x10090001, 0x10090001, 0x10090001, 0x10090001,
};
/**************************************************
* R/W ops.
**************************************************/
......@@ -674,6 +710,51 @@ void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value)
return;
}
void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...)
{
va_list args;
u32 type, value;
unsigned int i;
type = offset & B43_HTTAB_TYPEMASK;
offset &= 0xFFFF;
va_start(args, num);
switch (type) {
case B43_HTTAB_8BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < num; i++) {
value = va_arg(args, int);
B43_WARN_ON(value & ~0xFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
}
break;
case B43_HTTAB_16BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < num; i++) {
value = va_arg(args, int);
B43_WARN_ON(value & ~0xFFFF);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, value);
}
break;
case B43_HTTAB_32BIT:
b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, offset);
for (i = 0; i < num; i++) {
value = va_arg(args, int);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI,
value >> 16);
b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO,
value & 0xFFFF);
}
break;
default:
B43_WARN_ON(1);
}
va_end(args);
return;
}
void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data)
{
......@@ -723,6 +804,9 @@ void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
} while (0)
void b43_phy_ht_tables_init(struct b43_wldev *dev)
{
BUILD_BUG_ON(ARRAY_SIZE(b43_httab_0x1a_0xc0_late) !=
B43_HTTAB_1A_C0_LATE_SIZE);
httab_upload(dev, B43_HTTAB16(0x12, 0), b43_httab_0x12);
httab_upload(dev, B43_HTTAB16(0x27, 0), b43_httab_0x27);
httab_upload(dev, B43_HTTAB16(0x26, 0), b43_httab_0x26);
......
......@@ -14,9 +14,13 @@ u32 b43_httab_read(struct b43_wldev *dev, u32 offset);
void b43_httab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data);
void b43_httab_write(struct b43_wldev *dev, u32 offset, u32 value);
void b43_httab_write_few(struct b43_wldev *dev, u32 offset, size_t num, ...);
void b43_httab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
void b43_phy_ht_tables_init(struct b43_wldev *dev);
#define B43_HTTAB_1A_C0_LATE_SIZE 128
extern const u32 b43_httab_0x1a_0xc0_late[];
#endif /* B43_TABLES_PHY_HT_H_ */
#ifndef B43_TABLES_PHY_LCN_H_
#define B43_TABLES_PHY_LCN_H_
/* The LCN-PHY tables. */
#define B43_LCNTAB_TYPEMASK 0xF0000000
#define B43_LCNTAB_8BIT 0x10000000
#define B43_LCNTAB_16BIT 0x20000000
#define B43_LCNTAB_32BIT 0x30000000
#define B43_LCNTAB8(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_8BIT)
#define B43_LCNTAB16(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_16BIT)
#define B43_LCNTAB32(table, offset) (((table) << 10) | (offset) | B43_LCNTAB_32BIT)
u32 b43_lcntab_read(struct b43_wldev *dev, u32 offset);
void b43_lcntab_read_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, void *_data);
void b43_lcntab_write(struct b43_wldev *dev, u32 offset, u32 value);
void b43_lcntab_write_bulk(struct b43_wldev *dev, u32 offset,
unsigned int nr_elements, const void *_data);
void b43_phy_lcn_tables_init(struct b43_wldev *dev);
#endif /* B43_TABLES_PHY_LCN_H_ */
......@@ -337,12 +337,19 @@ int b43_generate_txhdr(struct b43_wldev *dev,
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
}
}
if (b43_is_old_txhdr_format(dev)) {
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_598.plcp),
plcp_fragment_len, rate);
} else {
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
break;
case B43_FW_HDR_351:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_351.plcp),
plcp_fragment_len, rate);
break;
case B43_FW_HDR_410:
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->format_410.plcp),
plcp_fragment_len, rate);
break;
}
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
plcp_fragment_len, rate_fb);
......@@ -415,10 +422,10 @@ int b43_generate_txhdr(struct b43_wldev *dev,
if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
(rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
unsigned int len;
struct ieee80211_hdr *hdr;
struct ieee80211_hdr *uninitialized_var(hdr);
int rts_rate, rts_rate_fb;
int rts_rate_ofdm, rts_rate_fb_ofdm;
struct b43_plcp_hdr6 *plcp;
struct b43_plcp_hdr6 *uninitialized_var(plcp);
struct ieee80211_rate *rts_cts_rate;
rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info);
......@@ -429,14 +436,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
struct ieee80211_cts *cts;
struct ieee80211_cts *uninitialized_var(cts);
if (b43_is_old_txhdr_format(dev)) {
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
cts = (struct ieee80211_cts *)
(txhdr->old_format.rts_frame);
} else {
(txhdr->format_598.rts_frame);
break;
case B43_FW_HDR_351:
cts = (struct ieee80211_cts *)
(txhdr->new_format.rts_frame);
(txhdr->format_351.rts_frame);
break;
case B43_FW_HDR_410:
cts = (struct ieee80211_cts *)
(txhdr->format_410.rts_frame);
break;
}
ieee80211_ctstoself_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
......@@ -444,14 +458,21 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= B43_TXH_MAC_SENDCTS;
len = sizeof(struct ieee80211_cts);
} else {
struct ieee80211_rts *rts;
struct ieee80211_rts *uninitialized_var(rts);
if (b43_is_old_txhdr_format(dev)) {
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
rts = (struct ieee80211_rts *)
(txhdr->old_format.rts_frame);
} else {
(txhdr->format_598.rts_frame);
break;
case B43_FW_HDR_351:
rts = (struct ieee80211_rts *)
(txhdr->format_351.rts_frame);
break;
case B43_FW_HDR_410:
rts = (struct ieee80211_rts *)
(txhdr->new_format.rts_frame);
(txhdr->format_410.rts_frame);
break;
}
ieee80211_rts_get(dev->wl->hw, info->control.vif,
fragment_data, fragment_len,
......@@ -462,22 +483,36 @@ int b43_generate_txhdr(struct b43_wldev *dev,
len += FCS_LEN;
/* Generate the PLCP headers for the RTS/CTS frame */
if (b43_is_old_txhdr_format(dev))
plcp = &txhdr->old_format.rts_plcp;
else
plcp = &txhdr->new_format.rts_plcp;
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
plcp = &txhdr->format_598.rts_plcp;
break;
case B43_FW_HDR_351:
plcp = &txhdr->format_351.rts_plcp;
break;
case B43_FW_HDR_410:
plcp = &txhdr->format_410.rts_plcp;
break;
}
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate);
plcp = &txhdr->rts_plcp_fb;
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate_fb);
if (b43_is_old_txhdr_format(dev)) {
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
hdr = (struct ieee80211_hdr *)
(&txhdr->old_format.rts_frame);
} else {
(&txhdr->format_598.rts_frame);
break;
case B43_FW_HDR_351:
hdr = (struct ieee80211_hdr *)
(&txhdr->format_351.rts_frame);
break;
case B43_FW_HDR_410:
hdr = (struct ieee80211_hdr *)
(&txhdr->new_format.rts_frame);
(&txhdr->format_410.rts_frame);
break;
}
txhdr->rts_dur_fb = hdr->duration_id;
......@@ -505,10 +540,17 @@ int b43_generate_txhdr(struct b43_wldev *dev,
}
/* Magic cookie */
if (b43_is_old_txhdr_format(dev))
txhdr->old_format.cookie = cpu_to_le16(cookie);
else
txhdr->new_format.cookie = cpu_to_le16(cookie);
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
txhdr->format_598.cookie = cpu_to_le16(cookie);
break;
case B43_FW_HDR_351:
txhdr->format_351.cookie = cpu_to_le16(cookie);
break;
case B43_FW_HDR_410:
txhdr->format_410.cookie = cpu_to_le16(cookie);
break;
}
if (phy->type == B43_PHYTYPE_N) {
txhdr->phy_ctl1 =
......@@ -611,8 +653,9 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
struct ieee80211_hdr *wlhdr;
const struct b43_rxhdr_fw4 *rxhdr = _rxhdr;
__le16 fctl;
u16 phystat0, phystat3, chanstat, mactime;
u32 macstat;
u16 phystat0, phystat3;
u16 uninitialized_var(chanstat), uninitialized_var(mactime);
u32 uninitialized_var(macstat);
u16 chanid;
u16 phytype;
int padding;
......@@ -622,9 +665,19 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
/* Get metadata about the frame from the header. */
phystat0 = le16_to_cpu(rxhdr->phy_status0);
phystat3 = le16_to_cpu(rxhdr->phy_status3);
macstat = le32_to_cpu(rxhdr->mac_status);
mactime = le16_to_cpu(rxhdr->mac_time);
chanstat = le16_to_cpu(rxhdr->channel);
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
macstat = le32_to_cpu(rxhdr->format_598.mac_status);
mactime = le16_to_cpu(rxhdr->format_598.mac_time);
chanstat = le16_to_cpu(rxhdr->format_598.channel);
break;
case B43_FW_HDR_410:
case B43_FW_HDR_351:
macstat = le32_to_cpu(rxhdr->format_351.mac_status);
mactime = le16_to_cpu(rxhdr->format_351.mac_time);
chanstat = le16_to_cpu(rxhdr->format_351.channel);
break;
}
phytype = chanstat & B43_RX_CHAN_PHYTYPE;
if (unlikely(macstat & B43_RX_MAC_FCSERR)) {
......@@ -744,6 +797,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
break;
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
case B43_PHYTYPE_HT:
/* chanid is the SHM channel cookie. Which is the plain
* channel number in b43. */
if (chanstat & B43_RX_CHAN_5GHZ) {
......
......@@ -46,7 +46,24 @@ struct b43_txhdr {
__le32 timeout; /* Timeout */
union {
/* The new r410 format. */
/* Tested with 598.314, 644.1001 and 666.2 */
struct {
__le16 mimo_antenna; /* MIMO antenna select */
__le16 preload_size; /* Preload size */
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
__le16 tx_status; /* TX status */
__le16 max_n_mpdus;
__le16 max_a_bytes_mrt;
__le16 max_a_bytes_fbr;
__le16 min_m_bytes;
struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
} format_598 __packed;
/* Tested with 410.2160, 478.104 and 508.* */
struct {
__le16 mimo_antenna; /* MIMO antenna select */
__le16 preload_size; /* Preload size */
......@@ -57,9 +74,9 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
} new_format __packed;
} format_410 __packed;
/* The old r351 format. */
/* Tested with 351.126 */
struct {
PAD_BYTES(2);
__le16 cookie; /* TX frame cookie */
......@@ -68,7 +85,7 @@ struct b43_txhdr {
__u8 rts_frame[16]; /* The RTS frame (if used) */
PAD_BYTES(2);
struct b43_plcp_hdr6 plcp; /* Main PLCP header */
} old_format __packed;
} format_351 __packed;
} __packed;
} __packed;
......@@ -166,19 +183,18 @@ struct b43_tx_legacy_rate_phy_ctl_entry {
#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */
/* r351 firmware compatibility stuff. */
static inline
bool b43_is_old_txhdr_format(struct b43_wldev *dev)
{
return (dev->fw.rev <= 351);
}
static inline
size_t b43_txhdr_size(struct b43_wldev *dev)
{
if (b43_is_old_txhdr_format(dev))
switch (dev->fw.hdr_format) {
case B43_FW_HDR_598:
return 112 + sizeof(struct b43_plcp_hdr6);
case B43_FW_HDR_410:
return 104 + sizeof(struct b43_plcp_hdr6);
case B43_FW_HDR_351:
return 100 + sizeof(struct b43_plcp_hdr6);
return 104 + sizeof(struct b43_plcp_hdr6);
}
return 0;
}
......@@ -234,9 +250,23 @@ struct b43_rxhdr_fw4 {
} __packed;
__le16 phy_status2; /* PHY RX Status 2 */
__le16 phy_status3; /* PHY RX Status 3 */
__le32 mac_status; /* MAC RX status */
__le16 mac_time;
__le16 channel;
union {
/* Tested with 598.314, 644.1001 and 666.2 */
struct {
__le16 phy_status4; /* PHY RX Status 4 */
__le16 phy_status5; /* PHY RX Status 5 */
__le32 mac_status; /* MAC RX status */
__le16 mac_time;
__le16 channel;
} format_598 __packed;
/* Tested with 351.126, 410.2160, 478.104 and 508.* */
struct {
__le32 mac_status; /* MAC RX status */
__le16 mac_time;
__le16 channel;
} format_351 __packed;
} __packed;
} __packed;
/* PHY RX Status 0 */
......
......@@ -22,10 +22,6 @@
#include "phy.h"
/* The unique identifier of the firmware that's officially supported by this
* driver version. */
#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10"
#define B43legacy_IRQWAIT_MAX_RETRIES 20
/* MMIO offsets */
......
......@@ -60,7 +60,6 @@ MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43legacy/ucode2.fw");
MODULE_FIRMWARE("b43legacy/ucode4.fw");
......@@ -3947,8 +3946,7 @@ static void b43legacy_print_driverinfo(void)
feat_dma = "D";
#endif
printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
"[ Features: %s%s%s%s, Firmware-ID: "
B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
"[ Features: %s%s%s%s ]\n",
feat_pci, feat_leds, feat_pio, feat_dma);
}
......
......@@ -238,28 +238,3 @@ hostsleep
echo "1" > hostsleep : enable host sleep.
echo "0" > hostsleep : disable host sleep
========================
IWCONFIG COMMANDS
========================
power period
This command is used to configure the station in deep sleep mode /
auto deep sleep mode.
The timer is implemented to monitor the activities (command, event,
etc.). When an activity is detected station will exit from deep
sleep mode automatically and restart the timer. At timer expiry
(no activity for defined time period) the deep sleep mode is entered
automatically.
Note: this command is for SDIO interface only.
Usage:
To enable deep sleep mode do:
iwconfig wlan0 power period 0
To enable auto deep sleep mode with idle time period 5 seconds do:
iwconfig wlan0 power period 5
To disable deep sleep/auto deep sleep mode do:
iwconfig wlan0 power period -1
==============================================================================
......@@ -190,8 +190,8 @@ static inline int lbs_iface_active(struct lbs_private *priv)
int r;
r = netif_running(priv->dev);
if (priv->mesh_dev);
r |= netif_running(priv->dev);
if (priv->mesh_dev)
r |= netif_running(priv->mesh_dev);
return r;
}
......
......@@ -1480,8 +1480,8 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
return -ENOMEM;
}
beacon_ie = kzalloc(ie_len, GFP_KERNEL);
if (!bss_desc) {
dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
if (!beacon_ie) {
dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
return -ENOMEM;
}
memcpy(beacon_ie, ie_buf, ie_len);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
新手
引导
客服 返回
顶部