mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 06:31:52 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Conflicts: drivers/net/wireless/libertas_tf/cmd.c drivers/net/wireless/libertas_tf/main.c
This commit is contained in:
commit
83163244f8
@ -3956,6 +3956,7 @@ F: net/rfkill/
|
||||
F: net/wireless/
|
||||
F: include/net/ieee80211*
|
||||
F: include/linux/wireless.h
|
||||
F: include/linux/iw_handler.h
|
||||
F: drivers/net/wireless/
|
||||
|
||||
NETWORKING DRIVERS
|
||||
|
@ -38,6 +38,12 @@ config LIBERTAS_THINFIRM
|
||||
---help---
|
||||
A library for Marvell Libertas 8xxx devices using thinfirm.
|
||||
|
||||
config LIBERTAS_THINFIRM_DEBUG
|
||||
bool "Enable full debugging output in the Libertas thin firmware module."
|
||||
depends on LIBERTAS_THINFIRM
|
||||
---help---
|
||||
Debugging support.
|
||||
|
||||
config LIBERTAS_THINFIRM_USB
|
||||
tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
|
||||
depends on LIBERTAS_THINFIRM && USB
|
||||
|
@ -1889,6 +1889,7 @@ static void at76_dwork_hw_scan(struct work_struct *work)
|
||||
}
|
||||
|
||||
static int at76_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct at76_priv *priv = hw->priv;
|
||||
|
@ -927,7 +927,6 @@ static void ar9170_rx_phy_status(struct ar9170 *ar,
|
||||
|
||||
/* TODO: we could do something with phy_errors */
|
||||
status->signal = ar->noise[0] + phy->rssi_combined;
|
||||
status->noise = ar->noise[0];
|
||||
}
|
||||
|
||||
static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len)
|
||||
@ -2548,8 +2547,7 @@ void *ar9170_alloc(size_t priv_size)
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
IEEE80211_HW_SIGNAL_DBM;
|
||||
|
||||
if (modparam_ht) {
|
||||
ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
|
||||
|
@ -548,8 +548,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
IEEE80211_HW_SIGNAL_DBM;
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
@ -2030,8 +2029,7 @@ accept:
|
||||
rxs->freq = sc->curchan->center_freq;
|
||||
rxs->band = sc->curband->band;
|
||||
|
||||
rxs->noise = sc->ah->ah_noise_floor;
|
||||
rxs->signal = rxs->noise + rs.rs_rssi;
|
||||
rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi;
|
||||
|
||||
rxs->antenna = rs.rs_antenna;
|
||||
|
||||
|
@ -657,12 +657,3 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
if (ah->config.enable_ani)
|
||||
ah->proc_phyerr |= HAL_PROCESS_ANI;
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_disable(struct ath_hw *ah)
|
||||
{
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n");
|
||||
|
||||
ath9k_hw_disable_mib_counters(ah);
|
||||
REG_WRITE(ah, AR_PHY_ERR_1, 0);
|
||||
REG_WRITE(ah, AR_PHY_ERR_2, 0);
|
||||
}
|
||||
|
@ -118,6 +118,5 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
|
||||
void ath9k_hw_procmibevent(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_disable(struct ath_hw *ah);
|
||||
|
||||
#endif /* ANI_H */
|
||||
|
@ -249,7 +249,7 @@ static const u32 ar5416Common[][2] = {
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8000010 },
|
||||
{ 0x00008264, 0x88000010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
|
@ -850,7 +850,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
|
||||
|
||||
REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
|
||||
|
||||
if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
|
||||
if (IS_CHAN_A_FAST_CLOCK(ah, chan)) {
|
||||
REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
|
||||
regWrites);
|
||||
}
|
||||
@ -892,8 +892,7 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
rfMode |= (IS_CHAN_5GHZ(chan)) ?
|
||||
AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
|
||||
|
||||
if ((AR_SREV_9280_20(ah) || AR_SREV_9300_20_OR_LATER(ah))
|
||||
&& IS_CHAN_A_5MHZ_SPACED(chan))
|
||||
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
|
||||
rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_MODE, rfMode);
|
||||
|
@ -408,6 +408,8 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
|
||||
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
||||
|
||||
} else {
|
||||
ENABLE_REGWRITE_BUFFER(ah);
|
||||
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
|
||||
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
|
||||
|
||||
@ -428,6 +430,9 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
|
||||
|
||||
/* Load the new settings */
|
||||
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
|
||||
|
||||
REGWRITE_BUFFER_FLUSH(ah);
|
||||
DISABLE_REGWRITE_BUFFER(ah);
|
||||
}
|
||||
|
||||
udelay(1000);
|
||||
|
@ -793,7 +793,7 @@ static const u32 ar9280Common_9280_2[][2] = {
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8a00010 },
|
||||
{ 0x00008264, 0x88a00010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
@ -1963,7 +1963,7 @@ static const u32 ar9285Common_9285[][2] = {
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8a00010 },
|
||||
{ 0x00008264, 0x88a00010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
@ -3185,7 +3185,7 @@ static const u32 ar9287Common_9287_1_0[][2] = {
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8a00010 },
|
||||
{ 0x00008264, 0x88a00010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
@ -4973,7 +4973,7 @@ static const u32 ar9271Common_9271[][2] = {
|
||||
{ 0x00008258, 0x00000000 },
|
||||
{ 0x0000825c, 0x400000ff },
|
||||
{ 0x00008260, 0x00080922 },
|
||||
{ 0x00008264, 0xa8a00010 },
|
||||
{ 0x00008264, 0x88a00010 },
|
||||
{ 0x00008270, 0x00000000 },
|
||||
{ 0x00008274, 0x40000000 },
|
||||
{ 0x00008278, 0x003e4180 },
|
||||
|
@ -455,16 +455,12 @@ static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
|
||||
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
|
||||
|
||||
if (chan && IS_CHAN_5GHZ(chan)) {
|
||||
pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
|
||||
|
||||
|
||||
if (AR_SREV_9280_20(ah)) {
|
||||
if (((chan->channel % 20) == 0)
|
||||
|| ((chan->channel % 10) == 0))
|
||||
pll = 0x2850;
|
||||
else
|
||||
pll = 0x142c;
|
||||
}
|
||||
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
|
||||
pll = 0x142c;
|
||||
else if (AR_SREV_9280_20(ah))
|
||||
pll = 0x2850;
|
||||
else
|
||||
pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
|
||||
} else {
|
||||
pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
|
||||
}
|
||||
|
@ -755,7 +755,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
}
|
||||
|
||||
/* Do Tx IQ Calibration */
|
||||
ar9003_hw_tx_iq_cal(ah);
|
||||
if (ah->config.tx_iq_calibration)
|
||||
ar9003_hw_tx_iq_cal(ah);
|
||||
|
||||
/* Revert chainmasks to their original values before NF cal */
|
||||
ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
|
||||
|
@ -659,6 +659,9 @@ static void ar9300_swap_eeprom(struct ar9300_eeprom *eep)
|
||||
word = swab16(eep->baseEepHeader.regDmn[1]);
|
||||
eep->baseEepHeader.regDmn[1] = word;
|
||||
|
||||
dword = swab32(eep->baseEepHeader.swreg);
|
||||
eep->baseEepHeader.swreg = dword;
|
||||
|
||||
dword = swab32(eep->modalHeader2G.antCtrlCommon);
|
||||
eep->modalHeader2G.antCtrlCommon = dword;
|
||||
|
||||
@ -1200,7 +1203,7 @@ static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
|
||||
u8 *pFreqBin;
|
||||
|
||||
if (is2GHz) {
|
||||
numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
|
||||
numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
|
||||
pEepromTargetPwr = eep->calTargetPower2G;
|
||||
pFreqBin = eep->calTarget_freqbin_2G;
|
||||
} else {
|
||||
@ -1236,7 +1239,7 @@ static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
|
||||
u8 *pFreqBin;
|
||||
|
||||
if (is2GHz) {
|
||||
numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
|
||||
numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
|
||||
pEepromTargetPwr = eep->calTargetPower2GHT20;
|
||||
pFreqBin = eep->calTarget_freqbin_2GHT20;
|
||||
} else {
|
||||
@ -1817,6 +1820,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit)
|
||||
{
|
||||
ah->txpower_limit = powerLimit;
|
||||
ar9003_hw_set_target_power_eeprom(ah, chan->channel);
|
||||
ar9003_hw_calibration_apply(ah, chan->channel);
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ struct cal_ctl_edge_pwr {
|
||||
} __packed;
|
||||
|
||||
struct cal_ctl_data_2g {
|
||||
struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G];
|
||||
struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G];
|
||||
} __packed;
|
||||
|
||||
struct cal_ctl_data_5g {
|
||||
|
@ -31,7 +31,7 @@ static const u32 ar9300_2p0_radio_postamble[][5] = {
|
||||
|
||||
static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
|
||||
@ -545,7 +545,7 @@ static const u32 ar9300_2p0_soc_postamble[][5] = {
|
||||
};
|
||||
|
||||
static const u32 ar9200_merlin_2p0_radio_core[][2] = {
|
||||
/* Addr common */
|
||||
/* Addr allmodes */
|
||||
{0x00007800, 0x00040000},
|
||||
{0x00007804, 0xdb005012},
|
||||
{0x00007808, 0x04924914},
|
||||
@ -835,71 +835,71 @@ static const u32 ar9300_2p0_baseband_core[][2] = {
|
||||
|
||||
static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da},
|
||||
{0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400},
|
||||
{0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402},
|
||||
{0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603},
|
||||
{0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02},
|
||||
{0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04},
|
||||
{0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20},
|
||||
{0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20},
|
||||
{0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22},
|
||||
{0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24},
|
||||
{0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640},
|
||||
{0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660},
|
||||
{0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84},
|
||||
{0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
|
||||
{0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
|
||||
{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
|
||||
{0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
|
||||
{0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
|
||||
{0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
|
||||
{0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20},
|
||||
{0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22},
|
||||
{0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24},
|
||||
{0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640},
|
||||
{0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660},
|
||||
{0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84},
|
||||
{0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000},
|
||||
{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002},
|
||||
{0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004},
|
||||
{0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200},
|
||||
{0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202},
|
||||
{0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400},
|
||||
{0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402},
|
||||
{0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404},
|
||||
{0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603},
|
||||
{0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02},
|
||||
{0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04},
|
||||
{0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20},
|
||||
{0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20},
|
||||
{0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22},
|
||||
{0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24},
|
||||
{0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640},
|
||||
{0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660},
|
||||
{0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861},
|
||||
{0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81},
|
||||
{0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83},
|
||||
{0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84},
|
||||
{0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3},
|
||||
{0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5},
|
||||
{0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9},
|
||||
{0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb},
|
||||
{0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004},
|
||||
{0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200},
|
||||
{0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202},
|
||||
{0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400},
|
||||
{0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402},
|
||||
{0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404},
|
||||
{0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603},
|
||||
{0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02},
|
||||
{0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04},
|
||||
{0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20},
|
||||
{0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20},
|
||||
{0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22},
|
||||
{0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24},
|
||||
{0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640},
|
||||
{0x0000a5c0, 0x4c8a3065, 0x44883e46, 0x44883e46, 0x38801660},
|
||||
{0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861},
|
||||
{0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81},
|
||||
{0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83},
|
||||
{0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84},
|
||||
{0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3},
|
||||
{0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5},
|
||||
{0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9},
|
||||
{0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb},
|
||||
{0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
|
||||
{0x00016048, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61},
|
||||
{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
|
||||
@ -913,71 +913,71 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
|
||||
|
||||
static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da},
|
||||
{0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400},
|
||||
{0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402},
|
||||
{0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603},
|
||||
{0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02},
|
||||
{0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04},
|
||||
{0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20},
|
||||
{0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20},
|
||||
{0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22},
|
||||
{0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24},
|
||||
{0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640},
|
||||
{0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660},
|
||||
{0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84},
|
||||
{0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
|
||||
{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
|
||||
{0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
|
||||
{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
|
||||
{0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
|
||||
{0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
|
||||
{0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
|
||||
{0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20},
|
||||
{0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22},
|
||||
{0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24},
|
||||
{0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640},
|
||||
{0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660},
|
||||
{0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84},
|
||||
{0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
|
||||
{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000},
|
||||
{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002},
|
||||
{0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004},
|
||||
{0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200},
|
||||
{0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202},
|
||||
{0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400},
|
||||
{0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402},
|
||||
{0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404},
|
||||
{0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603},
|
||||
{0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02},
|
||||
{0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04},
|
||||
{0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20},
|
||||
{0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20},
|
||||
{0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22},
|
||||
{0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24},
|
||||
{0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640},
|
||||
{0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660},
|
||||
{0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861},
|
||||
{0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81},
|
||||
{0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83},
|
||||
{0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84},
|
||||
{0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3},
|
||||
{0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5},
|
||||
{0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9},
|
||||
{0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb},
|
||||
{0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
|
||||
{0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004},
|
||||
{0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200},
|
||||
{0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202},
|
||||
{0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400},
|
||||
{0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402},
|
||||
{0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404},
|
||||
{0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603},
|
||||
{0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02},
|
||||
{0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04},
|
||||
{0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20},
|
||||
{0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20},
|
||||
{0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22},
|
||||
{0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24},
|
||||
{0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640},
|
||||
{0x0000a5c0, 0x44883e46, 0x44883e46, 0x38801660, 0x38801660},
|
||||
{0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861},
|
||||
{0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81},
|
||||
{0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83},
|
||||
{0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84},
|
||||
{0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3},
|
||||
{0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5},
|
||||
{0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9},
|
||||
{0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb},
|
||||
{0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
|
||||
{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
|
||||
{0x00016048, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
@ -1251,7 +1251,7 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
|
||||
|
||||
static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
|
||||
@ -1760,31 +1760,22 @@ static const u32 ar9300_2p0_soc_preamble[][2] = {
|
||||
{0x00007038, 0x000004c2},
|
||||
};
|
||||
|
||||
/*
|
||||
* PCIE-PHY programming array, to be used prior to entering
|
||||
* full sleep (holding RTC in reset, PLL is ON in L1 mode)
|
||||
*/
|
||||
static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00004040, 0x08212e5e},
|
||||
{0x00004040, 0x0008003b},
|
||||
{0x00004044, 0x00000000},
|
||||
};
|
||||
|
||||
/*
|
||||
* PCIE-PHY programming array, to be used when not in
|
||||
* full sleep (holding RTC in reset)
|
||||
*/
|
||||
static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00004040, 0x08253e5e},
|
||||
{0x00004040, 0x0008003b},
|
||||
{0x00004044, 0x00000000},
|
||||
};
|
||||
|
||||
/*
|
||||
* PCIE-PHY programming array, to be used prior to entering
|
||||
* full sleep (holding RTC in reset)
|
||||
*/
|
||||
static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00004040, 0x08213e5e},
|
||||
{0x00004040, 0x0008003b},
|
||||
{0x00004044, 0x00000000},
|
||||
|
@ -311,6 +311,9 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
|
||||
{
|
||||
struct ar9003_txc *ads = (struct ar9003_txc *) ds;
|
||||
|
||||
if (txpower > ah->txpower_limit)
|
||||
txpower = ah->txpower_limit;
|
||||
|
||||
txpower += ah->txpower_indexoffset;
|
||||
if (txpower > 63)
|
||||
txpower = 63;
|
||||
|
@ -375,16 +375,7 @@ static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah,
|
||||
else if (chan && IS_CHAN_QUARTER_RATE(chan))
|
||||
pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL);
|
||||
|
||||
if (chan && IS_CHAN_5GHZ(chan)) {
|
||||
pll |= SM(0x28, AR_RTC_9300_PLL_DIV);
|
||||
|
||||
/*
|
||||
* When doing fast clock, set PLL to 0x142c
|
||||
*/
|
||||
if (IS_CHAN_A_5MHZ_SPACED(chan))
|
||||
pll = 0x142c;
|
||||
} else
|
||||
pll |= SM(0x2c, AR_RTC_9300_PLL_DIV);
|
||||
pll |= SM(0x2c, AR_RTC_9300_PLL_DIV);
|
||||
|
||||
return pll;
|
||||
}
|
||||
@ -592,7 +583,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
|
||||
* For 5GHz channels requiring Fast Clock, apply
|
||||
* different modal values.
|
||||
*/
|
||||
if (IS_CHAN_A_5MHZ_SPACED(chan))
|
||||
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
|
||||
REG_WRITE_ARRAY(&ah->iniModesAdditional,
|
||||
modesIndex, regWrites);
|
||||
|
||||
@ -622,7 +613,7 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah,
|
||||
rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
|
||||
? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
|
||||
|
||||
if (IS_CHAN_A_5MHZ_SPACED(chan))
|
||||
if (IS_CHAN_A_FAST_CLOCK(ah, chan))
|
||||
rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
|
||||
|
||||
REG_WRITE(ah, AR_PHY_MODE, rfMode);
|
||||
@ -1102,6 +1093,7 @@ static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
|
||||
"to load: AR_PHY_AGC_CONTROL=0x%x\n",
|
||||
REG_READ(ah, AR_PHY_AGC_CONTROL));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -212,7 +212,6 @@ int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
|
||||
rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
|
||||
rx_status->band = hw->conf.channel->band;
|
||||
rx_status->freq = hw->conf.channel->center_freq;
|
||||
rx_status->noise = common->ani.noise_floor;
|
||||
rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
|
||||
rx_status->antenna = rx_stats->rs_antenna;
|
||||
rx_status->flag |= RX_FLAG_TSFT;
|
||||
|
@ -300,7 +300,8 @@ struct base_eep_header {
|
||||
u32 binBuildNumber;
|
||||
u8 deviceType;
|
||||
u8 pwdclkind;
|
||||
u8 futureBase_1[2];
|
||||
u8 fastClk5g;
|
||||
u8 divChain;
|
||||
u8 rxGainType;
|
||||
u8 dacHiPwrMode_5G;
|
||||
u8 openLoopPwrCntl;
|
||||
|
@ -274,6 +274,8 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
|
||||
return pBase->txMask;
|
||||
case EEP_RX_MASK:
|
||||
return pBase->rxMask;
|
||||
case EEP_FSTCLK_5G:
|
||||
return pBase->fastClk5g;
|
||||
case EEP_RXGAIN_TYPE:
|
||||
return pBase->rxGainType;
|
||||
case EEP_TXGAIN_TYPE:
|
||||
|
@ -93,63 +93,6 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hif_usb_tx_cb(struct urb *urb)
|
||||
{
|
||||
struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
|
||||
struct hif_device_usb *hif_dev = tx_buf->hif_dev;
|
||||
struct sk_buff *skb;
|
||||
bool drop, flush;
|
||||
|
||||
if (!hif_dev)
|
||||
return;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
break;
|
||||
case -ENOENT:
|
||||
case -ECONNRESET:
|
||||
break;
|
||||
case -ENODEV:
|
||||
case -ESHUTDOWN:
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (tx_buf) {
|
||||
spin_lock(&hif_dev->tx.tx_lock);
|
||||
drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP);
|
||||
flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH);
|
||||
spin_unlock(&hif_dev->tx.tx_lock);
|
||||
|
||||
while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) {
|
||||
if (!drop && !flush) {
|
||||
ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
|
||||
skb, 1);
|
||||
TX_STAT_INC(skb_completed);
|
||||
} else {
|
||||
dev_kfree_skb_any(skb);
|
||||
TX_STAT_INC(skb_dropped);
|
||||
}
|
||||
}
|
||||
|
||||
if (flush)
|
||||
return;
|
||||
|
||||
tx_buf->len = tx_buf->offset = 0;
|
||||
__skb_queue_head_init(&tx_buf->skb_queue);
|
||||
|
||||
spin_lock(&hif_dev->tx.tx_lock);
|
||||
list_del(&tx_buf->list);
|
||||
list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
|
||||
hif_dev->tx.tx_buf_cnt++;
|
||||
if (!drop)
|
||||
__hif_usb_tx(hif_dev); /* Check for pending SKBs */
|
||||
TX_STAT_INC(buf_completed);
|
||||
spin_unlock(&hif_dev->tx.tx_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
|
||||
struct sk_buff_head *list)
|
||||
{
|
||||
@ -161,6 +104,63 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
|
||||
}
|
||||
}
|
||||
|
||||
static void hif_usb_tx_cb(struct urb *urb)
|
||||
{
|
||||
struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
|
||||
struct hif_device_usb *hif_dev = tx_buf->hif_dev;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!hif_dev || !tx_buf)
|
||||
return;
|
||||
|
||||
switch (urb->status) {
|
||||
case 0:
|
||||
break;
|
||||
case -ENOENT:
|
||||
case -ECONNRESET:
|
||||
case -ENODEV:
|
||||
case -ESHUTDOWN:
|
||||
/*
|
||||
* The URB has been killed, free the SKBs
|
||||
* and return.
|
||||
*/
|
||||
ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if TX has been stopped */
|
||||
spin_lock(&hif_dev->tx.tx_lock);
|
||||
if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
|
||||
spin_unlock(&hif_dev->tx.tx_lock);
|
||||
ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
|
||||
goto add_free;
|
||||
}
|
||||
spin_unlock(&hif_dev->tx.tx_lock);
|
||||
|
||||
/* Complete the queued SKBs. */
|
||||
while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) {
|
||||
ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
|
||||
skb, 1);
|
||||
TX_STAT_INC(skb_completed);
|
||||
}
|
||||
|
||||
add_free:
|
||||
/* Re-initialize the SKB queue */
|
||||
tx_buf->len = tx_buf->offset = 0;
|
||||
__skb_queue_head_init(&tx_buf->skb_queue);
|
||||
|
||||
/* Add this TX buffer to the free list */
|
||||
spin_lock(&hif_dev->tx.tx_lock);
|
||||
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
|
||||
hif_dev->tx.tx_buf_cnt++;
|
||||
if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
|
||||
__hif_usb_tx(hif_dev); /* Check for pending SKBs */
|
||||
TX_STAT_INC(buf_completed);
|
||||
spin_unlock(&hif_dev->tx.tx_lock);
|
||||
}
|
||||
|
||||
/* TX lock has to be taken */
|
||||
static int __hif_usb_tx(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
@ -178,8 +178,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
|
||||
return 0;
|
||||
|
||||
tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list);
|
||||
list_del(&tx_buf->list);
|
||||
list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending);
|
||||
list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending);
|
||||
hif_dev->tx.tx_buf_cnt--;
|
||||
|
||||
tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM);
|
||||
@ -511,9 +510,18 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||
if (likely(urb->actual_length != 0)) {
|
||||
skb_put(skb, urb->actual_length);
|
||||
|
||||
/* Process the command first */
|
||||
ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
|
||||
skb->len, USB_REG_IN_PIPE);
|
||||
|
||||
|
||||
nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
goto resubmit;
|
||||
if (!nskb) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: REG_IN memory allocation failure\n");
|
||||
urb->context = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
usb_fill_int_urb(urb, hif_dev->udev,
|
||||
usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
|
||||
@ -523,12 +531,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
|
||||
ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
if (ret) {
|
||||
kfree_skb(nskb);
|
||||
goto free;
|
||||
urb->context = NULL;
|
||||
}
|
||||
|
||||
ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
|
||||
skb->len, USB_REG_IN_PIPE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -548,20 +553,17 @@ free:
|
||||
|
||||
static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
|
||||
|
||||
list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) {
|
||||
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
|
||||
&hif_dev->tx.tx_buf, list) {
|
||||
usb_kill_urb(tx_buf->urb);
|
||||
list_del(&tx_buf->list);
|
||||
usb_free_urb(tx_buf->urb);
|
||||
kfree(tx_buf->buf);
|
||||
kfree(tx_buf);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
||||
hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
|
||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||
|
||||
list_for_each_entry_safe(tx_buf, tx_buf_tmp,
|
||||
&hif_dev->tx.tx_pending, list) {
|
||||
usb_kill_urb(tx_buf->urb);
|
||||
@ -570,10 +572,6 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
|
||||
kfree(tx_buf->buf);
|
||||
kfree(tx_buf);
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
|
||||
hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH;
|
||||
spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
|
||||
}
|
||||
|
||||
static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
|
||||
@ -897,6 +895,26 @@ err_alloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_reboot(struct usb_device *udev)
|
||||
{
|
||||
u32 reboot_cmd = 0xffffffff;
|
||||
void *buf;
|
||||
int ret;
|
||||
|
||||
buf = kmalloc(4, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return;
|
||||
|
||||
memcpy(buf, &reboot_cmd, 4);
|
||||
|
||||
ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE),
|
||||
buf, 4, NULL, HZ);
|
||||
if (ret)
|
||||
dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n");
|
||||
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(interface);
|
||||
@ -904,14 +922,15 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
|
||||
(struct hif_device_usb *) usb_get_intfdata(interface);
|
||||
|
||||
if (hif_dev) {
|
||||
ath9k_htc_hw_deinit(hif_dev->htc_handle, true);
|
||||
ath9k_htc_hw_deinit(hif_dev->htc_handle,
|
||||
(udev->state == USB_STATE_NOTATTACHED) ? true : false);
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
ath9k_hif_usb_dev_deinit(hif_dev);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
}
|
||||
|
||||
if (hif_dev->flags & HIF_USB_START)
|
||||
usb_reset_device(udev);
|
||||
ath9k_hif_usb_reboot(udev);
|
||||
|
||||
kfree(hif_dev);
|
||||
dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
|
||||
|
@ -61,7 +61,6 @@ struct tx_buf {
|
||||
};
|
||||
|
||||
#define HIF_USB_TX_STOP BIT(0)
|
||||
#define HIF_USB_TX_FLUSH BIT(1)
|
||||
|
||||
struct hif_usb_tx {
|
||||
u8 flags;
|
||||
|
@ -329,6 +329,7 @@ struct htc_beacon_config {
|
||||
#define OP_ASSOCIATED BIT(8)
|
||||
#define OP_ENABLE_BEACON BIT(9)
|
||||
#define OP_LED_DEINIT BIT(10)
|
||||
#define OP_UNPLUGGED BIT(11)
|
||||
|
||||
struct ath9k_htc_priv {
|
||||
struct device *dev;
|
||||
@ -378,6 +379,7 @@ struct ath9k_htc_priv {
|
||||
struct mutex htc_pm_lock;
|
||||
unsigned long ps_usecount;
|
||||
bool ps_enabled;
|
||||
bool ps_idle;
|
||||
|
||||
struct ath_led radio_led;
|
||||
struct ath_led assoc_led;
|
||||
|
@ -744,6 +744,9 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
|
||||
if (ret)
|
||||
goto err_init;
|
||||
|
||||
/* The device may have been unplugged earlier. */
|
||||
priv->op_flags &= ~OP_UNPLUGGED;
|
||||
|
||||
ret = ath9k_init_device(priv, devid);
|
||||
if (ret)
|
||||
goto err_init;
|
||||
@ -760,6 +763,11 @@ err_free:
|
||||
void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
|
||||
{
|
||||
if (htc_handle->drv_priv) {
|
||||
|
||||
/* Check if the device has been yanked out. */
|
||||
if (hotunplug)
|
||||
htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
|
||||
|
||||
ath9k_deinit_device(htc_handle->drv_priv);
|
||||
ath9k_deinit_wmi(htc_handle->drv_priv);
|
||||
ieee80211_free_hw(htc_handle->drv_priv->hw);
|
||||
|
@ -94,8 +94,11 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
|
||||
if (--priv->ps_usecount != 0)
|
||||
goto unlock;
|
||||
|
||||
if (priv->ps_enabled)
|
||||
if (priv->ps_idle)
|
||||
ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
|
||||
else if (priv->ps_enabled)
|
||||
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&priv->htc_pm_lock);
|
||||
}
|
||||
@ -153,7 +156,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset channel (%u Mhz) "
|
||||
"reset status %d\n", channel->center_freq, ret);
|
||||
ath9k_htc_ps_restore(priv);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -1097,7 +1099,7 @@ fail_tx:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
static int ath9k_htc_radio_enable(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
@ -1113,8 +1115,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
"Starting driver with initial channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
/* setup initial channel */
|
||||
init_channel = ath9k_cmn_get_curchannel(hw, ah);
|
||||
|
||||
@ -1127,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d "
|
||||
"(freq %u MHz)\n", ret, curchan->center_freq);
|
||||
goto mutex_unlock;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath_update_txpow(priv);
|
||||
@ -1135,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
mode = ath9k_htc_get_curmode(priv, init_channel);
|
||||
htc_mode = cpu_to_be16(mode);
|
||||
WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
|
||||
if (ret)
|
||||
goto mutex_unlock;
|
||||
|
||||
WMI_CMD(WMI_ATH_INIT_CMDID);
|
||||
if (ret)
|
||||
goto mutex_unlock;
|
||||
|
||||
WMI_CMD(WMI_START_RECV_CMDID);
|
||||
if (ret)
|
||||
goto mutex_unlock;
|
||||
|
||||
ath9k_host_rx_init(priv);
|
||||
|
||||
@ -1157,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
|
||||
mutex_unlock:
|
||||
mutex_unlock(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
static int ath9k_htc_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ret = ath9k_htc_radio_enable(hw);
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
struct ath_hw *ah = priv->ah;
|
||||
@ -1170,14 +1172,18 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
int ret = 0;
|
||||
u8 cmd_rsp;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (priv->op_flags & OP_INVALID) {
|
||||
ath_print(common, ATH_DBG_ANY, "Device not present\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Cancel all the running timers/work .. */
|
||||
cancel_work_sync(&priv->ps_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_ani_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_aggr_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
|
||||
ath9k_led_stop_brightness(priv);
|
||||
|
||||
ath9k_htc_ps_wakeup(priv);
|
||||
htc_stop(priv->htc);
|
||||
WMI_CMD(WMI_DISABLE_INTR_CMDID);
|
||||
@ -1189,11 +1195,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
ath9k_htc_ps_restore(priv);
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
|
||||
|
||||
cancel_work_sync(&priv->ps_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_ani_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_aggr_work);
|
||||
cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
|
||||
ath9k_led_stop_brightness(priv);
|
||||
skb_queue_purge(&priv->tx_queue);
|
||||
|
||||
/* Remove monitor interface here */
|
||||
@ -1207,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
priv->op_flags |= OP_INVALID;
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
|
||||
}
|
||||
|
||||
static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
ath9k_htc_radio_disable(hw);
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
|
||||
static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -1325,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
bool enable_radio = false;
|
||||
bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
|
||||
|
||||
if (!idle && priv->ps_idle)
|
||||
enable_radio = true;
|
||||
|
||||
priv->ps_idle = idle;
|
||||
|
||||
if (enable_radio) {
|
||||
ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
|
||||
ath9k_htc_radio_enable(hw);
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"not-idle: enabling radio\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
struct ieee80211_channel *curchan = hw->conf.channel;
|
||||
int pos = curchan->hw_value;
|
||||
@ -1368,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->ps_idle) {
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"idle: disabling radio\n");
|
||||
ath9k_htc_radio_disable(hw);
|
||||
}
|
||||
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
return 0;
|
||||
|
@ -244,16 +244,25 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
|
||||
enum htc_endpoint_id ep_id, bool txok)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ieee80211_tx_info *tx_info;
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
if (ep_id == priv->mgmt_ep)
|
||||
if (ep_id == priv->mgmt_ep) {
|
||||
skb_pull(skb, sizeof(struct tx_mgmt_hdr));
|
||||
else
|
||||
/* TODO: Check for cab/uapsd/data */
|
||||
} else if ((ep_id == priv->data_bk_ep) ||
|
||||
(ep_id == priv->data_be_ep) ||
|
||||
(ep_id == priv->data_vi_ep) ||
|
||||
(ep_id == priv->data_vo_ep)) {
|
||||
skb_pull(skb, sizeof(struct tx_frame_hdr));
|
||||
} else {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unsupported TX EPID: %d\n", ep_id);
|
||||
dev_kfree_skb_any(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
@ -439,10 +448,32 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
struct sk_buff *skb = rxbuf->skb;
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath_htc_rx_status *rxstatus;
|
||||
int hdrlen, padpos, padsize;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
__le16 fc;
|
||||
|
||||
if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Corrupted RX frame, dropping\n");
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
rxstatus = (struct ath_htc_rx_status *)skb->data;
|
||||
|
||||
if (be16_to_cpu(rxstatus->rs_datalen) -
|
||||
(skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Corrupted RX data len, dropping "
|
||||
"(dlen: %d, skblen: %d)\n",
|
||||
rxstatus->rs_datalen, skb->len);
|
||||
goto rx_next;
|
||||
}
|
||||
|
||||
/* Get the RX status information */
|
||||
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
|
||||
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
|
||||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
fc = hdr->frame_control;
|
||||
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
|
||||
@ -607,8 +638,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
|
||||
struct ath_hw *ah = priv->ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
|
||||
struct ath_htc_rx_status *rxstatus;
|
||||
u32 len = 0;
|
||||
|
||||
spin_lock(&priv->rx.rxbuflock);
|
||||
list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
|
||||
@ -625,27 +654,7 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
|
||||
goto err;
|
||||
}
|
||||
|
||||
len = skb->len;
|
||||
if (len <= HTC_RX_FRAME_HEADER_SIZE) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Corrupted RX frame, dropping\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
rxstatus = (struct ath_htc_rx_status *)skb->data;
|
||||
|
||||
if (be16_to_cpu(rxstatus->rs_datalen) -
|
||||
(len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Corrupted RX data len, dropping "
|
||||
"(epid: %d, dlen: %d, skblen: %d)\n",
|
||||
ep_id, rxstatus->rs_datalen, len);
|
||||
goto err;
|
||||
}
|
||||
|
||||
spin_lock(&priv->rx.rxbuflock);
|
||||
memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
|
||||
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
|
||||
rxbuf->skb = skb;
|
||||
rxbuf->in_process = true;
|
||||
spin_unlock(&priv->rx.rxbuflock);
|
||||
|
@ -341,8 +341,9 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
|
||||
skb_pull(skb, sizeof(struct htc_frame_hdr));
|
||||
|
||||
if (endpoint->ep_callbacks.tx) {
|
||||
endpoint->ep_callbacks.tx(htc_handle->drv_priv, skb,
|
||||
htc_hdr->endpoint_id, txok);
|
||||
endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
|
||||
skb, htc_hdr->endpoint_id,
|
||||
txok);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define ATH9K_CLOCK_RATE_CCK 22
|
||||
#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
|
||||
#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
|
||||
#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44
|
||||
|
||||
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
|
||||
|
||||
@ -91,7 +92,11 @@ static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
|
||||
return usecs *ATH9K_CLOCK_RATE_CCK;
|
||||
if (conf->channel->band == IEEE80211_BAND_2GHZ)
|
||||
return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
|
||||
return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM;
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
|
||||
return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
|
||||
else
|
||||
return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM;
|
||||
}
|
||||
|
||||
static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
|
||||
@ -386,6 +391,12 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
|
||||
|
||||
ah->config.rx_intr_mitigation = true;
|
||||
|
||||
/*
|
||||
* Tx IQ Calibration (ah->config.tx_iq_calibration) is only
|
||||
* used by AR9003, but it is showing reliability issues.
|
||||
* It will take a while to fix so this is currently disabled.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We need this for PCI devices only (Cardbus, PCI, miniPCI)
|
||||
* _and_ if on non-uniprocessor systems (Multiprocessor/HT).
|
||||
@ -819,9 +830,6 @@ void ath9k_hw_deinit(struct ath_hw *ah)
|
||||
if (common->state < ATH_HW_INITIALIZED)
|
||||
goto free_hw;
|
||||
|
||||
if (!AR_SREV_9100(ah))
|
||||
ath9k_hw_ani_disable(ah);
|
||||
|
||||
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
|
||||
|
||||
free_hw:
|
||||
@ -1221,8 +1229,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
(chan->channel != ah->curchan->channel) &&
|
||||
((chan->channelFlags & CHANNEL_ALL) ==
|
||||
(ah->curchan->channelFlags & CHANNEL_ALL)) &&
|
||||
!(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) ||
|
||||
IS_CHAN_A_5MHZ_SPACED(ah->curchan))) {
|
||||
!AR_SREV_9280(ah)) {
|
||||
|
||||
if (ath9k_hw_channel_change(ah, chan)) {
|
||||
ath9k_hw_loadnf(ah, ah->curchan);
|
||||
@ -2186,7 +2193,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
}
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC;
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC |
|
||||
ATH9K_HW_CAP_FASTCLOCK;
|
||||
pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
|
||||
pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
|
||||
pCap->rx_status_len = sizeof(struct ar9003_rxs);
|
||||
@ -2194,6 +2202,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
pCap->txs_len = sizeof(struct ar9003_txs);
|
||||
} else {
|
||||
pCap->tx_desc_len = sizeof(struct ath_desc);
|
||||
if (AR_SREV_9280_20(ah) &&
|
||||
((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
|
||||
AR5416_EEP_MINOR_VER_16) ||
|
||||
ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
|
||||
}
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
|
@ -198,6 +198,7 @@ enum ath9k_hw_caps {
|
||||
ATH9K_HW_CAP_EDMA = BIT(17),
|
||||
ATH9K_HW_CAP_RAC_SUPPORTED = BIT(18),
|
||||
ATH9K_HW_CAP_LDPC = BIT(19),
|
||||
ATH9K_HW_CAP_FASTCLOCK = BIT(20),
|
||||
};
|
||||
|
||||
enum ath9k_capability_type {
|
||||
@ -261,6 +262,7 @@ struct ath9k_ops_config {
|
||||
#define AR_BASE_FREQ_5GHZ 4900
|
||||
#define AR_SPUR_FEEQ_BOUND_HT40 19
|
||||
#define AR_SPUR_FEEQ_BOUND_HT20 10
|
||||
bool tx_iq_calibration; /* Only available for >= AR9003 */
|
||||
int spurmode;
|
||||
u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
|
||||
u8 max_txtrig_level;
|
||||
@ -367,10 +369,9 @@ struct ath9k_channel {
|
||||
#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
|
||||
#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
|
||||
#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
|
||||
#define IS_CHAN_A_5MHZ_SPACED(_c) \
|
||||
#define IS_CHAN_A_FAST_CLOCK(_ah, _c) \
|
||||
((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \
|
||||
(((_c)->channel % 20) != 0) && \
|
||||
(((_c)->channel % 10) != 0))
|
||||
((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK))
|
||||
|
||||
/* These macros check chanmode and not channelFlags */
|
||||
#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
|
||||
@ -718,6 +719,7 @@ struct ath_hw {
|
||||
u32 *addac5416_21;
|
||||
u32 *bank6Temp;
|
||||
|
||||
u8 txpower_limit;
|
||||
int16_t txpower_indexoffset;
|
||||
int coverage_class;
|
||||
u32 beacon_interval;
|
||||
|
@ -878,10 +878,12 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
|
||||
if (ints & ATH9K_INT_TX) {
|
||||
if (ah->config.tx_intr_mitigation)
|
||||
mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
|
||||
if (ah->txok_interrupt_mask)
|
||||
mask |= AR_IMR_TXOK;
|
||||
if (ah->txdesc_interrupt_mask)
|
||||
mask |= AR_IMR_TXDESC;
|
||||
else {
|
||||
if (ah->txok_interrupt_mask)
|
||||
mask |= AR_IMR_TXOK;
|
||||
if (ah->txdesc_interrupt_mask)
|
||||
mask |= AR_IMR_TXDESC;
|
||||
}
|
||||
if (ah->txerr_interrupt_mask)
|
||||
mask |= AR_IMR_TXERR;
|
||||
if (ah->txeol_interrupt_mask)
|
||||
|
@ -2044,6 +2044,25 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
|
||||
if (idx != 0)
|
||||
return -ENOENT;
|
||||
|
||||
survey->channel = conf->channel;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
survey->noise = common->ani.noise_floor;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
@ -2115,6 +2134,7 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.set_tsf = ath9k_set_tsf,
|
||||
.reset_tsf = ath9k_reset_tsf,
|
||||
.ampdu_action = ath9k_ampdu_action,
|
||||
.get_survey = ath9k_get_survey,
|
||||
.sw_scan_start = ath9k_sw_scan_start,
|
||||
.sw_scan_complete = ath9k_sw_scan_complete,
|
||||
.rfkill_poll = ath9k_rfkill_poll_state,
|
||||
|
@ -276,6 +276,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||
int time_left, ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (wmi->drv_priv->op_flags & OP_UNPLUGGED)
|
||||
return 0;
|
||||
|
||||
if (!wmi)
|
||||
return -EINVAL;
|
||||
|
||||
@ -302,14 +305,14 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||
wmi->cmd_rsp_buf = rsp_buf;
|
||||
wmi->cmd_rsp_len = rsp_len;
|
||||
|
||||
ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
spin_lock_irqsave(&wmi->wmi_lock, flags);
|
||||
wmi->last_cmd_id = cmd_id;
|
||||
spin_unlock_irqrestore(&wmi->wmi_lock, flags);
|
||||
|
||||
ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
|
||||
if (!time_left) {
|
||||
ath_print(common, ATH_DBG_WMI,
|
||||
|
@ -126,14 +126,14 @@ void ath9k_wmi_tasklet(unsigned long data);
|
||||
do { \
|
||||
ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0, \
|
||||
(u8 *) &cmd_rsp, \
|
||||
sizeof(cmd_rsp), HZ); \
|
||||
sizeof(cmd_rsp), HZ*2); \
|
||||
} while (0)
|
||||
|
||||
#define WMI_CMD_BUF(_wmi_cmd, _buf) \
|
||||
do { \
|
||||
ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, \
|
||||
(u8 *) _buf, sizeof(*_buf), \
|
||||
&cmd_rsp, sizeof(cmd_rsp), HZ); \
|
||||
&cmd_rsp, sizeof(cmd_rsp), HZ*2); \
|
||||
} while (0)
|
||||
|
||||
#endif /* WMI_H */
|
||||
|
@ -2290,6 +2290,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head,
|
||||
&txs, txok, 0);
|
||||
|
||||
ath_wake_mac80211_queue(sc, txq);
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (!list_empty(&txq->txq_fifo_pending)) {
|
||||
INIT_LIST_HEAD(&bf_head);
|
||||
|
@ -4571,6 +4571,23 @@ static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw)
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
struct b43_wl *wl = hw_to_b43_wl(hw);
|
||||
struct b43_wldev *dev = wl->current_dev;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
|
||||
if (idx != 0)
|
||||
return -ENOENT;
|
||||
|
||||
survey->channel = conf->channel;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
survey->noise = dev->stats.link_noise;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops b43_hw_ops = {
|
||||
.tx = b43_op_tx,
|
||||
.conf_tx = b43_op_conf_tx,
|
||||
@ -4590,6 +4607,7 @@ static const struct ieee80211_ops b43_hw_ops = {
|
||||
.sta_notify = b43_op_sta_notify,
|
||||
.sw_scan_start = b43_op_sw_scan_start_notifier,
|
||||
.sw_scan_complete = b43_op_sw_scan_complete_notifier,
|
||||
.get_survey = b43_op_get_survey,
|
||||
.rfkill_poll = b43_rfkill_poll,
|
||||
};
|
||||
|
||||
@ -4905,8 +4923,7 @@ static int b43_wireless_init(struct ssb_device *dev)
|
||||
|
||||
/* fill hw info */
|
||||
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
IEEE80211_HW_SIGNAL_DBM;
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
|
@ -610,7 +610,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
|
||||
}
|
||||
|
||||
/* Link quality statistics */
|
||||
status.noise = dev->stats.link_noise;
|
||||
if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
|
||||
// s8 rssi = max(rxhdr->power0, rxhdr->power1);
|
||||
//TODO: Find out what the rssi value is (dBm or percentage?)
|
||||
|
@ -3482,6 +3482,23 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
struct survey_info *survey)
|
||||
{
|
||||
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
|
||||
struct b43legacy_wldev *dev = wl->current_dev;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
|
||||
if (idx != 0)
|
||||
return -ENOENT;
|
||||
|
||||
survey->channel = conf->channel;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
survey->noise = dev->stats.link_noise;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops b43legacy_hw_ops = {
|
||||
.tx = b43legacy_op_tx,
|
||||
.conf_tx = b43legacy_op_conf_tx,
|
||||
@ -3494,6 +3511,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
|
||||
.start = b43legacy_op_start,
|
||||
.stop = b43legacy_op_stop,
|
||||
.set_tim = b43legacy_op_beacon_set_tim,
|
||||
.get_survey = b43legacy_op_get_survey,
|
||||
.rfkill_poll = b43legacy_rfkill_poll,
|
||||
};
|
||||
|
||||
@ -3769,8 +3787,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
|
||||
|
||||
/* fill hw info */
|
||||
hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
IEEE80211_HW_SIGNAL_DBM;
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_AP) |
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
|
@ -548,7 +548,6 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
|
||||
(phystat0 & B43legacy_RX_PHYST0_OFDM),
|
||||
(phystat0 & B43legacy_RX_PHYST0_GAINCTL),
|
||||
(phystat3 & B43legacy_RX_PHYST3_TRSTATE));
|
||||
status.noise = dev->stats.link_noise;
|
||||
/* change to support A PHY */
|
||||
if (phystat0 & B43legacy_RX_PHYST0_OFDM)
|
||||
status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
|
||||
|
@ -22,5 +22,6 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
|
||||
# 3945
|
||||
obj-$(CONFIG_IWL3945) += iwl3945.o
|
||||
iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
|
||||
iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o
|
||||
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@ -282,7 +282,6 @@ struct iwl_cfg iwl1000_bg_cfg = {
|
||||
.use_bsm = false,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.support_ct_kill_exit = true,
|
||||
|
500
drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c
Normal file
500
drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c
Normal file
@ -0,0 +1,500 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
|
||||
#include "iwl-3945-debugfs.h"
|
||||
|
||||
ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
|
||||
sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
|
||||
ssize_t ret;
|
||||
struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
|
||||
struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
|
||||
struct iwl39_statistics_rx_non_phy *general, *accum_general;
|
||||
struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IWL_ERR(priv, "Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The statistic information display here is based on
|
||||
* the last statistics notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
ofdm = &priv->_3945.statistics.rx.ofdm;
|
||||
cck = &priv->_3945.statistics.rx.cck;
|
||||
general = &priv->_3945.statistics.rx.general;
|
||||
accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
|
||||
accum_cck = &priv->_3945.accum_statistics.rx.cck;
|
||||
accum_general = &priv->_3945.accum_statistics.rx.general;
|
||||
delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
|
||||
delta_cck = &priv->_3945.delta_statistics.rx.cck;
|
||||
delta_general = &priv->_3945.delta_statistics.rx.general;
|
||||
max_ofdm = &priv->_3945.max_delta.rx.ofdm;
|
||||
max_cck = &priv->_3945.max_delta.rx.cck;
|
||||
max_general = &priv->_3945.max_delta.rx.general;
|
||||
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - OFDM:");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
|
||||
accum_ofdm->ina_cnt,
|
||||
delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"fina_cnt:",
|
||||
le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
|
||||
delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "plcp_err:",
|
||||
le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
|
||||
delta_ofdm->plcp_err, max_ofdm->plcp_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "crc32_err:",
|
||||
le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
|
||||
delta_ofdm->crc32_err, max_ofdm->crc32_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "overrun_err:",
|
||||
le32_to_cpu(ofdm->overrun_err),
|
||||
accum_ofdm->overrun_err, delta_ofdm->overrun_err,
|
||||
max_ofdm->overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"early_overrun_err:",
|
||||
le32_to_cpu(ofdm->early_overrun_err),
|
||||
accum_ofdm->early_overrun_err,
|
||||
delta_ofdm->early_overrun_err,
|
||||
max_ofdm->early_overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"crc32_good:", le32_to_cpu(ofdm->crc32_good),
|
||||
accum_ofdm->crc32_good, delta_ofdm->crc32_good,
|
||||
max_ofdm->crc32_good);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n", "false_alarm_cnt:",
|
||||
le32_to_cpu(ofdm->false_alarm_cnt),
|
||||
accum_ofdm->false_alarm_cnt,
|
||||
delta_ofdm->false_alarm_cnt,
|
||||
max_ofdm->false_alarm_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"fina_sync_err_cnt:",
|
||||
le32_to_cpu(ofdm->fina_sync_err_cnt),
|
||||
accum_ofdm->fina_sync_err_cnt,
|
||||
delta_ofdm->fina_sync_err_cnt,
|
||||
max_ofdm->fina_sync_err_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sfd_timeout:",
|
||||
le32_to_cpu(ofdm->sfd_timeout),
|
||||
accum_ofdm->sfd_timeout,
|
||||
delta_ofdm->sfd_timeout,
|
||||
max_ofdm->sfd_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"fina_timeout:",
|
||||
le32_to_cpu(ofdm->fina_timeout),
|
||||
accum_ofdm->fina_timeout,
|
||||
delta_ofdm->fina_timeout,
|
||||
max_ofdm->fina_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"unresponded_rts:",
|
||||
le32_to_cpu(ofdm->unresponded_rts),
|
||||
accum_ofdm->unresponded_rts,
|
||||
delta_ofdm->unresponded_rts,
|
||||
max_ofdm->unresponded_rts);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"rxe_frame_lmt_ovrun:",
|
||||
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
|
||||
accum_ofdm->rxe_frame_limit_overrun,
|
||||
delta_ofdm->rxe_frame_limit_overrun,
|
||||
max_ofdm->rxe_frame_limit_overrun);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sent_ack_cnt:",
|
||||
le32_to_cpu(ofdm->sent_ack_cnt),
|
||||
accum_ofdm->sent_ack_cnt,
|
||||
delta_ofdm->sent_ack_cnt,
|
||||
max_ofdm->sent_ack_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sent_cts_cnt:",
|
||||
le32_to_cpu(ofdm->sent_cts_cnt),
|
||||
accum_ofdm->sent_cts_cnt,
|
||||
delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - CCK:");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"ina_cnt:",
|
||||
le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
|
||||
delta_cck->ina_cnt, max_cck->ina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"fina_cnt:",
|
||||
le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
|
||||
delta_cck->fina_cnt, max_cck->fina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"plcp_err:",
|
||||
le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
|
||||
delta_cck->plcp_err, max_cck->plcp_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"crc32_err:",
|
||||
le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
|
||||
delta_cck->crc32_err, max_cck->crc32_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"overrun_err:",
|
||||
le32_to_cpu(cck->overrun_err),
|
||||
accum_cck->overrun_err,
|
||||
delta_cck->overrun_err, max_cck->overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"early_overrun_err:",
|
||||
le32_to_cpu(cck->early_overrun_err),
|
||||
accum_cck->early_overrun_err,
|
||||
delta_cck->early_overrun_err,
|
||||
max_cck->early_overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"crc32_good:",
|
||||
le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
|
||||
delta_cck->crc32_good,
|
||||
max_cck->crc32_good);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"false_alarm_cnt:",
|
||||
le32_to_cpu(cck->false_alarm_cnt),
|
||||
accum_cck->false_alarm_cnt,
|
||||
delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"fina_sync_err_cnt:",
|
||||
le32_to_cpu(cck->fina_sync_err_cnt),
|
||||
accum_cck->fina_sync_err_cnt,
|
||||
delta_cck->fina_sync_err_cnt,
|
||||
max_cck->fina_sync_err_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sfd_timeout:",
|
||||
le32_to_cpu(cck->sfd_timeout),
|
||||
accum_cck->sfd_timeout,
|
||||
delta_cck->sfd_timeout, max_cck->sfd_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"fina_timeout:",
|
||||
le32_to_cpu(cck->fina_timeout),
|
||||
accum_cck->fina_timeout,
|
||||
delta_cck->fina_timeout, max_cck->fina_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"unresponded_rts:",
|
||||
le32_to_cpu(cck->unresponded_rts),
|
||||
accum_cck->unresponded_rts,
|
||||
delta_cck->unresponded_rts,
|
||||
max_cck->unresponded_rts);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"rxe_frame_lmt_ovrun:",
|
||||
le32_to_cpu(cck->rxe_frame_limit_overrun),
|
||||
accum_cck->rxe_frame_limit_overrun,
|
||||
delta_cck->rxe_frame_limit_overrun,
|
||||
max_cck->rxe_frame_limit_overrun);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sent_ack_cnt:",
|
||||
le32_to_cpu(cck->sent_ack_cnt),
|
||||
accum_cck->sent_ack_cnt,
|
||||
delta_cck->sent_ack_cnt,
|
||||
max_cck->sent_ack_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sent_cts_cnt:",
|
||||
le32_to_cpu(cck->sent_cts_cnt),
|
||||
accum_cck->sent_cts_cnt,
|
||||
delta_cck->sent_cts_cnt,
|
||||
max_cck->sent_cts_cnt);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Rx - GENERAL:");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"bogus_cts:",
|
||||
le32_to_cpu(general->bogus_cts),
|
||||
accum_general->bogus_cts,
|
||||
delta_general->bogus_cts, max_general->bogus_cts);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"bogus_ack:",
|
||||
le32_to_cpu(general->bogus_ack),
|
||||
accum_general->bogus_ack,
|
||||
delta_general->bogus_ack, max_general->bogus_ack);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"non_bssid_frames:",
|
||||
le32_to_cpu(general->non_bssid_frames),
|
||||
accum_general->non_bssid_frames,
|
||||
delta_general->non_bssid_frames,
|
||||
max_general->non_bssid_frames);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"filtered_frames:",
|
||||
le32_to_cpu(general->filtered_frames),
|
||||
accum_general->filtered_frames,
|
||||
delta_general->filtered_frames,
|
||||
max_general->filtered_frames);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"non_channel_beacons:",
|
||||
le32_to_cpu(general->non_channel_beacons),
|
||||
accum_general->non_channel_beacons,
|
||||
delta_general->non_channel_beacons,
|
||||
max_general->non_channel_beacons);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
|
||||
ssize_t ret;
|
||||
struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IWL_ERR(priv, "Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The statistic information display here is based on
|
||||
* the last statistics notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
tx = &priv->_3945.statistics.tx;
|
||||
accum_tx = &priv->_3945.accum_statistics.tx;
|
||||
delta_tx = &priv->_3945.delta_statistics.tx;
|
||||
max_tx = &priv->_3945.max_delta.tx;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_Tx:");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"preamble:",
|
||||
le32_to_cpu(tx->preamble_cnt),
|
||||
accum_tx->preamble_cnt,
|
||||
delta_tx->preamble_cnt, max_tx->preamble_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"rx_detected_cnt:",
|
||||
le32_to_cpu(tx->rx_detected_cnt),
|
||||
accum_tx->rx_detected_cnt,
|
||||
delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"bt_prio_defer_cnt:",
|
||||
le32_to_cpu(tx->bt_prio_defer_cnt),
|
||||
accum_tx->bt_prio_defer_cnt,
|
||||
delta_tx->bt_prio_defer_cnt,
|
||||
max_tx->bt_prio_defer_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"bt_prio_kill_cnt:",
|
||||
le32_to_cpu(tx->bt_prio_kill_cnt),
|
||||
accum_tx->bt_prio_kill_cnt,
|
||||
delta_tx->bt_prio_kill_cnt,
|
||||
max_tx->bt_prio_kill_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"few_bytes_cnt:",
|
||||
le32_to_cpu(tx->few_bytes_cnt),
|
||||
accum_tx->few_bytes_cnt,
|
||||
delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"cts_timeout:",
|
||||
le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
|
||||
delta_tx->cts_timeout, max_tx->cts_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"ack_timeout:",
|
||||
le32_to_cpu(tx->ack_timeout),
|
||||
accum_tx->ack_timeout,
|
||||
delta_tx->ack_timeout, max_tx->ack_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"expected_ack_cnt:",
|
||||
le32_to_cpu(tx->expected_ack_cnt),
|
||||
accum_tx->expected_ack_cnt,
|
||||
delta_tx->expected_ack_cnt,
|
||||
max_tx->expected_ack_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"actual_ack_cnt:",
|
||||
le32_to_cpu(tx->actual_ack_cnt),
|
||||
accum_tx->actual_ack_cnt,
|
||||
delta_tx->actual_ack_cnt,
|
||||
max_tx->actual_ack_cnt);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t iwl3945_ucode_general_stats_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int pos = 0;
|
||||
char *buf;
|
||||
int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
|
||||
ssize_t ret;
|
||||
struct iwl39_statistics_general *general, *accum_general;
|
||||
struct iwl39_statistics_general *delta_general, *max_general;
|
||||
struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
|
||||
struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IWL_ERR(priv, "Can not allocate Buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* The statistic information display here is based on
|
||||
* the last statistics notification from uCode
|
||||
* might not reflect the current uCode activity
|
||||
*/
|
||||
general = &priv->_3945.statistics.general;
|
||||
dbg = &priv->_3945.statistics.general.dbg;
|
||||
div = &priv->_3945.statistics.general.div;
|
||||
accum_general = &priv->_3945.accum_statistics.general;
|
||||
delta_general = &priv->_3945.delta_statistics.general;
|
||||
max_general = &priv->_3945.max_delta.general;
|
||||
accum_dbg = &priv->_3945.accum_statistics.general.dbg;
|
||||
delta_dbg = &priv->_3945.delta_statistics.general.dbg;
|
||||
max_dbg = &priv->_3945.max_delta.general.dbg;
|
||||
accum_div = &priv->_3945.accum_statistics.general.div;
|
||||
delta_div = &priv->_3945.delta_statistics.general.div;
|
||||
max_div = &priv->_3945.max_delta.general.div;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%-32s current"
|
||||
"acumulative delta max\n",
|
||||
"Statistics_General:");
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"burst_check:",
|
||||
le32_to_cpu(dbg->burst_check),
|
||||
accum_dbg->burst_check,
|
||||
delta_dbg->burst_check, max_dbg->burst_check);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"burst_count:",
|
||||
le32_to_cpu(dbg->burst_count),
|
||||
accum_dbg->burst_count,
|
||||
delta_dbg->burst_count, max_dbg->burst_count);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"sleep_time:",
|
||||
le32_to_cpu(general->sleep_time),
|
||||
accum_general->sleep_time,
|
||||
delta_general->sleep_time, max_general->sleep_time);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"slots_out:",
|
||||
le32_to_cpu(general->slots_out),
|
||||
accum_general->slots_out,
|
||||
delta_general->slots_out, max_general->slots_out);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"slots_idle:",
|
||||
le32_to_cpu(general->slots_idle),
|
||||
accum_general->slots_idle,
|
||||
delta_general->slots_idle, max_general->slots_idle);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
|
||||
le32_to_cpu(general->ttl_timestamp));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"tx_on_a:",
|
||||
le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
|
||||
delta_div->tx_on_a, max_div->tx_on_a);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"tx_on_b:",
|
||||
le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
|
||||
delta_div->tx_on_b, max_div->tx_on_b);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"exec_time:",
|
||||
le32_to_cpu(div->exec_time), accum_div->exec_time,
|
||||
delta_div->exec_time, max_div->exec_time);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
" %-30s %10u %10u %10u %10u\n",
|
||||
"probe_time:",
|
||||
le32_to_cpu(div->probe_time), accum_div->probe_time,
|
||||
delta_div->probe_time, max_div->probe_time);
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
60
drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h
Normal file
60
drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h
Normal file
@ -0,0 +1,60 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-debug.h"
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos);
|
||||
ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos);
|
||||
ssize_t iwl3945_ucode_general_stats_read(struct file *file,
|
||||
char __user *user_buf, size_t count,
|
||||
loff_t *ppos);
|
||||
#else
|
||||
static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
|
||||
char __user *user_buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
|
||||
char __user *user_buf, size_t count,
|
||||
loff_t *ppos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
@ -50,6 +50,7 @@
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-led.h"
|
||||
#include "iwl-3945-led.h"
|
||||
#include "iwl-3945-debugfs.h"
|
||||
|
||||
#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \
|
||||
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
|
||||
@ -293,7 +294,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
|
||||
* iwl3945_rx_reply_tx - Handle Tx response
|
||||
*/
|
||||
static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
@ -351,18 +352,81 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
||||
* RX handler implementations
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
/*
|
||||
* based on the assumption of all statistics counter are in DWORD
|
||||
* FIXME: This function is for debugging, do not deal with
|
||||
* the case of counters roll-over.
|
||||
*/
|
||||
static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
|
||||
__le32 *stats)
|
||||
{
|
||||
int i;
|
||||
__le32 *prev_stats;
|
||||
u32 *accum_stats;
|
||||
u32 *delta, *max_delta;
|
||||
|
||||
prev_stats = (__le32 *)&priv->_3945.statistics;
|
||||
accum_stats = (u32 *)&priv->_3945.accum_statistics;
|
||||
delta = (u32 *)&priv->_3945.delta_statistics;
|
||||
max_delta = (u32 *)&priv->_3945.max_delta;
|
||||
|
||||
for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics);
|
||||
i += sizeof(__le32), stats++, prev_stats++, delta++,
|
||||
max_delta++, accum_stats++) {
|
||||
if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
|
||||
*delta = (le32_to_cpu(*stats) -
|
||||
le32_to_cpu(*prev_stats));
|
||||
*accum_stats += *delta;
|
||||
if (*delta > *max_delta)
|
||||
*max_delta = *delta;
|
||||
}
|
||||
}
|
||||
|
||||
/* reset accumulative statistics for "no-counter" type statistics */
|
||||
priv->_3945.accum_statistics.general.temperature =
|
||||
priv->_3945.statistics.general.temperature;
|
||||
priv->_3945.accum_statistics.general.ttl_timestamp =
|
||||
priv->_3945.statistics.general.ttl_timestamp;
|
||||
}
|
||||
#endif
|
||||
|
||||
void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
||||
(int)sizeof(struct iwl3945_notif_statistics),
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
|
||||
#endif
|
||||
|
||||
memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
|
||||
}
|
||||
|
||||
void iwl3945_reply_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
__le32 *flag = (__le32 *)&pkt->u.raw;
|
||||
|
||||
if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
memset(&priv->_3945.accum_statistics, 0,
|
||||
sizeof(struct iwl3945_notif_statistics));
|
||||
memset(&priv->_3945.delta_statistics, 0,
|
||||
sizeof(struct iwl3945_notif_statistics));
|
||||
memset(&priv->_3945.max_delta, 0,
|
||||
sizeof(struct iwl3945_notif_statistics));
|
||||
#endif
|
||||
IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
|
||||
}
|
||||
iwl3945_hw_rx_statistics(priv, rxb);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Misc. internal state and helper functions
|
||||
@ -2736,6 +2800,12 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
.isr = iwl_isr_legacy,
|
||||
.config_ap = iwl3945_config_ap,
|
||||
.add_bcast_station = iwl3945_add_bcast_station,
|
||||
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl3945_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl3945_ucode_tx_stats_read,
|
||||
.general_stats_read = iwl3945_ucode_general_stats_read,
|
||||
},
|
||||
};
|
||||
|
||||
static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
|
||||
|
@ -264,6 +264,8 @@ extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
|
||||
extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
|
||||
extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl3945_reply_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
extern void iwl3945_disable_events(struct iwl_priv *priv);
|
||||
extern int iwl4965_get_temperature(const struct iwl_priv *priv);
|
||||
extern void iwl3945_post_associate(struct iwl_priv *priv);
|
||||
|
@ -200,26 +200,57 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
|
||||
case CSR_HW_REV_TYPE_5150:
|
||||
priv->hw_params.sens = &iwl5150_sensitivity;
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_DC) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
priv->hw_params.sens = &iwl5000_sensitivity;
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_TX_IQ_PERD) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
break;
|
||||
default:
|
||||
priv->hw_params.sens = &iwl5000_sensitivity;
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_TX_IQ_PERD) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
priv->cfg->num_of_queues =
|
||||
priv->cfg->mod_params->num_of_queues;
|
||||
|
||||
priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
|
||||
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
|
||||
priv->hw_params.scd_bc_tbls_size =
|
||||
priv->cfg->num_of_queues *
|
||||
sizeof(struct iwlagn_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
|
||||
|
||||
priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
|
||||
|
||||
priv->hw_params.max_bsm_size = 0;
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
|
||||
|
||||
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
||||
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
priv->hw_params.sens = &iwl5150_sensitivity;
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_DC) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -332,7 +363,7 @@ static struct iwl_lib_ops iwl5000_lib = {
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl5150_lib = {
|
||||
.set_hw_params = iwl5000_hw_set_hw_params,
|
||||
.set_hw_params = iwl5150_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
|
||||
.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
|
||||
.txq_set_sched = iwlagn_txq_set_sched,
|
||||
|
@ -176,24 +176,56 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
priv->hw_params.sens = &iwl6000_sensitivity;
|
||||
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
|
||||
case CSR_HW_REV_TYPE_6x50:
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_DC) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
break;
|
||||
default:
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl6050_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
|
||||
priv->cfg->num_of_queues =
|
||||
priv->cfg->mod_params->num_of_queues;
|
||||
|
||||
priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
|
||||
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
|
||||
priv->hw_params.scd_bc_tbls_size =
|
||||
priv->cfg->num_of_queues *
|
||||
sizeof(struct iwlagn_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
|
||||
|
||||
priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
|
||||
priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
|
||||
|
||||
priv->hw_params.max_bsm_size = 0;
|
||||
priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
|
||||
BIT(IEEE80211_BAND_5GHZ);
|
||||
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
|
||||
|
||||
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
||||
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
|
||||
/* Set initial sensitivity parameters */
|
||||
/* Set initial calibration set */
|
||||
priv->hw_params.sens = &iwl6000_sensitivity;
|
||||
priv->hw_params.calib_init_cfg =
|
||||
BIT(IWL_CALIB_XTAL) |
|
||||
BIT(IWL_CALIB_DC) |
|
||||
BIT(IWL_CALIB_LO) |
|
||||
BIT(IWL_CALIB_TX_IQ) |
|
||||
BIT(IWL_CALIB_BASE_BAND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -304,7 +336,7 @@ static const struct iwl_ops iwl6000_ops = {
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl6050_lib = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.set_hw_params = iwl6050_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
|
||||
.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
|
||||
.txq_set_sched = iwlagn_txq_set_sched,
|
||||
@ -468,7 +500,6 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
@ -501,7 +532,6 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
@ -568,7 +598,6 @@ struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
|
@ -1395,16 +1395,29 @@ void iwlagn_request_scan(struct iwl_priv *priv)
|
||||
rate = IWL_RATE_1M_PLCP;
|
||||
rate_flags = RATE_MCS_CCK_MSK;
|
||||
}
|
||||
scan->good_CRC_th = 0;
|
||||
scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;
|
||||
break;
|
||||
case IEEE80211_BAND_5GHZ:
|
||||
rate = IWL_RATE_6M_PLCP;
|
||||
/*
|
||||
* If active scaning is requested but a certain channel
|
||||
* is marked passive, we can do active scanning if we
|
||||
* detect transmissions.
|
||||
* If active scanning is requested but a certain channel is
|
||||
* marked passive, we can do active scanning if we detect
|
||||
* transmissions.
|
||||
*
|
||||
* There is an issue with some firmware versions that triggers
|
||||
* a sysassert on a "good CRC threshold" of zero (== disabled),
|
||||
* on a radar channel even though this means that we should NOT
|
||||
* send probes.
|
||||
*
|
||||
* The "good CRC threshold" is the number of frames that we
|
||||
* need to receive during our dwell time on a channel before
|
||||
* sending out probes -- setting this to a huge value will
|
||||
* mean we never reach it, but at the same time work around
|
||||
* the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
|
||||
* here instead of IWL_GOOD_CRC_TH_DISABLED.
|
||||
*/
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_NEVER;
|
||||
break;
|
||||
default:
|
||||
IWL_WARN(priv, "Invalid scan band count\n");
|
||||
|
@ -868,14 +868,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
|
||||
rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
|
||||
&rs_index);
|
||||
rs_collect_tx_data(curr_tbl, rs_index,
|
||||
info->status.ampdu_ack_len,
|
||||
info->status.ampdu_ack_map);
|
||||
info->status.ampdu_len,
|
||||
info->status.ampdu_ack_len);
|
||||
|
||||
/* Update success/fail counts if not searching for new mode */
|
||||
if (lq_sta->stay_in_tbl) {
|
||||
lq_sta->total_success += info->status.ampdu_ack_map;
|
||||
lq_sta->total_failed += (info->status.ampdu_ack_len -
|
||||
info->status.ampdu_ack_map);
|
||||
lq_sta->total_success += info->status.ampdu_ack_len;
|
||||
lq_sta->total_failed += (info->status.ampdu_len -
|
||||
info->status.ampdu_ack_len);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
@ -2078,10 +2078,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
}
|
||||
/* Else we have enough samples; calculate estimate of
|
||||
* actual average throughput */
|
||||
|
||||
/* Sanity-check TPT calculations */
|
||||
BUG_ON(window->average_tpt != ((window->success_ratio *
|
||||
tbl->expected_tpt[index] + 64) / 128));
|
||||
if (window->average_tpt != ((window->success_ratio *
|
||||
tbl->expected_tpt[index] + 64) / 128)) {
|
||||
IWL_ERR(priv, "expected_tpt should have been calculated by now\n");
|
||||
window->average_tpt = ((window->success_ratio *
|
||||
tbl->expected_tpt[index] + 64) / 128);
|
||||
}
|
||||
|
||||
/* If we are searching for better modulation mode, check success. */
|
||||
if (lq_sta->search_better_tbl &&
|
||||
|
@ -83,6 +83,15 @@ static inline int get_fifo_from_ac(u8 ac)
|
||||
return ac_to_fifo[ac];
|
||||
}
|
||||
|
||||
static inline int get_ac_from_tid(u16 tid)
|
||||
{
|
||||
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
|
||||
return tid_to_ac[tid];
|
||||
|
||||
/* no support for TIDs 8-15 yet */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int get_fifo_from_tid(u16 tid)
|
||||
{
|
||||
if (likely(tid < ARRAY_SIZE(tid_to_ac)))
|
||||
@ -991,7 +1000,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
|
||||
tid_data = &priv->stations[sta_id].tid[tid];
|
||||
*ssn = SEQ_TO_SN(tid_data->seq_number);
|
||||
tid_data->agg.txq_id = txq_id;
|
||||
priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id);
|
||||
priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id);
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo,
|
||||
@ -1224,8 +1233,9 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
info->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
info->status.ampdu_ack_map = successes;
|
||||
info->status.ampdu_ack_len = agg->frame_count;
|
||||
info->status.ampdu_ack_len = successes;
|
||||
info->status.ampdu_ack_map = bitmap;
|
||||
info->status.ampdu_len = agg->frame_count;
|
||||
iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);
|
||||
|
@ -2654,7 +2654,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_SPECTRUM_MGMT;
|
||||
|
||||
@ -3002,18 +3001,6 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_mac_get_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_low_level_stats *stats)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
priv = hw->priv;
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
@ -3391,7 +3378,6 @@ static struct ieee80211_ops iwl_hw_ops = {
|
||||
.configure_filter = iwl_configure_filter,
|
||||
.set_key = iwl_mac_set_key,
|
||||
.update_tkip_key = iwl_mac_update_tkip_key,
|
||||
.get_stats = iwl_mac_get_stats,
|
||||
.conf_tx = iwl_mac_conf_tx,
|
||||
.reset_tsf = iwl_mac_reset_tsf,
|
||||
.bss_info_changed = iwl_bss_info_changed,
|
||||
|
@ -2663,7 +2663,9 @@ struct iwl_ssid_ie {
|
||||
#define PROBE_OPTION_MAX_3945 4
|
||||
#define PROBE_OPTION_MAX 20
|
||||
#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF)
|
||||
#define IWL_GOOD_CRC_TH cpu_to_le16(1)
|
||||
#define IWL_GOOD_CRC_TH_DISABLED 0
|
||||
#define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1)
|
||||
#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff)
|
||||
#define IWL_MAX_SCAN_SIZE 1024
|
||||
#define IWL_MAX_CMD_SIZE 4096
|
||||
#define IWL_MAX_PROBE_REQUEST 200
|
||||
|
@ -2117,10 +2117,6 @@ EXPORT_SYMBOL(iwl_mac_remove_interface);
|
||||
|
||||
/**
|
||||
* iwl_mac_config - mac80211 config callback
|
||||
*
|
||||
* We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
|
||||
* be set inappropriately and the driver currently sets the hardware up to
|
||||
* use it whenever needed.
|
||||
*/
|
||||
int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
@ -2935,6 +2931,12 @@ int iwl_pci_resume(struct pci_dev *pdev)
|
||||
struct iwl_priv *priv = pci_get_drvdata(pdev);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* We disable the RETRY_TIMEOUT register (0x41) to keep
|
||||
* PCI Tx retries from interfering with C3 CPU state.
|
||||
*/
|
||||
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret)
|
||||
|
@ -512,7 +512,9 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
|
||||
void iwl_init_scan_params(struct iwl_priv *priv);
|
||||
int iwl_scan_cancel(struct iwl_priv *priv);
|
||||
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
||||
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
|
||||
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req);
|
||||
void iwl_internal_short_hw_scan(struct iwl_priv *priv);
|
||||
int iwl_force_reset(struct iwl_priv *priv, int mode);
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
|
@ -1059,10 +1059,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
if (priv->cfg->ops->lib->debugfs_ops.rx_stats_read)
|
||||
return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
|
||||
user_buf, count, ppos);
|
||||
return 0;
|
||||
return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
|
||||
user_buf, count, ppos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
||||
@ -1070,10 +1068,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
if (priv->cfg->ops->lib->debugfs_ops.tx_stats_read)
|
||||
return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
|
||||
user_buf, count, ppos);
|
||||
return 0;
|
||||
return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
|
||||
user_buf, count, ppos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
|
||||
@ -1081,10 +1077,8 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
if (priv->cfg->ops->lib->debugfs_ops.general_stats_read)
|
||||
return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
|
||||
user_buf, count, ppos);
|
||||
return 0;
|
||||
return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
|
||||
user_buf, count, ppos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
|
||||
|
@ -1202,6 +1202,11 @@ struct iwl_priv {
|
||||
struct delayed_work rfkill_poll;
|
||||
|
||||
struct iwl3945_notif_statistics statistics;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl3945_notif_statistics accum_statistics;
|
||||
struct iwl3945_notif_statistics delta_statistics;
|
||||
struct iwl3945_notif_statistics max_delta;
|
||||
#endif
|
||||
|
||||
u32 sta_supp_rates;
|
||||
int last_rx_rssi; /* From Rx packet statistics */
|
||||
|
@ -313,7 +313,8 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct cfg80211_scan_request *req)
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
int ret;
|
||||
|
@ -957,7 +957,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
|
||||
* statistics request from the host as well as for the periodic
|
||||
* statistics notifications (after received beacons) from the uCode.
|
||||
*/
|
||||
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
|
||||
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
|
||||
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
|
||||
|
||||
iwl_setup_rx_scan_handlers(priv);
|
||||
@ -2939,7 +2939,8 @@ void iwl3945_request_scan(struct iwl_priv *priv)
|
||||
* is marked passive, we can do active scanning if we
|
||||
* detect transmissions.
|
||||
*/
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
|
||||
scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
|
||||
IWL_GOOD_CRC_TH_DISABLED;
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
break;
|
||||
default:
|
||||
@ -3873,7 +3874,6 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM |
|
||||
IEEE80211_HW_SPECTRUM_MGMT;
|
||||
|
||||
if (!priv->cfg->broken_powersave)
|
||||
|
@ -31,7 +31,7 @@ struct iwm_if_ops {
|
||||
int (*disable)(struct iwm_priv *iwm);
|
||||
int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
|
||||
|
||||
int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
|
||||
void (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
|
||||
void (*debugfs_exit)(struct iwm_priv *iwm);
|
||||
|
||||
const char *umac_name;
|
||||
|
@ -113,13 +113,10 @@ struct iwm_debugfs {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IWM_DEBUG
|
||||
int iwm_debugfs_init(struct iwm_priv *iwm);
|
||||
void iwm_debugfs_init(struct iwm_priv *iwm);
|
||||
void iwm_debugfs_exit(struct iwm_priv *iwm);
|
||||
#else
|
||||
static inline int iwm_debugfs_init(struct iwm_priv *iwm)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void iwm_debugfs_init(struct iwm_priv *iwm) {}
|
||||
static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
|
||||
#endif
|
||||
|
||||
|
@ -48,12 +48,11 @@ static struct {
|
||||
|
||||
#define add_dbg_module(dbg, name, id, initlevel) \
|
||||
do { \
|
||||
struct dentry *d; \
|
||||
dbg.dbg_module[id] = (initlevel); \
|
||||
d = debugfs_create_x8(name, 0600, dbg.dbgdir, \
|
||||
&(dbg.dbg_module[id])); \
|
||||
if (!IS_ERR(d)) \
|
||||
dbg.dbg_module_dentries[id] = d; \
|
||||
dbg.dbg_module_dentries[id] = \
|
||||
debugfs_create_x8(name, 0600, \
|
||||
dbg.dbgdir, \
|
||||
&(dbg.dbg_module[id])); \
|
||||
} while (0)
|
||||
|
||||
static int iwm_debugfs_u32_read(void *data, u64 *val)
|
||||
@ -423,89 +422,29 @@ static const struct file_operations iwm_debugfs_fw_err_fops = {
|
||||
.read = iwm_debugfs_fw_err_read,
|
||||
};
|
||||
|
||||
int iwm_debugfs_init(struct iwm_priv *iwm)
|
||||
void iwm_debugfs_init(struct iwm_priv *iwm)
|
||||
{
|
||||
int i, result;
|
||||
char devdir[16];
|
||||
int i;
|
||||
|
||||
iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
|
||||
result = PTR_ERR(iwm->dbg.rootdir);
|
||||
if (!result || IS_ERR(iwm->dbg.rootdir)) {
|
||||
if (result == -ENODEV) {
|
||||
IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not "
|
||||
"enabled in kernel config\n");
|
||||
result = 0; /* No debugfs support */
|
||||
}
|
||||
IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm)));
|
||||
|
||||
iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir);
|
||||
result = PTR_ERR(iwm->dbg.devdir);
|
||||
if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create devdir: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.devdir = debugfs_create_dir(wiphy_name(iwm_to_wiphy(iwm)),
|
||||
iwm->dbg.rootdir);
|
||||
iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir);
|
||||
result = PTR_ERR(iwm->dbg.dbgdir);
|
||||
if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir);
|
||||
result = PTR_ERR(iwm->dbg.rxdir);
|
||||
if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir);
|
||||
result = PTR_ERR(iwm->dbg.txdir);
|
||||
if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir);
|
||||
result = PTR_ERR(iwm->dbg.busdir);
|
||||
if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (iwm->bus_ops->debugfs_init) {
|
||||
result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
|
||||
if (result < 0) {
|
||||
IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (iwm->bus_ops->debugfs_init)
|
||||
iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
|
||||
|
||||
iwm->dbg.dbg_level = IWM_DL_NONE;
|
||||
iwm->dbg.dbg_level_dentry =
|
||||
debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,
|
||||
&fops_iwm_dbg_level);
|
||||
result = PTR_ERR(iwm->dbg.dbg_level_dentry);
|
||||
if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
iwm->dbg.dbg_modules = IWM_DM_DEFAULT;
|
||||
iwm->dbg.dbg_modules_dentry =
|
||||
debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,
|
||||
&fops_iwm_dbg_modules);
|
||||
result = PTR_ERR(iwm->dbg.dbg_modules_dentry);
|
||||
if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i < __IWM_DM_NR; i++)
|
||||
add_dbg_module(iwm->dbg, iwm_debug_module[i].name,
|
||||
@ -514,44 +453,15 @@ int iwm_debugfs_init(struct iwm_priv *iwm)
|
||||
iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,
|
||||
iwm->dbg.txdir, iwm,
|
||||
&iwm_debugfs_txq_fops);
|
||||
result = PTR_ERR(iwm->dbg.txq_dentry);
|
||||
if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,
|
||||
iwm->dbg.txdir, iwm,
|
||||
&iwm_debugfs_tx_credit_fops);
|
||||
result = PTR_ERR(iwm->dbg.tx_credit_dentry);
|
||||
if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,
|
||||
iwm->dbg.rxdir, iwm,
|
||||
&iwm_debugfs_rx_ticket_fops);
|
||||
result = PTR_ERR(iwm->dbg.rx_ticket_dentry);
|
||||
if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,
|
||||
iwm->dbg.dbgdir, iwm,
|
||||
&iwm_debugfs_fw_err_fops);
|
||||
result = PTR_ERR(iwm->dbg.fw_err_dentry);
|
||||
if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
|
||||
void iwm_debugfs_exit(struct iwm_priv *iwm)
|
||||
|
@ -366,21 +366,13 @@ static const struct file_operations iwm_debugfs_sdio_fops = {
|
||||
.read = iwm_debugfs_sdio_read,
|
||||
};
|
||||
|
||||
static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
|
||||
static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
|
||||
{
|
||||
int result;
|
||||
struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
|
||||
|
||||
hw->cccr_dentry = debugfs_create_file("cccr", 0200,
|
||||
parent_dir, iwm,
|
||||
&iwm_debugfs_sdio_fops);
|
||||
result = PTR_ERR(hw->cccr_dentry);
|
||||
if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) {
|
||||
IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void if_sdio_debugfs_exit(struct iwm_priv *iwm)
|
||||
@ -440,11 +432,7 @@ static int iwm_sdio_probe(struct sdio_func *func,
|
||||
hw = iwm_private(iwm);
|
||||
hw->iwm = iwm;
|
||||
|
||||
ret = iwm_debugfs_init(iwm);
|
||||
if (ret < 0) {
|
||||
IWM_ERR(iwm, "Debugfs registration failed\n");
|
||||
goto if_free;
|
||||
}
|
||||
iwm_debugfs_init(iwm);
|
||||
|
||||
sdio_set_drvdata(func, hw);
|
||||
|
||||
@ -473,7 +461,6 @@ static int iwm_sdio_probe(struct sdio_func *func,
|
||||
destroy_workqueue(hw->isr_wq);
|
||||
debugfs_exit:
|
||||
iwm_debugfs_exit(iwm);
|
||||
if_free:
|
||||
iwm_if_free(iwm);
|
||||
return ret;
|
||||
}
|
||||
|
@ -324,7 +324,9 @@ static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition)
|
||||
timeout = jiffies + HZ;
|
||||
while (1) {
|
||||
status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
|
||||
if (ret || (status & condition))
|
||||
if (ret)
|
||||
return ret;
|
||||
if ((status & condition) == condition)
|
||||
break;
|
||||
if (time_after(jiffies, timeout))
|
||||
return -ETIMEDOUT;
|
||||
|
@ -7,6 +7,8 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "libertas_tf.h"
|
||||
@ -82,6 +84,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
|
||||
int ret = -1;
|
||||
u32 i;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
|
||||
@ -104,6 +108,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
|
||||
priv->fwrelease >> 8 & 0xff,
|
||||
priv->fwrelease & 0xff,
|
||||
priv->fwcapinfo);
|
||||
lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
|
||||
cmd.hwifversion, cmd.version);
|
||||
|
||||
/* Clamp region code to 8-bit since FW spec indicates that it should
|
||||
* only ever be 8-bit, even though the field size is 16-bit. Some
|
||||
@ -118,8 +124,10 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
|
||||
}
|
||||
|
||||
/* if it's unidentified region code, use the default (USA) */
|
||||
if (i >= MRVDRV_MAX_REGION_CODE)
|
||||
if (i >= MRVDRV_MAX_REGION_CODE) {
|
||||
priv->regioncode = 0x10;
|
||||
pr_info("unidentified region code; using the default (USA)\n");
|
||||
}
|
||||
|
||||
if (priv->current_addr[0] == 0xff)
|
||||
memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
|
||||
@ -128,6 +136,7 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
|
||||
|
||||
lbtf_geo_init(priv);
|
||||
out:
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -141,13 +150,18 @@ out:
|
||||
*/
|
||||
int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
|
||||
{
|
||||
int ret = 0;
|
||||
struct cmd_ds_802_11_rf_channel cmd;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
|
||||
return lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
|
||||
ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
|
||||
lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
|
||||
@ -155,20 +169,28 @@ int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
|
||||
struct cmd_ds_802_11_beacon_set cmd;
|
||||
int size;
|
||||
|
||||
if (beacon->len > MRVL_MAX_BCN_SIZE)
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
if (beacon->len > MRVL_MAX_BCN_SIZE) {
|
||||
lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1);
|
||||
return -1;
|
||||
}
|
||||
size = sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
|
||||
cmd.hdr.size = cpu_to_le16(size);
|
||||
cmd.len = cpu_to_le16(beacon->len);
|
||||
memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
|
||||
|
||||
lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
|
||||
|
||||
lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
|
||||
int beacon_int) {
|
||||
int beacon_int)
|
||||
{
|
||||
struct cmd_ds_802_11_beacon_control cmd;
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET);
|
||||
@ -176,6 +198,8 @@ int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
|
||||
cmd.beacon_period = cpu_to_le16(beacon_int);
|
||||
|
||||
lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -183,17 +207,28 @@ static void lbtf_queue_cmd(struct lbtf_private *priv,
|
||||
struct cmd_ctrl_node *cmdnode)
|
||||
{
|
||||
unsigned long flags;
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
if (!cmdnode)
|
||||
return;
|
||||
if (!cmdnode) {
|
||||
lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n");
|
||||
goto qcmd_done;
|
||||
}
|
||||
|
||||
if (!cmdnode->cmdbuf->size)
|
||||
return;
|
||||
if (!cmdnode->cmdbuf->size) {
|
||||
lbtf_deb_host("DNLD_CMD: cmd size is zero\n");
|
||||
goto qcmd_done;
|
||||
}
|
||||
|
||||
cmdnode->result = 0;
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
list_add_tail(&cmdnode->list, &priv->cmdpendingq);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
|
||||
le16_to_cpu(cmdnode->cmdbuf->command));
|
||||
|
||||
qcmd_done:
|
||||
lbtf_deb_leave(LBTF_DEB_HOST);
|
||||
}
|
||||
|
||||
static void lbtf_submit_command(struct lbtf_private *priv,
|
||||
@ -206,22 +241,33 @@ static void lbtf_submit_command(struct lbtf_private *priv,
|
||||
int timeo = 5 * HZ;
|
||||
int ret;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
cmd = cmdnode->cmdbuf;
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
priv->cur_cmd = cmdnode;
|
||||
cmdsize = le16_to_cpu(cmd->size);
|
||||
command = le16_to_cpu(cmd->command);
|
||||
|
||||
lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
|
||||
command, le16_to_cpu(cmd->seqnum), cmdsize);
|
||||
lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
|
||||
|
||||
ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
if (ret)
|
||||
if (ret) {
|
||||
pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
|
||||
/* Let the timer kick in and retry, and potentially reset
|
||||
the whole thing if the condition persists */
|
||||
timeo = HZ;
|
||||
}
|
||||
|
||||
/* Setup the timer after transmit command */
|
||||
mod_timer(&priv->command_timer, jiffies + timeo);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_HOST);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -231,8 +277,10 @@ static void lbtf_submit_command(struct lbtf_private *priv,
|
||||
static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
|
||||
struct cmd_ctrl_node *cmdnode)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
if (!cmdnode)
|
||||
return;
|
||||
goto cl_ins_out;
|
||||
|
||||
cmdnode->callback = NULL;
|
||||
cmdnode->callback_arg = 0;
|
||||
@ -240,6 +288,9 @@ static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
|
||||
memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
|
||||
|
||||
list_add_tail(&cmdnode->list, &priv->cmdfreeq);
|
||||
|
||||
cl_ins_out:
|
||||
lbtf_deb_leave(LBTF_DEB_HOST);
|
||||
}
|
||||
|
||||
static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
|
||||
@ -268,29 +319,41 @@ int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)
|
||||
{
|
||||
struct cmd_ds_mac_multicast_addr cmd;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET);
|
||||
|
||||
cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
|
||||
|
||||
lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs);
|
||||
|
||||
memcpy(cmd.maclist, priv->multicastlist,
|
||||
priv->nr_of_multicastmacaddr * ETH_ALEN);
|
||||
|
||||
lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
|
||||
{
|
||||
struct cmd_ds_set_mode cmd;
|
||||
lbtf_deb_enter(LBTF_DEB_WEXT);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.mode = cpu_to_le16(mode);
|
||||
lbtf_deb_wext("Switching to mode: 0x%x\n", mode);
|
||||
lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_WEXT);
|
||||
}
|
||||
|
||||
void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
|
||||
{
|
||||
struct cmd_ds_set_bssid cmd;
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.activate = activate ? 1 : 0;
|
||||
@ -298,11 +361,13 @@ void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
|
||||
memcpy(cmd.bssid, bssid, ETH_ALEN);
|
||||
|
||||
lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
}
|
||||
|
||||
int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
|
||||
{
|
||||
struct cmd_ds_802_11_mac_address cmd;
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET);
|
||||
@ -310,6 +375,7 @@ int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
|
||||
memcpy(cmd.macadd, mac_addr, ETH_ALEN);
|
||||
|
||||
lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -318,6 +384,8 @@ int lbtf_set_radio_control(struct lbtf_private *priv)
|
||||
int ret = 0;
|
||||
struct cmd_ds_802_11_radio_control cmd;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET);
|
||||
|
||||
@ -341,19 +409,28 @@ int lbtf_set_radio_control(struct lbtf_private *priv)
|
||||
else
|
||||
cmd.control &= cpu_to_le16(~TURN_ON_RF);
|
||||
|
||||
lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
|
||||
priv->preamble);
|
||||
|
||||
ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
|
||||
|
||||
lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lbtf_set_mac_control(struct lbtf_private *priv)
|
||||
{
|
||||
struct cmd_ds_mac_control cmd;
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(priv->mac_control);
|
||||
cmd.reserved = 0;
|
||||
|
||||
lbtf_cmd_async(priv, CMD_MAC_CONTROL,
|
||||
&cmd.hdr, sizeof(cmd));
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -365,29 +442,43 @@ void lbtf_set_mac_control(struct lbtf_private *priv)
|
||||
*/
|
||||
int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 bufsize;
|
||||
u32 i;
|
||||
struct cmd_ctrl_node *cmdarray;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
/* Allocate and initialize the command array */
|
||||
bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
|
||||
cmdarray = kzalloc(bufsize, GFP_KERNEL);
|
||||
if (!cmdarray)
|
||||
return -1;
|
||||
if (!cmdarray) {
|
||||
lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
priv->cmd_array = cmdarray;
|
||||
|
||||
/* Allocate and initialize each command buffer in the command array */
|
||||
for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
|
||||
cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
|
||||
if (!cmdarray[i].cmdbuf)
|
||||
return -1;
|
||||
if (!cmdarray[i].cmdbuf) {
|
||||
lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
|
||||
init_waitqueue_head(&cmdarray[i].cmdwait_q);
|
||||
lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
|
||||
}
|
||||
return 0;
|
||||
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -402,9 +493,13 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv)
|
||||
struct cmd_ctrl_node *cmdarray;
|
||||
unsigned int i;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
/* need to check if cmd array is allocated or not */
|
||||
if (priv->cmd_array == NULL)
|
||||
return 0;
|
||||
if (priv->cmd_array == NULL) {
|
||||
lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmdarray = priv->cmd_array;
|
||||
|
||||
@ -418,6 +513,8 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv)
|
||||
kfree(priv->cmd_array);
|
||||
priv->cmd_array = NULL;
|
||||
|
||||
done:
|
||||
lbtf_deb_leave(LBTF_DEB_HOST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -433,6 +530,8 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
|
||||
struct cmd_ctrl_node *tempnode;
|
||||
unsigned long flags;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
if (!priv)
|
||||
return NULL;
|
||||
|
||||
@ -442,11 +541,14 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
|
||||
tempnode = list_first_entry(&priv->cmdfreeq,
|
||||
struct cmd_ctrl_node, list);
|
||||
list_del(&tempnode->list);
|
||||
} else
|
||||
} else {
|
||||
lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
|
||||
tempnode = NULL;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_HOST);
|
||||
return tempnode;
|
||||
}
|
||||
|
||||
@ -462,16 +564,20 @@ int lbtf_execute_next_command(struct lbtf_private *priv)
|
||||
struct cmd_ctrl_node *cmdnode = NULL;
|
||||
struct cmd_header *cmd;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
|
||||
/* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the
|
||||
* only caller to us is lbtf_thread() and we get even when a
|
||||
* data packet is received */
|
||||
lbtf_deb_enter(LBTF_DEB_THREAD);
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
if (priv->cur_cmd) {
|
||||
pr_alert("EXEC_NEXT_CMD: already processing command!\n");
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!list_empty(&priv->cmdpendingq)) {
|
||||
@ -483,11 +589,17 @@ int lbtf_execute_next_command(struct lbtf_private *priv)
|
||||
cmd = cmdnode->cmdbuf;
|
||||
|
||||
list_del(&cmdnode->list);
|
||||
lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
|
||||
le16_to_cpu(cmd->command));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
lbtf_submit_command(priv, cmdnode);
|
||||
} else
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
return 0;
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
lbtf_deb_leave(LBTF_DEB_THREAD);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
|
||||
@ -498,14 +610,22 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
|
||||
{
|
||||
struct cmd_ctrl_node *cmdnode;
|
||||
|
||||
if (priv->surpriseremoved)
|
||||
return ERR_PTR(-ENOENT);
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
if (priv->surpriseremoved) {
|
||||
lbtf_deb_host("PREP_CMD: card removed\n");
|
||||
cmdnode = ERR_PTR(-ENOENT);
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmdnode = lbtf_get_cmd_ctrl_node(priv);
|
||||
if (cmdnode == NULL) {
|
||||
lbtf_deb_host("PREP_CMD: cmdnode is NULL\n");
|
||||
|
||||
/* Wake up main thread to execute next command */
|
||||
queue_work(lbtf_wq, &priv->cmd_work);
|
||||
return ERR_PTR(-ENOBUFS);
|
||||
cmdnode = ERR_PTR(-ENOBUFS);
|
||||
goto done;
|
||||
}
|
||||
|
||||
cmdnode->callback = callback;
|
||||
@ -520,17 +640,24 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
|
||||
cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size);
|
||||
cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum);
|
||||
cmdnode->cmdbuf->result = 0;
|
||||
|
||||
lbtf_deb_host("PREP_CMD: command 0x%04x\n", command);
|
||||
|
||||
cmdnode->cmdwaitqwoken = 0;
|
||||
lbtf_queue_cmd(priv, cmdnode);
|
||||
queue_work(lbtf_wq, &priv->cmd_work);
|
||||
|
||||
done:
|
||||
lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode);
|
||||
return cmdnode;
|
||||
}
|
||||
|
||||
void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
|
||||
struct cmd_header *in_cmd, int in_cmd_size)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
__lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
}
|
||||
|
||||
int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
|
||||
@ -543,30 +670,35 @@ int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_HOST);
|
||||
|
||||
cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
|
||||
callback, callback_arg);
|
||||
if (IS_ERR(cmdnode))
|
||||
return PTR_ERR(cmdnode);
|
||||
if (IS_ERR(cmdnode)) {
|
||||
ret = PTR_ERR(cmdnode);
|
||||
goto done;
|
||||
}
|
||||
|
||||
might_sleep();
|
||||
ret = wait_event_interruptible(cmdnode->cmdwait_q,
|
||||
cmdnode->cmdwaitqwoken);
|
||||
if (ret) {
|
||||
printk(KERN_DEBUG
|
||||
"libertastf: command 0x%04x interrupted by signal",
|
||||
command);
|
||||
return ret;
|
||||
if (ret) {
|
||||
pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n",
|
||||
command, ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
ret = cmdnode->result;
|
||||
if (ret)
|
||||
printk(KERN_DEBUG "libertastf: command 0x%04x failed: %d\n",
|
||||
pr_info("PREP_CMD: command 0x%04x failed: %d\n",
|
||||
command, ret);
|
||||
|
||||
__lbtf_cleanup_and_insert_cmd(priv, cmdnode);
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
|
||||
done:
|
||||
lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__lbtf_cmd);
|
||||
@ -587,6 +719,8 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
|
||||
unsigned long flags;
|
||||
uint16_t result;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
@ -602,7 +736,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
|
||||
result = le16_to_cpu(resp->result);
|
||||
|
||||
if (net_ratelimit())
|
||||
printk(KERN_DEBUG "libertastf: cmd response 0x%04x, seq %d, size %d\n",
|
||||
pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",
|
||||
respcmd, le16_to_cpu(resp->seqnum),
|
||||
le16_to_cpu(resp->size));
|
||||
|
||||
@ -639,7 +773,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
|
||||
switch (respcmd) {
|
||||
case CMD_RET(CMD_GET_HW_SPEC):
|
||||
case CMD_RET(CMD_802_11_RESET):
|
||||
printk(KERN_DEBUG "libertastf: reset failed\n");
|
||||
pr_info("libertastf: reset failed\n");
|
||||
break;
|
||||
|
||||
}
|
||||
@ -666,5 +800,6 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
|
||||
|
||||
done:
|
||||
mutex_unlock(&priv->lock);
|
||||
lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
104
drivers/net/wireless/libertas_tf/deb_defs.h
Normal file
104
drivers/net/wireless/libertas_tf/deb_defs.h
Normal file
@ -0,0 +1,104 @@
|
||||
/**
|
||||
* This header file contains global constant/enum definitions,
|
||||
* global variable declaration.
|
||||
*/
|
||||
#ifndef _LBS_DEB_DEFS_H_
|
||||
#define _LBS_DEB_EFS_H_
|
||||
|
||||
#ifndef DRV_NAME
|
||||
#define DRV_NAME "libertas_tf"
|
||||
#endif
|
||||
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#ifdef CONFIG_LIBERTAS_THINFIRM_DEBUG
|
||||
#define DEBUG
|
||||
#define PROC_DEBUG
|
||||
#endif
|
||||
|
||||
#define LBTF_DEB_ENTER 0x00000001
|
||||
#define LBTF_DEB_LEAVE 0x00000002
|
||||
#define LBTF_DEB_MAIN 0x00000004
|
||||
#define LBTF_DEB_NET 0x00000008
|
||||
#define LBTF_DEB_MESH 0x00000010
|
||||
#define LBTF_DEB_WEXT 0x00000020
|
||||
#define LBTF_DEB_IOCTL 0x00000040
|
||||
#define LBTF_DEB_SCAN 0x00000080
|
||||
#define LBTF_DEB_ASSOC 0x00000100
|
||||
#define LBTF_DEB_JOIN 0x00000200
|
||||
#define LBTF_DEB_11D 0x00000400
|
||||
#define LBTF_DEB_DEBUGFS 0x00000800
|
||||
#define LBTF_DEB_ETHTOOL 0x00001000
|
||||
#define LBTF_DEB_HOST 0x00002000
|
||||
#define LBTF_DEB_CMD 0x00004000
|
||||
#define LBTF_DEB_RX 0x00008000
|
||||
#define LBTF_DEB_TX 0x00010000
|
||||
#define LBTF_DEB_USB 0x00020000
|
||||
#define LBTF_DEB_CS 0x00040000
|
||||
#define LBTF_DEB_FW 0x00080000
|
||||
#define LBTF_DEB_THREAD 0x00100000
|
||||
#define LBTF_DEB_HEX 0x00200000
|
||||
#define LBTF_DEB_SDIO 0x00400000
|
||||
#define LBTF_DEB_MACOPS 0x00800000
|
||||
|
||||
extern unsigned int lbtf_debug;
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LBTF_DEB_LL(grp, grpnam, fmt, args...) \
|
||||
do { if ((lbtf_debug & (grp)) == (grp)) \
|
||||
printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
|
||||
in_interrupt() ? " (INT)" : "", ## args); } while (0)
|
||||
#else
|
||||
#define LBTF_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define lbtf_deb_enter(grp) \
|
||||
LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s()\n", __func__);
|
||||
#define lbtf_deb_enter_args(grp, fmt, args...) \
|
||||
LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
|
||||
#define lbtf_deb_leave(grp) \
|
||||
LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s()\n", __func__);
|
||||
#define lbtf_deb_leave_args(grp, fmt, args...) \
|
||||
LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
|
||||
__func__, ##args);
|
||||
#define lbtf_deb_main(fmt, args...) LBTF_DEB_LL(LBTF_DEB_MAIN, " main", fmt, ##args)
|
||||
#define lbtf_deb_net(fmt, args...) LBTF_DEB_LL(LBTF_DEB_NET, " net", fmt, ##args)
|
||||
#define lbtf_deb_mesh(fmt, args...) LBTF_DEB_LL(LBTF_DEB_MESH, " mesh", fmt, ##args)
|
||||
#define lbtf_deb_wext(fmt, args...) LBTF_DEB_LL(LBTF_DEB_WEXT, " wext", fmt, ##args)
|
||||
#define lbtf_deb_ioctl(fmt, args...) LBTF_DEB_LL(LBTF_DEB_IOCTL, " ioctl", fmt, ##args)
|
||||
#define lbtf_deb_scan(fmt, args...) LBTF_DEB_LL(LBTF_DEB_SCAN, " scan", fmt, ##args)
|
||||
#define lbtf_deb_assoc(fmt, args...) LBTF_DEB_LL(LBTF_DEB_ASSOC, " assoc", fmt, ##args)
|
||||
#define lbtf_deb_join(fmt, args...) LBTF_DEB_LL(LBTF_DEB_JOIN, " join", fmt, ##args)
|
||||
#define lbtf_deb_11d(fmt, args...) LBTF_DEB_LL(LBTF_DEB_11D, " 11d", fmt, ##args)
|
||||
#define lbtf_deb_debugfs(fmt, args...) LBTF_DEB_LL(LBTF_DEB_DEBUGFS, " debugfs", fmt, ##args)
|
||||
#define lbtf_deb_ethtool(fmt, args...) LBTF_DEB_LL(LBTF_DEB_ETHTOOL, " ethtool", fmt, ##args)
|
||||
#define lbtf_deb_host(fmt, args...) LBTF_DEB_LL(LBTF_DEB_HOST, " host", fmt, ##args)
|
||||
#define lbtf_deb_cmd(fmt, args...) LBTF_DEB_LL(LBTF_DEB_CMD, " cmd", fmt, ##args)
|
||||
#define lbtf_deb_rx(fmt, args...) LBTF_DEB_LL(LBTF_DEB_RX, " rx", fmt, ##args)
|
||||
#define lbtf_deb_tx(fmt, args...) LBTF_DEB_LL(LBTF_DEB_TX, " tx", fmt, ##args)
|
||||
#define lbtf_deb_fw(fmt, args...) LBTF_DEB_LL(LBTF_DEB_FW, " fw", fmt, ##args)
|
||||
#define lbtf_deb_usb(fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usb", fmt, ##args)
|
||||
#define lbtf_deb_usbd(dev, fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
|
||||
#define lbtf_deb_cs(fmt, args...) LBTF_DEB_LL(LBTF_DEB_CS, " cs", fmt, ##args)
|
||||
#define lbtf_deb_thread(fmt, args...) LBTF_DEB_LL(LBTF_DEB_THREAD, " thread", fmt, ##args)
|
||||
#define lbtf_deb_sdio(fmt, args...) LBTF_DEB_LL(LBTF_DEB_SDIO, " thread", fmt, ##args)
|
||||
#define lbtf_deb_macops(fmt, args...) LBTF_DEB_LL(LBTF_DEB_MACOPS, " thread", fmt, ##args)
|
||||
|
||||
#ifdef DEBUG
|
||||
static inline void lbtf_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
|
||||
{
|
||||
char newprompt[32];
|
||||
|
||||
if (len &&
|
||||
(lbtf_debug & LBTF_DEB_HEX) &&
|
||||
(lbtf_debug & grp)) {
|
||||
snprintf(newprompt, sizeof(newprompt), DRV_NAME " %s: ", prompt);
|
||||
print_hex_dump_bytes(prompt, DUMP_PREFIX_NONE, buf, len);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define lbtf_deb_hex(grp, prompt, buf, len) do {} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
@ -7,6 +7,13 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*/
|
||||
#define DRV_NAME "lbtf_usb"
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include "libertas_tf.h"
|
||||
#include "if_usb.h"
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/firmware.h>
|
||||
@ -14,10 +21,8 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#define DRV_NAME "lbtf_usb"
|
||||
|
||||
#include "libertas_tf.h"
|
||||
#include "if_usb.h"
|
||||
#define INSANEDEBUG 0
|
||||
#define lbtf_deb_usb2(...) do { if (INSANEDEBUG) lbtf_deb_usbd(__VA_ARGS__); } while (0)
|
||||
|
||||
#define MESSAGE_HEADER_LEN 4
|
||||
|
||||
@ -53,9 +58,14 @@ static int if_usb_reset_device(struct if_usb_card *cardp);
|
||||
*/
|
||||
static void if_usb_write_bulk_callback(struct urb *urb)
|
||||
{
|
||||
if (urb->status != 0)
|
||||
printk(KERN_INFO "libertastf: URB in failure status: %d\n",
|
||||
urb->status);
|
||||
if (urb->status != 0) {
|
||||
/* print the failure status number for debug */
|
||||
pr_info("URB in failure status: %d\n", urb->status);
|
||||
} else {
|
||||
lbtf_deb_usb2(&urb->dev->dev, "URB status is successful\n");
|
||||
lbtf_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
|
||||
urb->actual_length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,6 +75,8 @@ static void if_usb_write_bulk_callback(struct urb *urb)
|
||||
*/
|
||||
static void if_usb_free(struct if_usb_card *cardp)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
|
||||
/* Unlink tx & rx urb */
|
||||
usb_kill_urb(cardp->tx_urb);
|
||||
usb_kill_urb(cardp->rx_urb);
|
||||
@ -81,6 +93,8 @@ static void if_usb_free(struct if_usb_card *cardp)
|
||||
|
||||
kfree(cardp->ep_out_buf);
|
||||
cardp->ep_out_buf = NULL;
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
}
|
||||
|
||||
static void if_usb_setup_firmware(struct lbtf_private *priv)
|
||||
@ -88,23 +102,33 @@ static void if_usb_setup_firmware(struct lbtf_private *priv)
|
||||
struct if_usb_card *cardp = priv->card;
|
||||
struct cmd_ds_set_boot2_ver b2_cmd;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
|
||||
if_usb_submit_rx_urb(cardp);
|
||||
b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
|
||||
b2_cmd.action = 0;
|
||||
b2_cmd.version = cardp->boot2_version;
|
||||
|
||||
if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
|
||||
printk(KERN_INFO "libertastf: setting boot2 version failed\n");
|
||||
lbtf_deb_usb("Setting boot2 version failed\n");
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
}
|
||||
|
||||
static void if_usb_fw_timeo(unsigned long priv)
|
||||
{
|
||||
struct if_usb_card *cardp = (void *)priv;
|
||||
|
||||
if (!cardp->fwdnldover)
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
if (!cardp->fwdnldover) {
|
||||
/* Download timed out */
|
||||
cardp->priv->surpriseremoved = 1;
|
||||
pr_err("Download timed out\n");
|
||||
} else {
|
||||
lbtf_deb_usb("Download complete, no event. Assuming success\n");
|
||||
}
|
||||
wake_up(&cardp->fw_wq);
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,11 +149,14 @@ static int if_usb_probe(struct usb_interface *intf,
|
||||
struct if_usb_card *cardp;
|
||||
int i;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
udev = interface_to_usbdev(intf);
|
||||
|
||||
cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
|
||||
if (!cardp)
|
||||
if (!cardp) {
|
||||
pr_err("Out of memory allocating private data.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
|
||||
init_waitqueue_head(&cardp->fw_wq);
|
||||
@ -137,38 +164,62 @@ static int if_usb_probe(struct usb_interface *intf,
|
||||
cardp->udev = udev;
|
||||
iface_desc = intf->cur_altsetting;
|
||||
|
||||
lbtf_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
|
||||
" bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
|
||||
le16_to_cpu(udev->descriptor.bcdUSB),
|
||||
udev->descriptor.bDeviceClass,
|
||||
udev->descriptor.bDeviceSubClass,
|
||||
udev->descriptor.bDeviceProtocol);
|
||||
|
||||
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
if (usb_endpoint_is_bulk_in(endpoint)) {
|
||||
cardp->ep_in_size =
|
||||
le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
cardp->ep_in = usb_endpoint_num(endpoint);
|
||||
|
||||
lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
|
||||
lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
|
||||
} else if (usb_endpoint_is_bulk_out(endpoint)) {
|
||||
cardp->ep_out_size =
|
||||
le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
cardp->ep_out = usb_endpoint_num(endpoint);
|
||||
|
||||
lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
|
||||
lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n",
|
||||
cardp->ep_out_size);
|
||||
}
|
||||
}
|
||||
if (!cardp->ep_out_size || !cardp->ep_in_size)
|
||||
if (!cardp->ep_out_size || !cardp->ep_in_size) {
|
||||
lbtf_deb_usbd(&udev->dev, "Endpoints not found\n");
|
||||
/* Endpoints not found */
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!cardp->rx_urb)
|
||||
if (!cardp->rx_urb) {
|
||||
lbtf_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!cardp->tx_urb)
|
||||
if (!cardp->tx_urb) {
|
||||
lbtf_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (!cardp->cmd_urb)
|
||||
if (!cardp->cmd_urb) {
|
||||
lbtf_deb_usbd(&udev->dev, "Cmd URB allocation failed\n");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (!cardp->ep_out_buf)
|
||||
if (!cardp->ep_out_buf) {
|
||||
lbtf_deb_usbd(&udev->dev, "Could not allocate buffer\n");
|
||||
goto dealloc;
|
||||
}
|
||||
|
||||
priv = lbtf_add_card(cardp, &udev->dev);
|
||||
if (!priv)
|
||||
@ -189,6 +240,7 @@ static int if_usb_probe(struct usb_interface *intf,
|
||||
dealloc:
|
||||
if_usb_free(cardp);
|
||||
error:
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -202,6 +254,8 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
||||
struct if_usb_card *cardp = usb_get_intfdata(intf);
|
||||
struct lbtf_private *priv = (struct lbtf_private *) cardp->priv;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
|
||||
if_usb_reset_device(cardp);
|
||||
|
||||
if (priv)
|
||||
@ -212,6 +266,8 @@ static void if_usb_disconnect(struct usb_interface *intf)
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
usb_put_dev(interface_to_usbdev(intf));
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,6 +282,8 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
|
||||
struct fwdata *fwdata = cardp->ep_out_buf;
|
||||
u8 *firmware = (u8 *) cardp->fw->data;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_FW);
|
||||
|
||||
/* If we got a CRC failure on the last block, back
|
||||
up and retry it */
|
||||
if (!cardp->CRC_OK) {
|
||||
@ -233,6 +291,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
|
||||
cardp->fwseqnum--;
|
||||
}
|
||||
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
|
||||
cardp->totalbytes);
|
||||
|
||||
/* struct fwdata (which we sent to the card) has an
|
||||
extra __le32 field in between the header and the data,
|
||||
which is not in the struct fwheader in the actual
|
||||
@ -246,18 +307,33 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
|
||||
memcpy(fwdata->data, &firmware[cardp->totalbytes],
|
||||
le32_to_cpu(fwdata->hdr.datalength));
|
||||
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
|
||||
le32_to_cpu(fwdata->hdr.datalength));
|
||||
|
||||
fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
|
||||
cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
|
||||
|
||||
usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
|
||||
le32_to_cpu(fwdata->hdr.datalength), 0);
|
||||
|
||||
if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK))
|
||||
if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
|
||||
cardp->fwseqnum, cardp->totalbytes);
|
||||
} else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
|
||||
|
||||
/* Host has finished FW downloading
|
||||
* Donwloading FW JUMP BLOCK
|
||||
*/
|
||||
cardp->fwfinalblk = 1;
|
||||
}
|
||||
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
|
||||
cardp->totalbytes);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_FW);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -266,6 +342,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
|
||||
struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
|
||||
int ret;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
|
||||
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
|
||||
|
||||
cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET);
|
||||
@ -280,6 +358,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
|
||||
ret = usb_reset_device(cardp->udev);
|
||||
msleep(100);
|
||||
|
||||
lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(if_usb_reset_device);
|
||||
@ -297,11 +377,15 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device);
|
||||
static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
|
||||
uint16_t nb, u8 data)
|
||||
{
|
||||
int ret = -1;
|
||||
struct urb *urb;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
/* check if device is removed */
|
||||
if (cardp->priv->surpriseremoved)
|
||||
return -1;
|
||||
if (cardp->priv->surpriseremoved) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "Device removed\n");
|
||||
goto tx_ret;
|
||||
}
|
||||
|
||||
if (data)
|
||||
urb = cardp->tx_urb;
|
||||
@ -315,19 +399,34 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
|
||||
|
||||
urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
if (usb_submit_urb(urb, GFP_ATOMIC))
|
||||
return -1;
|
||||
return 0;
|
||||
if (usb_submit_urb(urb, GFP_ATOMIC)) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
|
||||
goto tx_ret;
|
||||
}
|
||||
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
|
||||
|
||||
ret = 0;
|
||||
|
||||
tx_ret:
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
|
||||
void (*callbackfn)(struct urb *urb))
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret = -1;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
|
||||
skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
|
||||
if (!skb)
|
||||
if (!skb) {
|
||||
pr_err("No free skb\n");
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cardp->rx_skb = skb;
|
||||
|
||||
@ -339,12 +438,19 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
|
||||
|
||||
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
|
||||
|
||||
if (usb_submit_urb(cardp->rx_urb, GFP_ATOMIC)) {
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
|
||||
ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
|
||||
if (ret) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
|
||||
kfree_skb(skb);
|
||||
cardp->rx_skb = NULL;
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return -1;
|
||||
} else
|
||||
} else {
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
|
||||
@ -364,8 +470,12 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
struct fwsyncheader *syncfwheader;
|
||||
struct bootcmdresp bcmdresp;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
if (urb->status) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev,
|
||||
"URB status is failed during fw load\n");
|
||||
kfree_skb(skb);
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -373,12 +483,17 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
__le32 *tmp = (__le32 *)(skb->data);
|
||||
|
||||
if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
|
||||
tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY))
|
||||
tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {
|
||||
/* Firmware ready event received */
|
||||
pr_info("Firmware ready event received\n");
|
||||
wake_up(&cardp->fw_wq);
|
||||
else
|
||||
} else {
|
||||
lbtf_deb_usb("Waiting for confirmation; got %x %x\n",
|
||||
le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
|
||||
if_usb_submit_rx_urb_fwload(cardp);
|
||||
}
|
||||
kfree_skb(skb);
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return;
|
||||
}
|
||||
if (cardp->bootcmdresp <= 0) {
|
||||
@ -389,34 +504,60 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
if_usb_submit_rx_urb_fwload(cardp);
|
||||
cardp->bootcmdresp = 1;
|
||||
/* Received valid boot command response */
|
||||
lbtf_deb_usbd(&cardp->udev->dev,
|
||||
"Received valid boot command response\n");
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return;
|
||||
}
|
||||
if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
|
||||
if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
|
||||
bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
|
||||
bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION))
|
||||
bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
|
||||
if (!cardp->bootcmdresp)
|
||||
pr_info("Firmware already seems alive; resetting\n");
|
||||
cardp->bootcmdresp = -1;
|
||||
} else if (bcmdresp.cmd == BOOT_CMD_FW_BY_USB &&
|
||||
bcmdresp.result == BOOT_CMD_RESP_OK)
|
||||
} else {
|
||||
pr_info("boot cmd response wrong magic number (0x%x)\n",
|
||||
le32_to_cpu(bcmdresp.magic));
|
||||
}
|
||||
} else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
|
||||
pr_info("boot cmd response cmd_tag error (%d)\n",
|
||||
bcmdresp.cmd);
|
||||
} else if (bcmdresp.result != BOOT_CMD_RESP_OK) {
|
||||
pr_info("boot cmd response result error (%d)\n",
|
||||
bcmdresp.result);
|
||||
} else {
|
||||
cardp->bootcmdresp = 1;
|
||||
lbtf_deb_usbd(&cardp->udev->dev,
|
||||
"Received valid boot command response\n");
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
if_usb_submit_rx_urb_fwload(cardp);
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return;
|
||||
}
|
||||
|
||||
syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
|
||||
if (!syncfwheader) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
|
||||
kfree_skb(skb);
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader));
|
||||
|
||||
if (!syncfwheader->cmd)
|
||||
if (!syncfwheader->cmd) {
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
|
||||
lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
|
||||
le32_to_cpu(syncfwheader->seqnum));
|
||||
cardp->CRC_OK = 1;
|
||||
else
|
||||
} else {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
|
||||
cardp->CRC_OK = 0;
|
||||
}
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
/* reschedule timer for 200ms hence */
|
||||
@ -434,6 +575,7 @@ static void if_usb_receive_fwload(struct urb *urb)
|
||||
|
||||
kfree(syncfwheader);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -445,6 +587,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
|
||||
{
|
||||
if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
|
||||
|| recvlength < MRVDRV_MIN_PKT_LEN) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
@ -460,6 +603,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
|
||||
struct lbtf_private *priv)
|
||||
{
|
||||
if (recvlength > LBS_CMD_BUFFER_SIZE) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev,
|
||||
"The receive buffer is too large\n");
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
@ -489,16 +634,24 @@ static void if_usb_receive(struct urb *urb)
|
||||
uint32_t recvtype = 0;
|
||||
__le32 *pkt = (__le32 *) skb->data;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
|
||||
if (recvlength) {
|
||||
if (urb->status) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
|
||||
urb->status);
|
||||
kfree_skb(skb);
|
||||
goto setup_for_next;
|
||||
}
|
||||
|
||||
recvbuff = skb->data;
|
||||
recvtype = le32_to_cpu(pkt[0]);
|
||||
lbtf_deb_usbd(&cardp->udev->dev,
|
||||
"Recv length = 0x%x, Recv type = 0x%X\n",
|
||||
recvlength, recvtype);
|
||||
} else if (urb->status) {
|
||||
kfree_skb(skb);
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -515,6 +668,7 @@ static void if_usb_receive(struct urb *urb)
|
||||
{
|
||||
/* Event cause handling */
|
||||
u32 event_cause = le32_to_cpu(pkt[1]);
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause);
|
||||
|
||||
/* Icky undocumented magic special case */
|
||||
if (event_cause & 0xffff0000) {
|
||||
@ -529,21 +683,22 @@ static void if_usb_receive(struct urb *urb)
|
||||
} else if (event_cause == LBTF_EVENT_BCN_SENT)
|
||||
lbtf_bcn_sent(priv);
|
||||
else
|
||||
printk(KERN_DEBUG
|
||||
lbtf_deb_usbd(&cardp->udev->dev,
|
||||
"Unsupported notification %d received\n",
|
||||
event_cause);
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printk(KERN_DEBUG "libertastf: unknown command type 0x%X\n",
|
||||
recvtype);
|
||||
lbtf_deb_usbd(&cardp->udev->dev,
|
||||
"libertastf: unknown command type 0x%X\n", recvtype);
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
|
||||
setup_for_next:
|
||||
if_usb_submit_rx_urb(cardp);
|
||||
lbtf_deb_leave(LBTF_DEB_USB);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -562,6 +717,9 @@ static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
|
||||
struct if_usb_card *cardp = priv->card;
|
||||
u8 data = 0;
|
||||
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "*** type = %u\n", type);
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "size after = %d\n", nb);
|
||||
|
||||
if (type == MVMS_CMD) {
|
||||
*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
|
||||
} else {
|
||||
@ -639,8 +797,10 @@ static int check_fwfile_format(const u8 *data, u32 totlen)
|
||||
} while (!exit);
|
||||
|
||||
if (ret)
|
||||
printk(KERN_INFO
|
||||
"libertastf: firmware file format check failed\n");
|
||||
pr_err("firmware file format check FAIL\n");
|
||||
else
|
||||
lbtf_deb_fw("firmware file format check PASS\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -651,10 +811,12 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
|
||||
static int reset_count = 10;
|
||||
int ret = 0;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_USB);
|
||||
|
||||
ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
|
||||
if (ret < 0) {
|
||||
printk(KERN_INFO "libertastf: firmware %s not found\n",
|
||||
lbtf_fw_name);
|
||||
pr_err("request_firmware() failed with %#x\n", ret);
|
||||
pr_err("firmware %s not found\n", lbtf_fw_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@ -663,6 +825,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
|
||||
|
||||
restart:
|
||||
if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
|
||||
lbtf_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
|
||||
ret = -1;
|
||||
goto release_fw;
|
||||
}
|
||||
@ -709,14 +872,13 @@ restart:
|
||||
usb_kill_urb(cardp->rx_urb);
|
||||
|
||||
if (!cardp->fwdnldover) {
|
||||
printk(KERN_INFO "libertastf: failed to load fw,"
|
||||
" resetting device!\n");
|
||||
pr_info("failed to load fw, resetting device!\n");
|
||||
if (--reset_count >= 0) {
|
||||
if_usb_reset_device(cardp);
|
||||
goto restart;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "libertastf: fw download failure\n");
|
||||
pr_info("FW download failure, time = %d ms\n", i * 100);
|
||||
ret = -1;
|
||||
goto release_fw;
|
||||
}
|
||||
@ -730,6 +892,7 @@ restart:
|
||||
if_usb_setup_firmware(cardp->priv);
|
||||
|
||||
done:
|
||||
lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(if_usb_prog_firmware);
|
||||
@ -751,13 +914,19 @@ static int __init if_usb_init_module(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
|
||||
ret = usb_register(&if_usb_driver);
|
||||
|
||||
lbtf_deb_leave_args(LBTF_DEB_MAIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit if_usb_exit_module(void)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
usb_deregister(&if_usb_driver);
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
}
|
||||
|
||||
module_init(if_usb_init_module);
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <linux/kthread.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "deb_defs.h"
|
||||
|
||||
#ifndef DRV_NAME
|
||||
#define DRV_NAME "libertas_tf"
|
||||
#endif
|
||||
|
@ -7,10 +7,12 @@
|
||||
* the Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
#include "libertas_tf.h"
|
||||
#include "linux/etherdevice.h"
|
||||
|
||||
#define DRIVER_RELEASE_VERSION "004.p0"
|
||||
/* thinfirm version: 5.132.X.pX */
|
||||
@ -18,7 +20,17 @@
|
||||
#define LBTF_FW_VER_MAX 0x0584ffff
|
||||
#define QOS_CONTROL_LEN 2
|
||||
|
||||
static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION;
|
||||
/* Module parameters */
|
||||
unsigned int lbtf_debug;
|
||||
EXPORT_SYMBOL_GPL(lbtf_debug);
|
||||
module_param_named(libertas_tf_debug, lbtf_debug, int, 0644);
|
||||
|
||||
static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION
|
||||
#ifdef DEBUG
|
||||
"-dbg"
|
||||
#endif
|
||||
"";
|
||||
|
||||
struct workqueue_struct *lbtf_wq;
|
||||
|
||||
static const struct ieee80211_channel lbtf_channels[] = {
|
||||
@ -81,6 +93,9 @@ static void lbtf_cmd_work(struct work_struct *work)
|
||||
{
|
||||
struct lbtf_private *priv = container_of(work, struct lbtf_private,
|
||||
cmd_work);
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
/* command response? */
|
||||
if (priv->cmd_response_rxed) {
|
||||
@ -108,11 +123,16 @@ static void lbtf_cmd_work(struct work_struct *work)
|
||||
priv->cmd_timed_out = 0;
|
||||
spin_unlock_irq(&priv->driver_lock);
|
||||
|
||||
if (!priv->fw_ready)
|
||||
if (!priv->fw_ready) {
|
||||
lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Execute the next command */
|
||||
if (!priv->cur_cmd)
|
||||
lbtf_execute_next_command(priv);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,6 +146,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_FW);
|
||||
/*
|
||||
* Read priv address from HW
|
||||
*/
|
||||
@ -141,6 +162,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv)
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -152,6 +174,7 @@ static void command_timer_fn(unsigned long data)
|
||||
{
|
||||
struct lbtf_private *priv = (struct lbtf_private *)data;
|
||||
unsigned long flags;
|
||||
lbtf_deb_enter(LBTF_DEB_CMD);
|
||||
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
|
||||
@ -168,10 +191,12 @@ static void command_timer_fn(unsigned long data)
|
||||
queue_work(lbtf_wq, &priv->cmd_work);
|
||||
out:
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
lbtf_deb_leave(LBTF_DEB_CMD);
|
||||
}
|
||||
|
||||
static int lbtf_init_adapter(struct lbtf_private *priv)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
memset(priv->current_addr, 0xff, ETH_ALEN);
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
@ -188,13 +213,16 @@ static int lbtf_init_adapter(struct lbtf_private *priv)
|
||||
if (lbtf_allocate_cmd_buffer(priv))
|
||||
return -1;
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lbtf_free_adapter(struct lbtf_private *priv)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
lbtf_free_cmd_buffer(priv);
|
||||
del_timer(&priv->command_timer);
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
}
|
||||
|
||||
static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
@ -221,14 +249,18 @@ static void lbtf_tx_work(struct work_struct *work)
|
||||
struct sk_buff *skb = NULL;
|
||||
int err;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS | LBTF_DEB_TX);
|
||||
|
||||
if ((priv->vif->type == NL80211_IFTYPE_AP) &&
|
||||
(!skb_queue_empty(&priv->bc_ps_buf)))
|
||||
skb = skb_dequeue(&priv->bc_ps_buf);
|
||||
else if (priv->skb_to_tx) {
|
||||
skb = priv->skb_to_tx;
|
||||
priv->skb_to_tx = NULL;
|
||||
} else
|
||||
} else {
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
|
||||
return;
|
||||
}
|
||||
|
||||
len = skb->len;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
@ -236,6 +268,7 @@ static void lbtf_tx_work(struct work_struct *work)
|
||||
|
||||
if (priv->surpriseremoved) {
|
||||
dev_kfree_skb_any(skb);
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -249,6 +282,7 @@ static void lbtf_tx_work(struct work_struct *work)
|
||||
ETH_ALEN);
|
||||
txpd->tx_packet_length = cpu_to_le16(len);
|
||||
txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
|
||||
lbtf_deb_hex(LBTF_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
|
||||
BUG_ON(priv->tx_skb);
|
||||
spin_lock_irq(&priv->driver_lock);
|
||||
priv->tx_skb = skb;
|
||||
@ -257,7 +291,9 @@ static void lbtf_tx_work(struct work_struct *work)
|
||||
if (err) {
|
||||
dev_kfree_skb_any(skb);
|
||||
priv->tx_skb = NULL;
|
||||
pr_err("TX error: %d", err);
|
||||
}
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
|
||||
}
|
||||
|
||||
static int lbtf_op_start(struct ieee80211_hw *hw)
|
||||
@ -266,6 +302,8 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
|
||||
void *card = priv->card;
|
||||
int ret = -1;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS);
|
||||
|
||||
if (!priv->fw_ready)
|
||||
/* Upload firmware */
|
||||
if (priv->hw_prog_firmware(card))
|
||||
@ -286,10 +324,12 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
return 0;
|
||||
|
||||
err_prog_firmware:
|
||||
priv->hw_reset_device(card);
|
||||
lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programing fw; ret=%d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -300,6 +340,9 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)
|
||||
struct sk_buff *skb;
|
||||
|
||||
struct cmd_ctrl_node *cmdnode;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS);
|
||||
|
||||
/* Flush pending command nodes */
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
|
||||
@ -316,6 +359,7 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)
|
||||
priv->radioon = RADIO_OFF;
|
||||
lbtf_set_radio_control(priv);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -323,6 +367,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS);
|
||||
if (priv->vif != NULL)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
@ -340,6 +385,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
lbtf_set_mac_address(priv, (u8 *) vif->addr);
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -347,6 +393,7 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS);
|
||||
|
||||
if (priv->vif->type == NL80211_IFTYPE_AP ||
|
||||
priv->vif->type == NL80211_IFTYPE_MESH_POINT)
|
||||
@ -354,17 +401,20 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
|
||||
lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
|
||||
lbtf_set_bssid(priv, 0, NULL);
|
||||
priv->vif = NULL;
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
}
|
||||
|
||||
static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS);
|
||||
|
||||
if (conf->channel->center_freq != priv->cur_freq) {
|
||||
priv->cur_freq = conf->channel->center_freq;
|
||||
lbtf_set_channel(priv, conf->channel->hw_value);
|
||||
}
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -395,11 +445,16 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
int old_mac_control = priv->mac_control;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS);
|
||||
|
||||
changed_flags &= SUPPORTED_FIF_FLAGS;
|
||||
*new_flags &= SUPPORTED_FIF_FLAGS;
|
||||
|
||||
if (!changed_flags)
|
||||
if (!changed_flags) {
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (*new_flags & (FIF_PROMISC_IN_BSS))
|
||||
priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE;
|
||||
@ -425,6 +480,8 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
|
||||
|
||||
if (priv->mac_control != old_mac_control)
|
||||
lbtf_set_mac_control(priv);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
}
|
||||
|
||||
static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
@ -434,6 +491,7 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct lbtf_private *priv = hw->priv;
|
||||
struct sk_buff *beacon;
|
||||
lbtf_deb_enter(LBTF_DEB_MACOPS);
|
||||
|
||||
if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
|
||||
switch (priv->vif->type) {
|
||||
@ -464,6 +522,8 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
priv->preamble = CMD_TYPE_LONG_PREAMBLE;
|
||||
lbtf_set_radio_control(priv);
|
||||
}
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_MACOPS);
|
||||
}
|
||||
|
||||
static const struct ieee80211_ops lbtf_ops = {
|
||||
@ -486,6 +546,8 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
|
||||
unsigned int flags;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_RX);
|
||||
|
||||
prxpd = (struct rxpd *) skb->data;
|
||||
|
||||
stats.flag = 0;
|
||||
@ -494,7 +556,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
|
||||
stats.freq = priv->cur_freq;
|
||||
stats.band = IEEE80211_BAND_2GHZ;
|
||||
stats.signal = prxpd->snr;
|
||||
stats.noise = prxpd->nf;
|
||||
/* Marvell rate index has a hole at value 4 */
|
||||
if (prxpd->rx_rate > 4)
|
||||
--prxpd->rx_rate;
|
||||
@ -516,7 +577,15 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
|
||||
}
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
|
||||
|
||||
lbtf_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
|
||||
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
|
||||
lbtf_deb_hex(LBTF_DEB_RX, "RX Data", skb->data,
|
||||
min_t(unsigned int, skb->len, 100));
|
||||
|
||||
ieee80211_rx_irqsafe(priv->hw, skb);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_RX);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbtf_rx);
|
||||
@ -533,6 +602,8 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
|
||||
struct ieee80211_hw *hw;
|
||||
struct lbtf_private *priv = NULL;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);
|
||||
if (!hw)
|
||||
goto done;
|
||||
@ -575,6 +646,7 @@ err_init_adapter:
|
||||
priv = NULL;
|
||||
|
||||
done:
|
||||
lbtf_deb_leave_args(LBTF_DEB_MAIN, "priv %p", priv);
|
||||
return priv;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbtf_add_card);
|
||||
@ -584,6 +656,8 @@ int lbtf_remove_card(struct lbtf_private *priv)
|
||||
{
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
|
||||
priv->surpriseremoved = 1;
|
||||
del_timer(&priv->command_timer);
|
||||
lbtf_free_adapter(priv);
|
||||
@ -591,6 +665,7 @@ int lbtf_remove_card(struct lbtf_private *priv)
|
||||
ieee80211_unregister_hw(hw);
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbtf_remove_card);
|
||||
@ -649,17 +724,21 @@ EXPORT_SYMBOL_GPL(lbtf_bcn_sent);
|
||||
|
||||
static int __init lbtf_init_module(void)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
lbtf_wq = create_workqueue("libertastf");
|
||||
if (lbtf_wq == NULL) {
|
||||
printk(KERN_ERR "libertastf: couldn't create workqueue\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit lbtf_exit_module(void)
|
||||
{
|
||||
lbtf_deb_enter(LBTF_DEB_MAIN);
|
||||
destroy_workqueue(lbtf_wq);
|
||||
lbtf_deb_leave(LBTF_DEB_MAIN);
|
||||
}
|
||||
|
||||
module_init(lbtf_init_module);
|
||||
|
@ -974,6 +974,7 @@ static void hw_scan_done(struct work_struct *work)
|
||||
}
|
||||
|
||||
static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL);
|
||||
@ -1020,7 +1021,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
|
||||
mutex_lock(&hwsim->mutex);
|
||||
|
||||
printk(KERN_DEBUG "hwsim sw_scan_complete\n");
|
||||
hwsim->scanning = true;
|
||||
hwsim->scanning = false;
|
||||
|
||||
mutex_unlock(&hwsim->mutex);
|
||||
}
|
||||
@ -1299,7 +1300,8 @@ static int __init init_mac80211_hwsim(void)
|
||||
hw->flags = IEEE80211_HW_MFP_CAPABLE |
|
||||
IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_SUPPORTS_STATIC_SMPS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS;
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION;
|
||||
|
||||
/* ask mac80211 to reserve space for magic */
|
||||
hw->vif_data_size = sizeof(struct hwsim_vif_priv);
|
||||
|
@ -750,7 +750,6 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
status->signal = -rxd->rssi;
|
||||
status->noise = -rxd->noise_floor;
|
||||
|
||||
if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
|
||||
status->flag |= RX_FLAG_HT;
|
||||
@ -852,7 +851,6 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
|
||||
memset(status, 0, sizeof(*status));
|
||||
|
||||
status->signal = -rxd->rssi;
|
||||
status->noise = -rxd->noise_level;
|
||||
status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);
|
||||
status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info);
|
||||
|
||||
@ -3984,8 +3982,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
|
||||
|
||||
hw->queues = MWL8K_TX_QUEUES;
|
||||
|
||||
/* Set rssi and noise values to dBm */
|
||||
hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
|
||||
/* Set rssi values to dBm */
|
||||
hw->flags |= IEEE80211_HW_SIGNAL_DBM;
|
||||
hw->vif_data_size = sizeof(struct mwl8k_vif);
|
||||
hw->sta_data_size = sizeof(struct mwl8k_sta);
|
||||
|
||||
|
@ -132,3 +132,10 @@ config PCMCIA_SPECTRUM
|
||||
This driver requires firmware download on startup. Utilities
|
||||
for downloading Symbol firmware are available at
|
||||
<http://sourceforge.net/projects/orinoco/>
|
||||
|
||||
config ORINOCO_USB
|
||||
tristate "Agere Orinoco USB support"
|
||||
depends on USB && HERMES
|
||||
select FW_LOADER
|
||||
---help---
|
||||
This driver is for USB versions of the Agere Orinoco card.
|
||||
|
@ -11,6 +11,7 @@ obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
|
||||
obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
|
||||
obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
|
||||
obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
|
||||
obj-$(CONFIG_ORINOCO_USB) += orinoco_usb.o
|
||||
|
||||
# Orinoco should be endian clean.
|
||||
ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
@ -77,9 +77,9 @@ airport_resume(struct macio_dev *mdev)
|
||||
|
||||
enable_irq(card->irq);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
err = orinoco_up(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
return err;
|
||||
}
|
||||
@ -195,7 +195,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
|
||||
ssleep(1);
|
||||
|
||||
/* Reset it before we get the interrupt */
|
||||
hermes_init(hw);
|
||||
hw->ops->init(hw);
|
||||
|
||||
if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
|
||||
printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
|
||||
@ -210,7 +210,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
|
||||
}
|
||||
|
||||
/* Register an interface with the stack */
|
||||
if (orinoco_if_add(priv, phys_addr, card->irq) != 0) {
|
||||
if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto failed;
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
|
||||
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
||||
/* Fast channel change - no commit if successful */
|
||||
hermes_t *hw = &priv->hw;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_SET_CHANNEL,
|
||||
channel, NULL);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
|
||||
|
||||
/* Read current plug data */
|
||||
err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
|
||||
err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
|
||||
dev_dbg(dev, "Read PDA returned %d\n", err);
|
||||
if (err)
|
||||
goto free;
|
||||
@ -149,7 +149,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
}
|
||||
|
||||
/* Enable aux port to allow programming */
|
||||
err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
|
||||
err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point));
|
||||
dev_dbg(dev, "Program init returned %d\n", err);
|
||||
if (err != 0)
|
||||
goto abort;
|
||||
@ -177,7 +177,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
|
||||
goto abort;
|
||||
|
||||
/* Tell card we've finished */
|
||||
err = hermesi_program_end(hw);
|
||||
err = hw->ops->program_end(hw);
|
||||
dev_dbg(dev, "Program end returned %d\n", err);
|
||||
if (err != 0)
|
||||
goto abort;
|
||||
@ -224,7 +224,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
|
||||
if (!pda)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1);
|
||||
ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
|
||||
if (ret)
|
||||
goto free;
|
||||
}
|
||||
@ -260,7 +260,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
|
||||
}
|
||||
|
||||
/* Reset hermes chip and make sure it responds */
|
||||
ret = hermes_init(hw);
|
||||
ret = hw->ops->init(hw);
|
||||
|
||||
/* hermes_reset() should return 0 with the secondary firmware */
|
||||
if (secondary && ret != 0)
|
||||
|
@ -51,6 +51,26 @@
|
||||
#define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
|
||||
#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
|
||||
|
||||
/*
|
||||
* AUX port access. To unlock the AUX port write the access keys to the
|
||||
* PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
|
||||
* register. Then read it and make sure it's HERMES_AUX_ENABLED.
|
||||
*/
|
||||
#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
|
||||
#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
|
||||
#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
|
||||
#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
|
||||
|
||||
#define HERMES_AUX_PW0 0xFE01
|
||||
#define HERMES_AUX_PW1 0xDC23
|
||||
#define HERMES_AUX_PW2 0xBA45
|
||||
|
||||
/* HERMES_CMD_DOWNLD */
|
||||
#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
|
||||
|
||||
/*
|
||||
* Debugging helpers
|
||||
*/
|
||||
@ -70,6 +90,7 @@
|
||||
|
||||
#endif /* ! HERMES_DEBUG */
|
||||
|
||||
static const struct hermes_ops hermes_ops_local;
|
||||
|
||||
/*
|
||||
* Internal functions
|
||||
@ -111,9 +132,9 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
|
||||
*/
|
||||
|
||||
/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
|
||||
int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp)
|
||||
static int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp)
|
||||
{
|
||||
int err = 0;
|
||||
int k;
|
||||
@ -163,17 +184,18 @@ int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_doicmd_wait);
|
||||
|
||||
void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
|
||||
{
|
||||
hw->iobase = address;
|
||||
hw->reg_spacing = reg_spacing;
|
||||
hw->inten = 0x0;
|
||||
hw->eeprom_pda = false;
|
||||
hw->ops = &hermes_ops_local;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_struct_init);
|
||||
|
||||
int hermes_init(hermes_t *hw)
|
||||
static int hermes_init(hermes_t *hw)
|
||||
{
|
||||
u16 reg;
|
||||
int err = 0;
|
||||
@ -217,7 +239,6 @@ int hermes_init(hermes_t *hw)
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_init);
|
||||
|
||||
/* Issue a command to the chip, and (busy!) wait for it to
|
||||
* complete.
|
||||
@ -228,8 +249,8 @@ EXPORT_SYMBOL(hermes_init);
|
||||
* > 0 on error returned by the firmware
|
||||
*
|
||||
* Callable from any context, but locking is your problem. */
|
||||
int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp)
|
||||
static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp)
|
||||
{
|
||||
int err;
|
||||
int k;
|
||||
@ -291,9 +312,8 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_docmd_wait);
|
||||
|
||||
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
|
||||
static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
|
||||
{
|
||||
int err = 0;
|
||||
int k;
|
||||
@ -333,7 +353,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_allocate);
|
||||
|
||||
/* Set up a BAP to read a particular chunk of data from card's internal buffer.
|
||||
*
|
||||
@ -403,8 +422,8 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
|
||||
* 0 on success
|
||||
* > 0 on error from firmware
|
||||
*/
|
||||
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
{
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
int err = 0;
|
||||
@ -422,7 +441,6 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_bap_pread);
|
||||
|
||||
/* Write a block of data to the chip's buffer, via the
|
||||
* BAP. Synchronization/serialization is the caller's problem.
|
||||
@ -432,8 +450,8 @@ EXPORT_SYMBOL(hermes_bap_pread);
|
||||
* 0 on success
|
||||
* > 0 on error from firmware
|
||||
*/
|
||||
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
u16 id, u16 offset)
|
||||
{
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
int err = 0;
|
||||
@ -451,7 +469,6 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_bap_pwrite);
|
||||
|
||||
/* Read a Length-Type-Value record from the card.
|
||||
*
|
||||
@ -461,8 +478,8 @@ EXPORT_SYMBOL(hermes_bap_pwrite);
|
||||
* practice.
|
||||
*
|
||||
* Callable from user or bh context. */
|
||||
int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
|
||||
u16 *length, void *buf)
|
||||
static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
|
||||
u16 *length, void *buf)
|
||||
{
|
||||
int err = 0;
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
@ -505,10 +522,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_read_ltv);
|
||||
|
||||
int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
u16 length, const void *value)
|
||||
static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
u16 length, const void *value)
|
||||
{
|
||||
int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
|
||||
int err = 0;
|
||||
@ -533,4 +549,228 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(hermes_write_ltv);
|
||||
|
||||
/*** Hermes AUX control ***/
|
||||
|
||||
static inline void
|
||||
hermes_aux_setaddr(hermes_t *hw, u32 addr)
|
||||
{
|
||||
hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
|
||||
hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
|
||||
}
|
||||
|
||||
static inline int
|
||||
hermes_aux_control(hermes_t *hw, int enabled)
|
||||
{
|
||||
int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
|
||||
int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
|
||||
int i;
|
||||
|
||||
/* Already open? */
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
|
||||
return 0;
|
||||
|
||||
hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
|
||||
hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
|
||||
hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
|
||||
hermes_write_reg(hw, HERMES_CONTROL, action);
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
udelay(10);
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) ==
|
||||
desired_state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*** Hermes programming ***/
|
||||
|
||||
/* About to start programming data (Hermes I)
|
||||
* offset is the entry point
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
static int hermesi_program_init(hermes_t *hw, u32 offset)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Disable interrupts?*/
|
||||
/*hw->inten = 0x0;*/
|
||||
/*hermes_write_regn(hw, INTEN, 0);*/
|
||||
/*hermes_set_irqmask(hw, 0);*/
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Using init_cmd_wait rather than cmd_wait */
|
||||
err = hw->ops->init_cmd_wait(hw,
|
||||
0x0100 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hw->ops->init_cmd_wait(hw,
|
||||
0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hermes_aux_control(hw, 1);
|
||||
pr_debug("AUX enable returned %d\n", err);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pr_debug("Enabling volatile, EP 0x%08x\n", offset);
|
||||
err = hw->ops->init_cmd_wait(hw,
|
||||
HERMES_PROGRAM_ENABLE_VOLATILE,
|
||||
offset & 0xFFFFu,
|
||||
offset >> 16,
|
||||
0,
|
||||
NULL);
|
||||
pr_debug("PROGRAM_ENABLE returned %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Done programming data (Hermes I)
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
static int hermesi_program_end(hermes_t *hw)
|
||||
{
|
||||
struct hermes_response resp;
|
||||
int rc = 0;
|
||||
int err;
|
||||
|
||||
rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
|
||||
|
||||
pr_debug("PROGRAM_DISABLE returned %d, "
|
||||
"r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
|
||||
rc, resp.resp0, resp.resp1, resp.resp2);
|
||||
|
||||
if ((rc == 0) &&
|
||||
((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
|
||||
rc = -EIO;
|
||||
|
||||
err = hermes_aux_control(hw, 0);
|
||||
pr_debug("AUX disable returned %d\n", err);
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Reinitialise, ignoring return */
|
||||
(void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
|
||||
return rc ? rc : err;
|
||||
}
|
||||
|
||||
static int hermes_program_bytes(struct hermes *hw, const char *data,
|
||||
u32 addr, u32 len)
|
||||
{
|
||||
/* wl lkm splits the programming into chunks of 2000 bytes.
|
||||
* This restriction appears to come from USB. The PCMCIA
|
||||
* adapters can program the whole lot in one go */
|
||||
hermes_aux_setaddr(hw, addr);
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read PDA from the adapter */
|
||||
static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len)
|
||||
{
|
||||
int ret;
|
||||
u16 pda_size;
|
||||
u16 data_len = pda_len;
|
||||
__le16 *data = pda;
|
||||
|
||||
if (hw->eeprom_pda) {
|
||||
/* PDA of spectrum symbol is in eeprom */
|
||||
|
||||
/* Issue command to read EEPROM */
|
||||
ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* wl_lkm does not include PDA size in the PDA area.
|
||||
* We will pad the information into pda, so other routines
|
||||
* don't have to be modified */
|
||||
pda[0] = cpu_to_le16(pda_len - 2);
|
||||
/* Includes CFG_PROD_DATA but not itself */
|
||||
pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
|
||||
data_len = pda_len - 4;
|
||||
data = pda + 2;
|
||||
}
|
||||
|
||||
/* Open auxiliary port */
|
||||
ret = hermes_aux_control(hw, 1);
|
||||
pr_debug("AUX enable returned %d\n", ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Read PDA */
|
||||
hermes_aux_setaddr(hw, pda_addr);
|
||||
hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
|
||||
|
||||
/* Close aux port */
|
||||
ret = hermes_aux_control(hw, 0);
|
||||
pr_debug("AUX disable returned %d\n", ret);
|
||||
|
||||
/* Check PDA length */
|
||||
pda_size = le16_to_cpu(pda[0]);
|
||||
pr_debug("Actual PDA length %d, Max allowed %d\n",
|
||||
pda_size, pda_len);
|
||||
if (pda_size > pda_len)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hermes_lock_irqsave(spinlock_t *lock,
|
||||
unsigned long *flags) __acquires(lock)
|
||||
{
|
||||
spin_lock_irqsave(lock, *flags);
|
||||
}
|
||||
|
||||
static void hermes_unlock_irqrestore(spinlock_t *lock,
|
||||
unsigned long *flags) __releases(lock)
|
||||
{
|
||||
spin_unlock_irqrestore(lock, *flags);
|
||||
}
|
||||
|
||||
static void hermes_lock_irq(spinlock_t *lock) __acquires(lock)
|
||||
{
|
||||
spin_lock_irq(lock);
|
||||
}
|
||||
|
||||
static void hermes_unlock_irq(spinlock_t *lock) __releases(lock)
|
||||
{
|
||||
spin_unlock_irq(lock);
|
||||
}
|
||||
|
||||
/* Hermes operations for local buses */
|
||||
static const struct hermes_ops hermes_ops_local = {
|
||||
.init = hermes_init,
|
||||
.cmd_wait = hermes_docmd_wait,
|
||||
.init_cmd_wait = hermes_doicmd_wait,
|
||||
.allocate = hermes_allocate,
|
||||
.read_ltv = hermes_read_ltv,
|
||||
.write_ltv = hermes_write_ltv,
|
||||
.bap_pread = hermes_bap_pread,
|
||||
.bap_pwrite = hermes_bap_pwrite,
|
||||
.read_pda = hermes_read_pda,
|
||||
.program_init = hermesi_program_init,
|
||||
.program_end = hermesi_program_end,
|
||||
.program = hermes_program_bytes,
|
||||
.lock_irqsave = hermes_lock_irqsave,
|
||||
.unlock_irqrestore = hermes_unlock_irqrestore,
|
||||
.lock_irq = hermes_lock_irq,
|
||||
.unlock_irq = hermes_unlock_irq,
|
||||
};
|
||||
|
@ -374,6 +374,37 @@ struct hermes_multicast {
|
||||
/* Timeouts */
|
||||
#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
|
||||
|
||||
struct hermes;
|
||||
|
||||
/* Functions to access hardware */
|
||||
struct hermes_ops {
|
||||
int (*init)(struct hermes *hw);
|
||||
int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp);
|
||||
int (*init_cmd_wait)(struct hermes *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp);
|
||||
int (*allocate)(struct hermes *hw, u16 size, u16 *fid);
|
||||
int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen,
|
||||
u16 *length, void *buf);
|
||||
int (*write_ltv)(struct hermes *hw, int bap, u16 rid,
|
||||
u16 length, const void *value);
|
||||
int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset);
|
||||
int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf,
|
||||
int len, u16 id, u16 offset);
|
||||
int (*read_pda)(struct hermes *hw, __le16 *pda,
|
||||
u32 pda_addr, u16 pda_len);
|
||||
int (*program_init)(struct hermes *hw, u32 entry_point);
|
||||
int (*program_end)(struct hermes *hw);
|
||||
int (*program)(struct hermes *hw, const char *buf,
|
||||
u32 addr, u32 len);
|
||||
void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags);
|
||||
void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags);
|
||||
void (*lock_irq)(spinlock_t *lock);
|
||||
void (*unlock_irq)(spinlock_t *lock);
|
||||
};
|
||||
|
||||
/* Basic control structure */
|
||||
typedef struct hermes {
|
||||
void __iomem *iobase;
|
||||
@ -381,6 +412,9 @@ typedef struct hermes {
|
||||
#define HERMES_16BIT_REGSPACING 0
|
||||
#define HERMES_32BIT_REGSPACING 1
|
||||
u16 inten; /* Which interrupts should be enabled? */
|
||||
bool eeprom_pda;
|
||||
const struct hermes_ops *ops;
|
||||
void *priv;
|
||||
} hermes_t;
|
||||
|
||||
/* Register access convenience macros */
|
||||
@ -394,22 +428,6 @@ typedef struct hermes {
|
||||
|
||||
/* Function prototypes */
|
||||
void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
|
||||
int hermes_init(hermes_t *hw);
|
||||
int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
|
||||
struct hermes_response *resp);
|
||||
int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
|
||||
u16 parm0, u16 parm1, u16 parm2,
|
||||
struct hermes_response *resp);
|
||||
int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
|
||||
|
||||
int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
|
||||
u16 id, u16 offset);
|
||||
int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
|
||||
u16 id, u16 offset);
|
||||
int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
|
||||
u16 *length, void *buf);
|
||||
int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
|
||||
u16 length, const void *value);
|
||||
|
||||
/* Inline functions */
|
||||
|
||||
@ -426,13 +444,13 @@ static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
|
||||
|
||||
static inline int hermes_enable_port(hermes_t *hw, int port)
|
||||
{
|
||||
return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
|
||||
return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
static inline int hermes_disable_port(hermes_t *hw, int port)
|
||||
{
|
||||
return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
|
||||
return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
|
||||
0, NULL);
|
||||
}
|
||||
|
||||
@ -440,7 +458,7 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
|
||||
* information frame in __orinoco_ev_info() */
|
||||
static inline int hermes_inquire(hermes_t *hw, u16 rid)
|
||||
{
|
||||
return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
|
||||
return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
|
||||
}
|
||||
|
||||
#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1)
|
||||
@ -475,10 +493,10 @@ static inline void hermes_clear_words(struct hermes *hw, int off,
|
||||
}
|
||||
|
||||
#define HERMES_READ_RECORD(hw, bap, rid, buf) \
|
||||
(hermes_read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
|
||||
(hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
|
||||
#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
|
||||
(hermes_write_ltv((hw), (bap), (rid), \
|
||||
HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
|
||||
(hw->ops->write_ltv((hw), (bap), (rid), \
|
||||
HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
|
||||
|
||||
static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
|
||||
{
|
||||
|
@ -46,37 +46,11 @@
|
||||
|
||||
#define PFX "hermes_dld: "
|
||||
|
||||
/*
|
||||
* AUX port access. To unlock the AUX port write the access keys to the
|
||||
* PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
|
||||
* register. Then read it and make sure it's HERMES_AUX_ENABLED.
|
||||
*/
|
||||
#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
|
||||
#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
|
||||
#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
|
||||
#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
|
||||
|
||||
#define HERMES_AUX_PW0 0xFE01
|
||||
#define HERMES_AUX_PW1 0xDC23
|
||||
#define HERMES_AUX_PW2 0xBA45
|
||||
|
||||
/* HERMES_CMD_DOWNLD */
|
||||
#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
|
||||
#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
|
||||
|
||||
/* End markers used in dblocks */
|
||||
#define PDI_END 0x00000000 /* End of PDA */
|
||||
#define BLOCK_END 0xFFFFFFFF /* Last image block */
|
||||
#define TEXT_END 0x1A /* End of text header */
|
||||
|
||||
/* Limit the amout we try to download in a single shot.
|
||||
* Size is in bytes.
|
||||
*/
|
||||
#define MAX_DL_SIZE 1024
|
||||
#define LIMIT_PROGRAM_SIZE 0
|
||||
|
||||
/*
|
||||
* The following structures have little-endian fields denoted by
|
||||
* the leading underscore. Don't access them directly - use inline
|
||||
@ -165,41 +139,6 @@ pdi_len(const struct pdi *pdi)
|
||||
return 2 * (le16_to_cpu(pdi->len) - 1);
|
||||
}
|
||||
|
||||
/*** Hermes AUX control ***/
|
||||
|
||||
static inline void
|
||||
hermes_aux_setaddr(hermes_t *hw, u32 addr)
|
||||
{
|
||||
hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
|
||||
hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
|
||||
}
|
||||
|
||||
static inline int
|
||||
hermes_aux_control(hermes_t *hw, int enabled)
|
||||
{
|
||||
int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
|
||||
int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
|
||||
int i;
|
||||
|
||||
/* Already open? */
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
|
||||
return 0;
|
||||
|
||||
hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
|
||||
hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
|
||||
hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
|
||||
hermes_write_reg(hw, HERMES_CONTROL, action);
|
||||
|
||||
for (i = 0; i < 20; i++) {
|
||||
udelay(10);
|
||||
if (hermes_read_reg(hw, HERMES_CONTROL) ==
|
||||
desired_state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*** Plug Data Functions ***/
|
||||
|
||||
/*
|
||||
@ -271,62 +210,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
|
||||
return -EINVAL;
|
||||
|
||||
/* do the actual plugging */
|
||||
hermes_aux_setaddr(hw, pdr_addr(pdr));
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read PDA from the adapter */
|
||||
int hermes_read_pda(hermes_t *hw,
|
||||
__le16 *pda,
|
||||
u32 pda_addr,
|
||||
u16 pda_len,
|
||||
int use_eeprom) /* can we get this into hw? */
|
||||
{
|
||||
int ret;
|
||||
u16 pda_size;
|
||||
u16 data_len = pda_len;
|
||||
__le16 *data = pda;
|
||||
|
||||
if (use_eeprom) {
|
||||
/* PDA of spectrum symbol is in eeprom */
|
||||
|
||||
/* Issue command to read EEPROM */
|
||||
ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* wl_lkm does not include PDA size in the PDA area.
|
||||
* We will pad the information into pda, so other routines
|
||||
* don't have to be modified */
|
||||
pda[0] = cpu_to_le16(pda_len - 2);
|
||||
/* Includes CFG_PROD_DATA but not itself */
|
||||
pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
|
||||
data_len = pda_len - 4;
|
||||
data = pda + 2;
|
||||
}
|
||||
|
||||
/* Open auxiliary port */
|
||||
ret = hermes_aux_control(hw, 1);
|
||||
pr_debug(PFX "AUX enable returned %d\n", ret);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* read PDA from EEPROM */
|
||||
hermes_aux_setaddr(hw, pda_addr);
|
||||
hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
|
||||
|
||||
/* Close aux port */
|
||||
ret = hermes_aux_control(hw, 0);
|
||||
pr_debug(PFX "AUX disable returned %d\n", ret);
|
||||
|
||||
/* Check PDA length */
|
||||
pda_size = le16_to_cpu(pda[0]);
|
||||
pr_debug(PFX "Actual PDA length %d, Max allowed %d\n",
|
||||
pda_size, pda_len);
|
||||
if (pda_size > pda_len)
|
||||
return -EINVAL;
|
||||
hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -389,101 +273,13 @@ hermes_blocks_length(const char *first_block, const void *end)
|
||||
|
||||
/*** Hermes programming ***/
|
||||
|
||||
/* About to start programming data (Hermes I)
|
||||
* offset is the entry point
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
int hermesi_program_init(hermes_t *hw, u32 offset)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* Disable interrupts?*/
|
||||
/*hw->inten = 0x0;*/
|
||||
/*hermes_write_regn(hw, INTEN, 0);*/
|
||||
/*hermes_set_irqmask(hw, 0);*/
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Using doicmd_wait rather than docmd_wait */
|
||||
err = hermes_doicmd_wait(hw,
|
||||
0x0100 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hermes_doicmd_wait(hw,
|
||||
0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = hermes_aux_control(hw, 1);
|
||||
pr_debug(PFX "AUX enable returned %d\n", err);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset);
|
||||
err = hermes_doicmd_wait(hw,
|
||||
HERMES_PROGRAM_ENABLE_VOLATILE,
|
||||
offset & 0xFFFFu,
|
||||
offset >> 16,
|
||||
0,
|
||||
NULL);
|
||||
pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Done programming data (Hermes I)
|
||||
*
|
||||
* Spectrum_cs' Symbol fw does not require this
|
||||
* wl_lkm Agere fw does
|
||||
* Don't know about intersil
|
||||
*/
|
||||
int hermesi_program_end(hermes_t *hw)
|
||||
{
|
||||
struct hermes_response resp;
|
||||
int rc = 0;
|
||||
int err;
|
||||
|
||||
rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
|
||||
|
||||
pr_debug(PFX "PROGRAM_DISABLE returned %d, "
|
||||
"r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
|
||||
rc, resp.resp0, resp.resp1, resp.resp2);
|
||||
|
||||
if ((rc == 0) &&
|
||||
((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
|
||||
rc = -EIO;
|
||||
|
||||
err = hermes_aux_control(hw, 0);
|
||||
pr_debug(PFX "AUX disable returned %d\n", err);
|
||||
|
||||
/* Acknowledge any outstanding command */
|
||||
hermes_write_regn(hw, EVACK, 0xFFFF);
|
||||
|
||||
/* Reinitialise, ignoring return */
|
||||
(void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
|
||||
0, 0, 0, NULL);
|
||||
|
||||
return rc ? rc : err;
|
||||
}
|
||||
|
||||
/* Program the data blocks */
|
||||
int hermes_program(hermes_t *hw, const char *first_block, const void *end)
|
||||
{
|
||||
const struct dblock *blk;
|
||||
u32 blkaddr;
|
||||
u32 blklen;
|
||||
#if LIMIT_PROGRAM_SIZE
|
||||
u32 addr;
|
||||
u32 len;
|
||||
#endif
|
||||
int err = 0;
|
||||
|
||||
blk = (const struct dblock *) first_block;
|
||||
|
||||
@ -498,30 +294,10 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
|
||||
pr_debug(PFX "Programming block of length %d "
|
||||
"to address 0x%08x\n", blklen, blkaddr);
|
||||
|
||||
#if !LIMIT_PROGRAM_SIZE
|
||||
/* wl_lkm driver splits this into writes of 2000 bytes */
|
||||
hermes_aux_setaddr(hw, blkaddr);
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
|
||||
blklen);
|
||||
#else
|
||||
len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE;
|
||||
addr = blkaddr;
|
||||
err = hw->ops->program(hw, blk->data, blkaddr, blklen);
|
||||
if (err)
|
||||
break;
|
||||
|
||||
while (addr < (blkaddr + blklen)) {
|
||||
pr_debug(PFX "Programming subblock of length %d "
|
||||
"to address 0x%08x. Data @ %p\n",
|
||||
len, addr, &blk->data[addr - blkaddr]);
|
||||
|
||||
hermes_aux_setaddr(hw, addr);
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA,
|
||||
&blk->data[addr - blkaddr],
|
||||
len);
|
||||
|
||||
addr += len;
|
||||
len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ?
|
||||
(blkaddr + blklen - addr) : MAX_DL_SIZE;
|
||||
}
|
||||
#endif
|
||||
blk = (const struct dblock *) &blk->data[blklen];
|
||||
|
||||
if ((void *) blk > (end - sizeof(*blk)))
|
||||
@ -530,7 +306,7 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
|
||||
blkaddr = dblock_addr(blk);
|
||||
blklen = dblock_len(blk);
|
||||
}
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
/*** Default plugging data for Hermes I ***/
|
||||
@ -690,9 +466,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
|
||||
if ((pdi_len(pdi) == pdr_len(pdr)) &&
|
||||
((void *) pdi->data + pdi_len(pdi) < pda_end)) {
|
||||
/* do the actual plugging */
|
||||
hermes_aux_setaddr(hw, pdr_addr(pdr));
|
||||
hermes_write_bytes(hw, HERMES_AUXDATA,
|
||||
pdi->data, pdi_len(pdi));
|
||||
hw->ops->program(hw, pdi->data, pdr_addr(pdr),
|
||||
pdi_len(pdi));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,9 +177,9 @@ int determine_fw_capabilities(struct orinoco_private *priv,
|
||||
/* 3Com MAC : 00:50:DA:* */
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
/* Get the Symbol firmware version */
|
||||
err = hermes_read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SECONDARYVERSION_SYMBOL,
|
||||
SYMBOL_MAX_VER_LEN, NULL, &tmp);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SECONDARYVERSION_SYMBOL,
|
||||
SYMBOL_MAX_VER_LEN, NULL, &tmp);
|
||||
if (err) {
|
||||
dev_warn(dev, "Error %d reading Symbol firmware info. "
|
||||
"Wildly guessing capabilities...\n", err);
|
||||
@ -286,8 +286,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
|
||||
u16 reclen;
|
||||
|
||||
/* Get the MAC address */
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
ETH_ALEN, NULL, dev_addr);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
ETH_ALEN, NULL, dev_addr);
|
||||
if (err) {
|
||||
dev_warn(dev, "Failed to read MAC address!\n");
|
||||
goto out;
|
||||
@ -296,8 +296,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
|
||||
dev_dbg(dev, "MAC address %pM\n", dev_addr);
|
||||
|
||||
/* Get the station name */
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
sizeof(nickbuf), &reclen, &nickbuf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
sizeof(nickbuf), &reclen, &nickbuf);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to read station name\n");
|
||||
goto out;
|
||||
@ -413,11 +413,11 @@ int orinoco_hw_allocate_fid(struct orinoco_private *priv)
|
||||
struct hermes *hw = &priv->hw;
|
||||
int err;
|
||||
|
||||
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
|
||||
/* Try workaround for old Symbol firmware bug */
|
||||
priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
|
||||
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
|
||||
|
||||
dev_warn(dev, "Firmware ALLOC bug detected "
|
||||
"(old Symbol firmware?). Work around %s\n",
|
||||
@ -463,8 +463,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
struct hermes_idstring idbuf;
|
||||
|
||||
/* Set the MAC address */
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
|
||||
HERMES_BYTES_TO_RECLEN(ETH_ALEN),
|
||||
dev->dev_addr);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d setting MAC address\n",
|
||||
dev->name, err);
|
||||
@ -527,7 +528,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
|
||||
memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
|
||||
/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
|
||||
&idbuf);
|
||||
if (err) {
|
||||
@ -535,7 +536,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
dev->name, err);
|
||||
return err;
|
||||
}
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
|
||||
&idbuf);
|
||||
if (err) {
|
||||
@ -547,9 +548,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
/* Set the station name */
|
||||
idbuf.len = cpu_to_le16(strlen(priv->nick));
|
||||
memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
|
||||
err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
|
||||
&idbuf);
|
||||
err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
|
||||
HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
|
||||
&idbuf);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d setting nickname\n",
|
||||
dev->name, err);
|
||||
@ -664,12 +665,12 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
|
||||
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
||||
/* Enable monitor mode */
|
||||
dev->type = ARPHRD_IEEE80211;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_MONITOR, 0, NULL);
|
||||
} else {
|
||||
/* Disable monitor mode */
|
||||
dev->type = ARPHRD_ETHER;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_STOP, 0, NULL);
|
||||
}
|
||||
if (err)
|
||||
@ -695,8 +696,8 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
|
||||
if ((key < 0) || (key >= 4))
|
||||
return -EINVAL;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
|
||||
sizeof(tsc_arr), NULL, &tsc_arr);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
|
||||
sizeof(tsc_arr), NULL, &tsc_arr);
|
||||
if (!err)
|
||||
memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
|
||||
|
||||
@ -875,7 +876,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
|
||||
memcpy(key, priv->keys[i].key,
|
||||
priv->keys[i].key_len);
|
||||
|
||||
err = hermes_write_ltv(hw, USER_BAP,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CNFDEFAULTKEY0 + i,
|
||||
HERMES_BYTES_TO_RECLEN(keylen),
|
||||
key);
|
||||
@ -1092,7 +1093,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
|
||||
memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
err = hermes_write_ltv(hw, USER_BAP,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CNFGROUPADDRESSES,
|
||||
HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
|
||||
&mclist);
|
||||
@ -1134,15 +1135,15 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
|
||||
rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
|
||||
HERMES_RID_CNFDESIREDSSID;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
|
||||
NULL, &essidbuf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
|
||||
NULL, &essidbuf);
|
||||
if (err)
|
||||
goto fail_unlock;
|
||||
} else {
|
||||
*active = 0;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
|
||||
sizeof(essidbuf), NULL, &essidbuf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
|
||||
sizeof(essidbuf), NULL, &essidbuf);
|
||||
if (err)
|
||||
goto fail_unlock;
|
||||
}
|
||||
@ -1213,8 +1214,8 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
|
||||
sizeof(list), NULL, &list);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
|
||||
sizeof(list), NULL, &list);
|
||||
orinoco_unlock(priv, &flags);
|
||||
|
||||
if (err)
|
||||
@ -1281,7 +1282,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
|
||||
idbuf.len = cpu_to_le16(len);
|
||||
memcpy(idbuf.val, ssid->ssid, len);
|
||||
|
||||
err = hermes_write_ltv(hw, USER_BAP,
|
||||
err = hw->ops->write_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CNFSCANSSID_AGERE,
|
||||
HERMES_BYTES_TO_RECLEN(len + 2),
|
||||
&idbuf);
|
||||
@ -1345,8 +1346,8 @@ int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
|
||||
hermes_t *hw = &priv->hw;
|
||||
int err;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, addr);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, addr);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -254,7 +254,7 @@ void set_port_type(struct orinoco_private *priv)
|
||||
/* Device methods */
|
||||
/********************************************************************/
|
||||
|
||||
static int orinoco_open(struct net_device *dev)
|
||||
int orinoco_open(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
unsigned long flags;
|
||||
@ -272,8 +272,9 @@ static int orinoco_open(struct net_device *dev)
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_open);
|
||||
|
||||
static int orinoco_stop(struct net_device *dev)
|
||||
int orinoco_stop(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
int err = 0;
|
||||
@ -281,25 +282,27 @@ static int orinoco_stop(struct net_device *dev)
|
||||
/* We mustn't use orinoco_lock() here, because we need to be
|
||||
able to close the interface even if hw_unavailable is set
|
||||
(e.g. as we're released after a PC Card removal) */
|
||||
spin_lock_irq(&priv->lock);
|
||||
orinoco_lock_irq(priv);
|
||||
|
||||
priv->open = 0;
|
||||
|
||||
err = __orinoco_down(priv);
|
||||
|
||||
spin_unlock_irq(&priv->lock);
|
||||
orinoco_unlock_irq(priv);
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_stop);
|
||||
|
||||
static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
|
||||
struct net_device_stats *orinoco_get_stats(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
|
||||
return &priv->stats;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_get_stats);
|
||||
|
||||
static void orinoco_set_multicast_list(struct net_device *dev)
|
||||
void orinoco_set_multicast_list(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
unsigned long flags;
|
||||
@ -313,8 +316,9 @@ static void orinoco_set_multicast_list(struct net_device *dev)
|
||||
__orinoco_set_multicast_list(dev);
|
||||
orinoco_unlock(priv, &flags);
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_set_multicast_list);
|
||||
|
||||
static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
|
||||
int orinoco_change_mtu(struct net_device *dev, int new_mtu)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
|
||||
@ -330,6 +334,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_change_mtu);
|
||||
|
||||
/********************************************************************/
|
||||
/* Tx path */
|
||||
@ -400,8 +405,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
*txcntl = cpu_to_le16(tx_control);
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
if (err) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_ERR "%s: Error %d writing Tx "
|
||||
@ -414,8 +419,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
memset(&desc, 0, sizeof(desc));
|
||||
|
||||
desc.tx_control = cpu_to_le16(tx_control);
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
|
||||
txfid, 0);
|
||||
if (err) {
|
||||
if (net_ratelimit())
|
||||
printk(KERN_ERR "%s: Error %d writing Tx "
|
||||
@ -458,8 +463,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
memcpy(eh, &hdr, sizeof(hdr));
|
||||
}
|
||||
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
|
||||
txfid, HERMES_802_3_OFFSET);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len,
|
||||
txfid, HERMES_802_3_OFFSET);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
|
||||
dev->name, err);
|
||||
@ -490,8 +495,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
|
||||
|
||||
/* Write the MIC */
|
||||
err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
|
||||
txfid, HERMES_802_3_OFFSET + offset);
|
||||
err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
|
||||
txfid, HERMES_802_3_OFFSET + offset);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
|
||||
dev->name, err);
|
||||
@ -502,7 +507,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
/* Finally, we actually initiate the send */
|
||||
netif_stop_queue(dev);
|
||||
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
|
||||
txfid, NULL);
|
||||
if (err) {
|
||||
netif_start_queue(dev);
|
||||
@ -572,9 +577,9 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
|
||||
return; /* Nothing's really happened */
|
||||
|
||||
/* Read part of the frame header - we need status and addr1 */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
|
||||
sizeof(struct hermes_txexc_data),
|
||||
fid, 0);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr,
|
||||
sizeof(struct hermes_txexc_data),
|
||||
fid, 0);
|
||||
|
||||
hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
|
||||
stats->tx_errors++;
|
||||
@ -615,7 +620,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
|
||||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
static void orinoco_tx_timeout(struct net_device *dev)
|
||||
void orinoco_tx_timeout(struct net_device *dev)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
struct net_device_stats *stats = &priv->stats;
|
||||
@ -630,6 +635,7 @@ static void orinoco_tx_timeout(struct net_device *dev)
|
||||
|
||||
schedule_work(&priv->reset_work);
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_tx_timeout);
|
||||
|
||||
/********************************************************************/
|
||||
/* Rx path (data frames) */
|
||||
@ -764,9 +770,9 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
|
||||
|
||||
/* If any, copy the data from the card to the skb */
|
||||
if (datalen > 0) {
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
|
||||
ALIGN(datalen, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
|
||||
ALIGN(datalen, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading monitor frame\n",
|
||||
dev->name, err);
|
||||
@ -792,7 +798,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
|
||||
stats->rx_dropped++;
|
||||
}
|
||||
|
||||
static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
struct net_device_stats *stats = &priv->stats;
|
||||
@ -814,8 +820,8 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
|
||||
rxfid = hermes_read_regn(hw, RXFID);
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
|
||||
rxfid, 0);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
|
||||
rxfid, 0);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading Rx descriptor. "
|
||||
"Frame dropped.\n", dev->name, err);
|
||||
@ -882,9 +888,9 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
|
||||
nothing is removed. 2 is for aligning the IP header. */
|
||||
skb_reserve(skb, ETH_HLEN + 2);
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
|
||||
ALIGN(length, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length),
|
||||
ALIGN(length, 2), rxfid,
|
||||
HERMES_802_2_OFFSET);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading frame. "
|
||||
"Frame dropped.\n", dev->name, err);
|
||||
@ -913,6 +919,7 @@ update_stats:
|
||||
out:
|
||||
kfree(desc);
|
||||
}
|
||||
EXPORT_SYMBOL(__orinoco_ev_rx);
|
||||
|
||||
static void orinoco_rx(struct net_device *dev,
|
||||
struct hermes_rx_descriptor *desc,
|
||||
@ -1145,9 +1152,9 @@ static void orinoco_join_ap(struct work_struct *work)
|
||||
goto out;
|
||||
|
||||
/* Read scan results from the firmware */
|
||||
err = hermes_read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SCANRESULTSTABLE,
|
||||
MAX_SCAN_LEN, &len, buf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_SCANRESULTSTABLE,
|
||||
MAX_SCAN_LEN, &len, buf);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: Cannot read scan results\n",
|
||||
dev->name);
|
||||
@ -1194,8 +1201,8 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
|
||||
union iwreq_data wrqu;
|
||||
int err;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
|
||||
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
|
||||
if (err != 0)
|
||||
return;
|
||||
|
||||
@ -1217,8 +1224,8 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
|
||||
if (!priv->has_wpa)
|
||||
return;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
if (err != 0)
|
||||
return;
|
||||
|
||||
@ -1247,8 +1254,9 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
|
||||
if (!priv->has_wpa)
|
||||
return;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP,
|
||||
HERMES_RID_CURRENT_ASSOC_RESP_INFO,
|
||||
sizeof(buf), NULL, &buf);
|
||||
if (err != 0)
|
||||
return;
|
||||
|
||||
@ -1353,7 +1361,7 @@ static void orinoco_process_scan_results(struct work_struct *work)
|
||||
spin_unlock_irqrestore(&priv->scan_lock, flags);
|
||||
}
|
||||
|
||||
static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
u16 infofid;
|
||||
@ -1371,8 +1379,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
infofid = hermes_read_regn(hw, INFOFID);
|
||||
|
||||
/* Read the info frame header - don't try too hard */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
|
||||
infofid, 0);
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info),
|
||||
infofid, 0);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: error %d reading info frame. "
|
||||
"Frame dropped.\n", dev->name, err);
|
||||
@ -1393,8 +1401,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
len = sizeof(tallies);
|
||||
}
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len,
|
||||
infofid, sizeof(info));
|
||||
if (err)
|
||||
break;
|
||||
|
||||
@ -1429,8 +1437,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
break;
|
||||
}
|
||||
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len,
|
||||
infofid, sizeof(info));
|
||||
if (err)
|
||||
break;
|
||||
newstatus = le16_to_cpu(linkstatus.linkstatus);
|
||||
@ -1494,8 +1502,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
}
|
||||
|
||||
/* Read scan data */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len,
|
||||
infofid, sizeof(info));
|
||||
if (err) {
|
||||
kfree(buf);
|
||||
qabort_scan(priv);
|
||||
@ -1547,8 +1555,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
break;
|
||||
|
||||
/* Read scan data */
|
||||
err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
|
||||
infofid, sizeof(info));
|
||||
err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len,
|
||||
infofid, sizeof(info));
|
||||
if (err)
|
||||
kfree(bss);
|
||||
else
|
||||
@ -1571,6 +1579,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
|
||||
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(__orinoco_ev_info);
|
||||
|
||||
static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
|
||||
{
|
||||
@ -1647,7 +1656,7 @@ static int orinoco_reinit_firmware(struct orinoco_private *priv)
|
||||
struct hermes *hw = &priv->hw;
|
||||
int err;
|
||||
|
||||
err = hermes_init(hw);
|
||||
err = hw->ops->init(hw);
|
||||
if (priv->do_fw_download && !err) {
|
||||
err = orinoco_download(priv);
|
||||
if (err)
|
||||
@ -1735,7 +1744,7 @@ void orinoco_reset(struct work_struct *work)
|
||||
}
|
||||
|
||||
/* This has to be called from user context */
|
||||
spin_lock_irq(&priv->lock);
|
||||
orinoco_lock_irq(priv);
|
||||
|
||||
priv->hw_unavailable--;
|
||||
|
||||
@ -1750,7 +1759,7 @@ void orinoco_reset(struct work_struct *work)
|
||||
dev->trans_start = jiffies;
|
||||
}
|
||||
|
||||
spin_unlock_irq(&priv->lock);
|
||||
orinoco_unlock_irq(priv);
|
||||
|
||||
return;
|
||||
disable:
|
||||
@ -1984,7 +1993,7 @@ int orinoco_init(struct orinoco_private *priv)
|
||||
priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
|
||||
|
||||
/* Initialize the firmware */
|
||||
err = hermes_init(hw);
|
||||
err = hw->ops->init(hw);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "Failed to initialize firmware (err = %d)\n",
|
||||
err);
|
||||
@ -2067,9 +2076,9 @@ int orinoco_init(struct orinoco_private *priv)
|
||||
|
||||
/* Make the hardware available, as long as it hasn't been
|
||||
* removed elsewhere (e.g. by PCMCIA hot unplug) */
|
||||
spin_lock_irq(&priv->lock);
|
||||
orinoco_lock_irq(priv);
|
||||
priv->hw_unavailable--;
|
||||
spin_unlock_irq(&priv->lock);
|
||||
orinoco_unlock_irq(priv);
|
||||
|
||||
dev_dbg(dev, "Ready\n");
|
||||
|
||||
@ -2192,7 +2201,8 @@ EXPORT_SYMBOL(alloc_orinocodev);
|
||||
*/
|
||||
int orinoco_if_add(struct orinoco_private *priv,
|
||||
unsigned long base_addr,
|
||||
unsigned int irq)
|
||||
unsigned int irq,
|
||||
const struct net_device_ops *ops)
|
||||
{
|
||||
struct wiphy *wiphy = priv_to_wiphy(priv);
|
||||
struct wireless_dev *wdev;
|
||||
@ -2211,12 +2221,17 @@ int orinoco_if_add(struct orinoco_private *priv,
|
||||
|
||||
/* Setup / override net_device fields */
|
||||
dev->ieee80211_ptr = wdev;
|
||||
dev->netdev_ops = &orinoco_netdev_ops;
|
||||
dev->watchdog_timeo = HZ; /* 1 second timeout */
|
||||
dev->wireless_handlers = &orinoco_handler_def;
|
||||
#ifdef WIRELESS_SPY
|
||||
dev->wireless_data = &priv->wireless_data;
|
||||
#endif
|
||||
/* Default to standard ops if not set */
|
||||
if (ops)
|
||||
dev->netdev_ops = ops;
|
||||
else
|
||||
dev->netdev_ops = &orinoco_netdev_ops;
|
||||
|
||||
/* we use the default eth_mac_addr for setting the MAC addr */
|
||||
|
||||
/* Reserve space in skb for the SNAP header */
|
||||
@ -2305,7 +2320,7 @@ int orinoco_up(struct orinoco_private *priv)
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
|
||||
err = orinoco_reinit_firmware(priv);
|
||||
if (err) {
|
||||
@ -2325,7 +2340,7 @@ int orinoco_up(struct orinoco_private *priv)
|
||||
}
|
||||
|
||||
exit:
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2337,7 +2352,7 @@ void orinoco_down(struct orinoco_private *priv)
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
err = __orinoco_down(priv);
|
||||
if (err)
|
||||
printk(KERN_WARNING "%s: Error %d downing interface\n",
|
||||
@ -2345,7 +2360,7 @@ void orinoco_down(struct orinoco_private *priv)
|
||||
|
||||
netif_device_detach(dev);
|
||||
priv->hw_unavailable++;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
}
|
||||
EXPORT_SYMBOL(orinoco_down);
|
||||
|
||||
|
@ -190,12 +190,24 @@ extern void free_orinocodev(struct orinoco_private *priv);
|
||||
extern int orinoco_init(struct orinoco_private *priv);
|
||||
extern int orinoco_if_add(struct orinoco_private *priv,
|
||||
unsigned long base_addr,
|
||||
unsigned int irq);
|
||||
unsigned int irq,
|
||||
const struct net_device_ops *ops);
|
||||
extern void orinoco_if_del(struct orinoco_private *priv);
|
||||
extern int orinoco_up(struct orinoco_private *priv);
|
||||
extern void orinoco_down(struct orinoco_private *priv);
|
||||
extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
|
||||
|
||||
extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
|
||||
extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
|
||||
|
||||
/* Common ndo functions exported for reuse by orinoco_usb */
|
||||
int orinoco_open(struct net_device *dev);
|
||||
int orinoco_stop(struct net_device *dev);
|
||||
struct net_device_stats *orinoco_get_stats(struct net_device *dev);
|
||||
void orinoco_set_multicast_list(struct net_device *dev);
|
||||
int orinoco_change_mtu(struct net_device *dev, int new_mtu);
|
||||
void orinoco_tx_timeout(struct net_device *dev);
|
||||
|
||||
/********************************************************************/
|
||||
/* Locking and synchronization functions */
|
||||
/********************************************************************/
|
||||
@ -203,11 +215,11 @@ extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
|
||||
static inline int orinoco_lock(struct orinoco_private *priv,
|
||||
unsigned long *flags)
|
||||
{
|
||||
spin_lock_irqsave(&priv->lock, *flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, flags);
|
||||
if (priv->hw_unavailable) {
|
||||
DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
|
||||
priv->ndev);
|
||||
spin_unlock_irqrestore(&priv->lock, *flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
|
||||
return -EBUSY;
|
||||
}
|
||||
return 0;
|
||||
@ -216,7 +228,17 @@ static inline int orinoco_lock(struct orinoco_private *priv,
|
||||
static inline void orinoco_unlock(struct orinoco_private *priv,
|
||||
unsigned long *flags)
|
||||
{
|
||||
spin_unlock_irqrestore(&priv->lock, *flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static inline void orinoco_lock_irq(struct orinoco_private *priv)
|
||||
{
|
||||
priv->hw.ops->lock_irq(&priv->lock);
|
||||
}
|
||||
|
||||
static inline void orinoco_unlock_irq(struct orinoco_private *priv)
|
||||
{
|
||||
priv->hw.ops->unlock_irq(&priv->lock);
|
||||
}
|
||||
|
||||
/*** Navigate from net_device to orinoco_private ***/
|
||||
|
@ -296,7 +296,7 @@ orinoco_cs_config(struct pcmcia_device *link)
|
||||
|
||||
/* Register an interface with the stack */
|
||||
if (orinoco_if_add(priv, link->io.BasePort1,
|
||||
link->irq.AssignedIRQ) != 0) {
|
||||
link->irq.AssignedIRQ, NULL) != 0) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto failed;
|
||||
}
|
||||
@ -327,9 +327,9 @@ orinoco_cs_release(struct pcmcia_device *link)
|
||||
|
||||
/* We're committed to taking the device away now, so mark the
|
||||
* hardware as unavailable */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
priv->hw_unavailable++;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
pcmcia_disable_device(link);
|
||||
if (priv->hw.iobase)
|
||||
|
@ -220,7 +220,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
@ -170,7 +170,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
@ -259,7 +259,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
@ -156,7 +156,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = orinoco_if_add(priv, 0, 0);
|
||||
err = orinoco_if_add(priv, 0, 0, NULL);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto fail;
|
||||
|
1800
drivers/net/wireless/orinoco/orinoco_usb.c
Normal file
1800
drivers/net/wireless/orinoco/orinoco_usb.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -349,6 +349,7 @@ spectrum_cs_config(struct pcmcia_device *link)
|
||||
goto failed;
|
||||
|
||||
hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
|
||||
hw->eeprom_pda = true;
|
||||
|
||||
/*
|
||||
* This actually configures the PCMCIA socket -- setting up
|
||||
@ -374,7 +375,7 @@ spectrum_cs_config(struct pcmcia_device *link)
|
||||
|
||||
/* Register an interface with the stack */
|
||||
if (orinoco_if_add(priv, link->io.BasePort1,
|
||||
link->irq.AssignedIRQ) != 0) {
|
||||
link->irq.AssignedIRQ, NULL) != 0) {
|
||||
printk(KERN_ERR PFX "orinoco_if_add() failed\n");
|
||||
goto failed;
|
||||
}
|
||||
@ -405,9 +406,9 @@ spectrum_cs_release(struct pcmcia_device *link)
|
||||
|
||||
/* We're committed to taking the device away now, so mark the
|
||||
* hardware as unavailable */
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->hw.ops->lock_irqsave(&priv->lock, &flags);
|
||||
priv->hw_unavailable++;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
|
||||
|
||||
pcmcia_disable_device(link);
|
||||
if (priv->hw.iobase)
|
||||
|
@ -458,7 +458,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
|
||||
if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
|
||||
/* Fast channel change - no commit if successful */
|
||||
hermes_t *hw = &priv->hw;
|
||||
err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
|
||||
err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
|
||||
HERMES_TEST_SET_CHANNEL,
|
||||
chan, NULL);
|
||||
}
|
||||
@ -1273,8 +1273,8 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
|
||||
if (orinoco_lock(priv, &flags) != 0)
|
||||
return -EBUSY;
|
||||
|
||||
err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
|
||||
extra);
|
||||
err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
|
||||
extra);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -546,8 +546,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
|
||||
IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_PS_NULLFUNC_STACK |
|
||||
IEEE80211_HW_BEACON_FILTER |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
||||
IEEE80211_HW_NOISE_DBM;
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS;
|
||||
|
||||
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC) |
|
||||
|
@ -277,6 +277,14 @@ static void p54p_tasklet(unsigned long dev_id)
|
||||
struct p54p_priv *priv = dev->priv;
|
||||
struct p54p_ring_control *ring_control = priv->ring_control;
|
||||
|
||||
p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
|
||||
ARRAY_SIZE(ring_control->tx_mgmt),
|
||||
priv->tx_buf_mgmt);
|
||||
|
||||
p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
|
||||
ARRAY_SIZE(ring_control->tx_data),
|
||||
priv->tx_buf_data);
|
||||
|
||||
p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
|
||||
ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
|
||||
|
||||
@ -285,14 +293,6 @@ static void p54p_tasklet(unsigned long dev_id)
|
||||
|
||||
wmb();
|
||||
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
|
||||
|
||||
p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
|
||||
ARRAY_SIZE(ring_control->tx_mgmt),
|
||||
priv->tx_buf_mgmt);
|
||||
|
||||
p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
|
||||
ARRAY_SIZE(ring_control->tx_data),
|
||||
priv->tx_buf_data);
|
||||
}
|
||||
|
||||
static irqreturn_t p54p_interrupt(int irq, void *dev_id)
|
||||
|
@ -350,7 +350,6 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
|
||||
rx_status->flag |= RX_FLAG_MMIC_ERROR;
|
||||
|
||||
rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi);
|
||||
rx_status->noise = priv->noise;
|
||||
if (hdr->rate & 0x10)
|
||||
rx_status->flag |= RX_FLAG_SHORTPRE;
|
||||
if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
|
||||
|
@ -87,7 +87,7 @@ if RT2800PCI
|
||||
|
||||
config RT2800PCI_RT30XX
|
||||
bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices"
|
||||
default n
|
||||
default y
|
||||
---help---
|
||||
This adds support for rt30xx wireless chipset family to the
|
||||
rt2800pci driver.
|
||||
@ -156,7 +156,7 @@ if RT2800USB
|
||||
|
||||
config RT2800USB_RT30XX
|
||||
bool "rt2800usb - Include support for rt30xx (USB) devices"
|
||||
default n
|
||||
default y
|
||||
---help---
|
||||
This adds support for rt30xx wireless chipset family to the
|
||||
rt2800usb driver.
|
||||
|
@ -1018,8 +1018,8 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_desc_write(entry_priv->desc, 1, word);
|
||||
|
||||
rt2x00_desc_read(txd, 2, &word);
|
||||
rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skb->len);
|
||||
rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skb->len);
|
||||
rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_desc_write(txd, 2, word);
|
||||
|
||||
rt2x00_desc_read(txd, 3, &word);
|
||||
|
@ -1209,7 +1209,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
|
||||
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
|
||||
test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
}
|
||||
|
@ -1072,7 +1072,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
|
||||
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
|
@ -107,7 +107,7 @@
|
||||
/*
|
||||
* INT_SOURCE_CSR: Interrupt source register.
|
||||
* Write one to clear corresponding bit.
|
||||
* TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c
|
||||
* TX_FIFO_STATUS: FIFO Statistics is full, sw should read TX_STA_FIFO
|
||||
*/
|
||||
#define INT_SOURCE_CSR 0x0200
|
||||
#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001)
|
||||
@ -845,7 +845,7 @@
|
||||
* TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
|
||||
*/
|
||||
#define TX_BAND_CFG 0x132c
|
||||
#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001)
|
||||
#define TX_BAND_CFG_HT40_MINUS FIELD32(0x00000001)
|
||||
#define TX_BAND_CFG_A FIELD32(0x00000002)
|
||||
#define TX_BAND_CFG_BG FIELD32(0x00000004)
|
||||
|
||||
@ -1519,7 +1519,7 @@ struct mac_iveiv_entry {
|
||||
* BBP 3: RX Antenna
|
||||
*/
|
||||
#define BBP3_RX_ANTENNA FIELD8(0x18)
|
||||
#define BBP3_HT40_PLUS FIELD8(0x20)
|
||||
#define BBP3_HT40_MINUS FIELD8(0x20)
|
||||
|
||||
/*
|
||||
* BBP 4: Bandwidth
|
||||
@ -1565,6 +1565,11 @@ struct mac_iveiv_entry {
|
||||
*/
|
||||
#define RFCSR12_TX_POWER FIELD8(0x1f)
|
||||
|
||||
/*
|
||||
* RFCSR 13:
|
||||
*/
|
||||
#define RFCSR13_TX_POWER FIELD8(0x1f)
|
||||
|
||||
/*
|
||||
* RFCSR 15:
|
||||
*/
|
||||
|
@ -41,9 +41,6 @@
|
||||
#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
|
||||
#include "rt2x00usb.h"
|
||||
#endif
|
||||
#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE)
|
||||
#include "rt2x00pci.h"
|
||||
#endif
|
||||
#include "rt2800lib.h"
|
||||
#include "rt2800.h"
|
||||
#include "rt2800usb.h"
|
||||
@ -76,6 +73,23 @@ MODULE_LICENSE("GPL");
|
||||
rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \
|
||||
H2M_MAILBOX_CSR_OWNER, (__reg))
|
||||
|
||||
static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
/* check for rt2872 on SoC */
|
||||
if (!rt2x00_is_soc(rt2x00dev) ||
|
||||
!rt2x00_rt(rt2x00dev, RT2872))
|
||||
return false;
|
||||
|
||||
/* we know for sure that these rf chipsets are used on rt305x boards */
|
||||
if (rt2x00_rf(rt2x00dev, RF3020) ||
|
||||
rt2x00_rf(rt2x00dev, RF3021) ||
|
||||
rt2x00_rf(rt2x00dev, RF3022))
|
||||
return true;
|
||||
|
||||
NOTICE(rt2x00dev, "Unknown RF chipset on rt305x\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
const unsigned int word, const u8 value)
|
||||
{
|
||||
@ -794,6 +808,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
|
||||
TXPOWER_G_TO_DEV(info->tx_power1));
|
||||
rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
|
||||
|
||||
rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
|
||||
rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
|
||||
TXPOWER_G_TO_DEV(info->tx_power2));
|
||||
rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
|
||||
|
||||
rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
|
||||
rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
|
||||
rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
|
||||
@ -849,7 +868,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
}
|
||||
|
||||
rt2800_register_read(rt2x00dev, TX_BAND_CFG, ®);
|
||||
rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
|
||||
rt2x00_set_field32(®, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));
|
||||
rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14);
|
||||
rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14);
|
||||
rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
|
||||
@ -882,7 +901,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
rt2800_bbp_write(rt2x00dev, 4, bbp);
|
||||
|
||||
rt2800_bbp_read(rt2x00dev, 3, &bbp);
|
||||
rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
|
||||
rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));
|
||||
rt2800_bbp_write(rt2x00dev, 3, bbp);
|
||||
|
||||
if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
|
||||
@ -1551,6 +1570,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_wait_bbp_ready(rt2x00dev)))
|
||||
return -EACCES;
|
||||
|
||||
if (rt2800_is_305x_soc(rt2x00dev))
|
||||
rt2800_bbp_write(rt2x00dev, 31, 0x08);
|
||||
|
||||
rt2800_bbp_write(rt2x00dev, 65, 0x2c);
|
||||
rt2800_bbp_write(rt2x00dev, 66, 0x38);
|
||||
|
||||
@ -1571,6 +1593,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_bbp_write(rt2x00dev, 79, 0x13);
|
||||
rt2800_bbp_write(rt2x00dev, 80, 0x05);
|
||||
rt2800_bbp_write(rt2x00dev, 81, 0x33);
|
||||
} else if (rt2800_is_305x_soc(rt2x00dev)) {
|
||||
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
|
||||
rt2800_bbp_write(rt2x00dev, 80, 0x08);
|
||||
} else {
|
||||
rt2800_bbp_write(rt2x00dev, 81, 0x37);
|
||||
}
|
||||
@ -1591,12 +1616,16 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
|
||||
if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
|
||||
rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
|
||||
rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
|
||||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E))
|
||||
rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
|
||||
rt2800_is_305x_soc(rt2x00dev))
|
||||
rt2800_bbp_write(rt2x00dev, 103, 0xc0);
|
||||
else
|
||||
rt2800_bbp_write(rt2x00dev, 103, 0x00);
|
||||
|
||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
||||
if (rt2800_is_305x_soc(rt2x00dev))
|
||||
rt2800_bbp_write(rt2x00dev, 105, 0x01);
|
||||
else
|
||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
||||
rt2800_bbp_write(rt2x00dev, 106, 0x35);
|
||||
|
||||
if (rt2x00_rt(rt2x00dev, RT3071) ||
|
||||
@ -1613,11 +1642,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_bbp_write(rt2x00dev, 138, value);
|
||||
}
|
||||
|
||||
if (rt2x00_rt(rt2x00dev, RT2872)) {
|
||||
rt2800_bbp_write(rt2x00dev, 31, 0x08);
|
||||
rt2800_bbp_write(rt2x00dev, 78, 0x0e);
|
||||
rt2800_bbp_write(rt2x00dev, 80, 0x08);
|
||||
}
|
||||
|
||||
for (i = 0; i < EEPROM_BBP_SIZE; i++) {
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
|
||||
@ -1703,7 +1727,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
if (!rt2x00_rt(rt2x00dev, RT3070) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3071) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3090) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3390))
|
||||
!rt2x00_rt(rt2x00dev, RT3390) &&
|
||||
!rt2800_is_305x_soc(rt2x00dev))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
@ -1771,6 +1796,40 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
|
||||
rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
|
||||
rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
|
||||
} else if (rt2800_is_305x_soc(rt2x00dev)) {
|
||||
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
|
||||
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
|
||||
rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
|
||||
rt2800_rfcsr_write(rt2x00dev, 3, 0x75);
|
||||
rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
|
||||
rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
|
||||
rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
|
||||
rt2800_rfcsr_write(rt2x00dev, 7, 0x50);
|
||||
rt2800_rfcsr_write(rt2x00dev, 8, 0x39);
|
||||
rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
|
||||
rt2800_rfcsr_write(rt2x00dev, 10, 0x60);
|
||||
rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
|
||||
rt2800_rfcsr_write(rt2x00dev, 12, 0x75);
|
||||
rt2800_rfcsr_write(rt2x00dev, 13, 0x75);
|
||||
rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
|
||||
rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
|
||||
rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
|
||||
rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
|
||||
rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
|
||||
rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
|
||||
rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
|
||||
rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
|
||||
rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
|
||||
rt2800_rfcsr_write(rt2x00dev, 23, 0x31);
|
||||
rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
|
||||
rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
|
||||
rt2800_rfcsr_write(rt2x00dev, 26, 0x25);
|
||||
rt2800_rfcsr_write(rt2x00dev, 27, 0x23);
|
||||
rt2800_rfcsr_write(rt2x00dev, 28, 0x13);
|
||||
rt2800_rfcsr_write(rt2x00dev, 29, 0x83);
|
||||
rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
|
||||
rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
|
||||
@ -1986,7 +2045,6 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
|
||||
} else if (rt2x00_rt(rt2x00dev, RT2860) ||
|
||||
rt2x00_rt(rt2x00dev, RT2870) ||
|
||||
rt2x00_rt(rt2x00dev, RT2872) ||
|
||||
rt2x00_rt(rt2x00dev, RT2872)) {
|
||||
/*
|
||||
* There is a max of 2 RX streams for RT28x0 series
|
||||
@ -2318,8 +2376,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
else
|
||||
spec->ht.ht_supported = false;
|
||||
|
||||
/*
|
||||
* Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes
|
||||
* reception problems with HT40 capable 11n APs
|
||||
*/
|
||||
spec->ht.cap =
|
||||
IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
|
||||
IEEE80211_HT_CAP_GRN_FLD |
|
||||
IEEE80211_HT_CAP_SGI_20 |
|
||||
IEEE80211_HT_CAP_SGI_40 |
|
||||
|
@ -663,7 +663,7 @@ static int rt2800pci_write_tx_data(struct queue_entry* entry,
|
||||
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
|
||||
txdesc->key_idx : 0xff);
|
||||
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
|
||||
skb->len - txdesc->l2pad);
|
||||
txdesc->length);
|
||||
rt2x00_set_field32(&word, TXWI_W1_PACKETID,
|
||||
skbdesc->entry->queue->qid + 1);
|
||||
rt2x00_desc_write(txwi, 1, word);
|
||||
@ -895,10 +895,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
|
||||
(rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
|
||||
rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
|
||||
|
||||
rxdesc->noise =
|
||||
(rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) +
|
||||
rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2;
|
||||
|
||||
rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
|
||||
|
||||
/*
|
||||
|
@ -437,7 +437,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
||||
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
|
||||
txdesc->key_idx : 0xff);
|
||||
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
|
||||
skb->len - txdesc->l2pad);
|
||||
txdesc->length);
|
||||
rt2x00_set_field32(&word, TXWI_W1_PACKETID,
|
||||
skbdesc->entry->queue->qid + 1);
|
||||
rt2x00_desc_write(txwi, 1, word);
|
||||
@ -645,10 +645,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
|
||||
(rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
|
||||
rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
|
||||
|
||||
rxdesc->noise =
|
||||
(rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) +
|
||||
rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2;
|
||||
|
||||
rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
|
||||
|
||||
/*
|
||||
@ -1027,7 +1023,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
#ifdef CONFIG_RT2800USB_UNKNOWN
|
||||
/*
|
||||
* Unclear what kind of devices these are (they aren't supported by the
|
||||
* vendor driver).
|
||||
* vendor linux driver).
|
||||
*/
|
||||
/* Amigo */
|
||||
{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
@ -1040,6 +1036,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
/* AzureWave */
|
||||
{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Belkin */
|
||||
{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Buffalo */
|
||||
@ -1058,6 +1055,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Encore */
|
||||
{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Gemtek */
|
||||
@ -1074,11 +1072,13 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
/* Motorola */
|
||||
{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Ovislink */
|
||||
{ USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Pegatron */
|
||||
{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Planex */
|
||||
{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Qcom */
|
||||
@ -1087,6 +1087,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user