Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
This commit is contained in:
Коммит
e9e80ea5f2
|
@ -649,6 +649,7 @@ config RTL8187
|
|||
Trendnet TEW-424UB
|
||||
ASUS P5B Deluxe
|
||||
Toshiba Satellite Pro series of laptops
|
||||
Asus Wireless Link
|
||||
|
||||
Thanks to Realtek for their support!
|
||||
|
||||
|
|
|
@ -186,11 +186,13 @@ struct ath5k_srev_name {
|
|||
#define AR5K_SREV_RAD_2111 0x20
|
||||
#define AR5K_SREV_RAD_5112 0x30
|
||||
#define AR5K_SREV_RAD_5112A 0x35
|
||||
#define AR5K_SREV_RAD_5112B 0x36
|
||||
#define AR5K_SREV_RAD_2112 0x40
|
||||
#define AR5K_SREV_RAD_2112A 0x45
|
||||
#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */
|
||||
#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */
|
||||
#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */
|
||||
#define AR5K_SREV_RAD_2112B 0x46
|
||||
#define AR5K_SREV_RAD_SC0 0x50 /* Found on 2413/2414 */
|
||||
#define AR5K_SREV_RAD_SC1 0x60 /* Found on 5413/5414 */
|
||||
#define AR5K_SREV_RAD_SC2 0xa0 /* Found on 2424-5/5424 */
|
||||
#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
|
||||
|
||||
/* IEEE defs */
|
||||
|
|
|
@ -2170,6 +2170,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
|
|||
|
||||
ath5k_hw_set_intr(ah, 0);
|
||||
sc->bmisscount = 0;
|
||||
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
|
||||
|
||||
if (sc->opmode == IEEE80211_IF_TYPE_STA) {
|
||||
sc->imask |= AR5K_INT_BMISS;
|
||||
|
|
|
@ -129,7 +129,7 @@ static struct reg regs[] = {
|
|||
REG_STRUCT_INIT(AR5K_CPC1),
|
||||
REG_STRUCT_INIT(AR5K_CPC2),
|
||||
REG_STRUCT_INIT(AR5K_CPC3),
|
||||
REG_STRUCT_INIT(AR5K_CPCORN),
|
||||
REG_STRUCT_INIT(AR5K_CPCOVF),
|
||||
REG_STRUCT_INIT(AR5K_RESET_CTL),
|
||||
REG_STRUCT_INIT(AR5K_SLEEP_CTL),
|
||||
REG_STRUCT_INIT(AR5K_INTPEND),
|
||||
|
|
|
@ -63,7 +63,6 @@
|
|||
|
||||
struct ath5k_softc;
|
||||
struct ath5k_hw;
|
||||
struct ieee80211_hw_mode;
|
||||
struct sk_buff;
|
||||
struct ath5k_buf;
|
||||
|
||||
|
|
|
@ -139,6 +139,8 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
|
|||
for (c = 0; c < 2; c++) {
|
||||
|
||||
cur_reg = regs[c];
|
||||
|
||||
/* Save previous value */
|
||||
init_val = ath5k_hw_reg_read(ah, cur_reg);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
|
@ -170,6 +172,10 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
|
|||
var_pattern = 0x003b080f;
|
||||
ath5k_hw_reg_write(ah, var_pattern, cur_reg);
|
||||
}
|
||||
|
||||
/* Restore previous value */
|
||||
ath5k_hw_reg_write(ah, init_val, cur_reg);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -287,67 +293,42 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
|
|||
/* Identify the radio chip*/
|
||||
if (ah->ah_version == AR5K_AR5210) {
|
||||
ah->ah_radio = AR5K_RF5110;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
|
||||
ah->ah_radio = AR5K_RF5111;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
|
||||
|
||||
ah->ah_radio = AR5K_RF5112;
|
||||
|
||||
if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) {
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
|
||||
} else {
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
|
||||
}
|
||||
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
|
||||
ah->ah_radio = AR5K_RF2413;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
|
||||
ah->ah_radio = AR5K_RF5413;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) {
|
||||
|
||||
/* AR5424 */
|
||||
if (srev >= AR5K_SREV_VER_AR5424) {
|
||||
ah->ah_radio = AR5K_RF5413;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424;
|
||||
/* AR2424 */
|
||||
} else {
|
||||
ah->ah_radio = AR5K_RF2413; /* For testing */
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A;
|
||||
}
|
||||
|
||||
/*
|
||||
* Register returns 0x4 for radio revision
|
||||
* Register returns 0x0/0x04 for radio revision
|
||||
* so ath5k_hw_radio_revision doesn't parse the value
|
||||
* correctly. For now we are based on mac's srev to
|
||||
* identify RF2425 radio.
|
||||
*/
|
||||
} else if (srev == AR5K_SREV_VER_AR2425) {
|
||||
ah->ah_radio = AR5K_RF2425;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
|
||||
ah->ah_radio = AR5K_RF5111;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) {
|
||||
ah->ah_radio = AR5K_RF5112;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
|
||||
ah->ah_radio = AR5K_RF2413;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) {
|
||||
ah->ah_radio = AR5K_RF5413;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
|
||||
} else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) {
|
||||
/* AR5424 */
|
||||
if (srev >= AR5K_SREV_VER_AR5424) {
|
||||
ah->ah_radio = AR5K_RF5413;
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413;
|
||||
/* AR2424 */
|
||||
} else {
|
||||
ah->ah_radio = AR5K_RF2413; /* For testing */
|
||||
ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413;
|
||||
}
|
||||
}
|
||||
|
||||
ah->ah_phy = AR5K_PHY(0);
|
||||
|
||||
/*
|
||||
* Identify AR5212-based PCI-E cards
|
||||
* And write some initial settings.
|
||||
*
|
||||
* (doing a "strings" on ndis driver
|
||||
* -ar5211.sys- reveals the following
|
||||
* pci-e related functions:
|
||||
*
|
||||
* pcieClockReq
|
||||
* pcieRxErrNotify
|
||||
* pcieL1SKPEnable
|
||||
* pcieAspm
|
||||
* pcieDisableAspmOnRfWake
|
||||
* pciePowerSaveEnable
|
||||
*
|
||||
* I guess these point to ClockReq but
|
||||
* i'm not sure.)
|
||||
* Write PCI-E power save settings
|
||||
*/
|
||||
if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
|
||||
ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080);
|
||||
|
@ -369,10 +350,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
|
|||
if (ret)
|
||||
goto err_free;
|
||||
|
||||
/* Write AR5K_PCICFG_UNK on 2112B and later chips */
|
||||
if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B ||
|
||||
srev > AR5K_SREV_VER_AR2413) {
|
||||
ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get card capabilities, values, ...
|
||||
*/
|
||||
|
||||
ret = ath5k_eeprom_init(ah);
|
||||
if (ret) {
|
||||
ATH5K_ERR(sc, "unable to init EEPROM\n");
|
||||
|
@ -843,27 +829,41 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
* Write some more initial register settings
|
||||
*/
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
|
||||
ath5k_hw_reg_write(ah, 0x0002a002, 0x982c);
|
||||
|
||||
if (channel->hw_value == CHANNEL_G)
|
||||
if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413)
|
||||
ath5k_hw_reg_write(ah, 0x00f80d80,
|
||||
AR5K_PHY(83));
|
||||
0x994c);
|
||||
else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424)
|
||||
ath5k_hw_reg_write(ah, 0x00380140,
|
||||
AR5K_PHY(83));
|
||||
0x994c);
|
||||
else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425)
|
||||
ath5k_hw_reg_write(ah, 0x00fc0ec0,
|
||||
AR5K_PHY(83));
|
||||
0x994c);
|
||||
else /* 2425 */
|
||||
ath5k_hw_reg_write(ah, 0x00fc0fc0,
|
||||
AR5K_PHY(83));
|
||||
0x994c);
|
||||
else
|
||||
ath5k_hw_reg_write(ah, 0x00000000,
|
||||
AR5K_PHY(83));
|
||||
ath5k_hw_reg_write(ah, 0x00000000, 0x994c);
|
||||
|
||||
ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
|
||||
ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
|
||||
/* Some bits are disabled here, we know nothing about
|
||||
* register 0xa228 yet, most of the times this ends up
|
||||
* with a value 0x9b5 -haven't seen any dump with
|
||||
* a different value- */
|
||||
/* Got this from decompiling binary HAL */
|
||||
data = ath5k_hw_reg_read(ah, 0xa228);
|
||||
data &= 0xfffffdff;
|
||||
ath5k_hw_reg_write(ah, data, 0xa228);
|
||||
|
||||
data = ath5k_hw_reg_read(ah, 0xa228);
|
||||
data &= 0xfffe03ff;
|
||||
ath5k_hw_reg_write(ah, data, 0xa228);
|
||||
data = 0;
|
||||
|
||||
/* Just write 0x9b5 ? */
|
||||
/* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */
|
||||
ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK);
|
||||
ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
|
||||
ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL);
|
||||
}
|
||||
|
@ -879,6 +879,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
else
|
||||
data = 0xffb80d20;
|
||||
ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
|
||||
data = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -898,7 +899,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
|
||||
/*
|
||||
* Write RF registers
|
||||
* TODO:Does this work on 5211 (5111) ?
|
||||
*/
|
||||
ret = ath5k_hw_rfregs(ah, channel, mode);
|
||||
if (ret)
|
||||
|
@ -935,7 +935,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
return ret;
|
||||
|
||||
/* Set antenna mode */
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x44),
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL,
|
||||
ah->ah_antenna[ee_mode][0], 0xfffffc06);
|
||||
|
||||
/*
|
||||
|
@ -965,15 +965,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
|
||||
ath5k_hw_reg_write(ah,
|
||||
AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
|
||||
AR5K_PHY(0x5a));
|
||||
AR5K_PHY_NFTHRES);
|
||||
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x11),
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING,
|
||||
(ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
|
||||
0xffffc07f);
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x12),
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN,
|
||||
(ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000,
|
||||
0xfffc0fff);
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x14),
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE,
|
||||
(ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
|
||||
((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00),
|
||||
0xffff0000);
|
||||
|
@ -982,13 +982,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
(ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
|
||||
(ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
|
||||
(ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
|
||||
(ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY(0x0d));
|
||||
(ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4);
|
||||
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x0a),
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3,
|
||||
ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x19),
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF,
|
||||
(ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x49), 4, 0xffffff01);
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01);
|
||||
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
|
||||
AR5K_PHY_IQ_CORR_ENABLE |
|
||||
|
@ -1063,7 +1063,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
|
||||
|
||||
/*
|
||||
* 5111/5112 Specific
|
||||
* On 5211+ read activation -> rx delay
|
||||
* and use it.
|
||||
*/
|
||||
if (ah->ah_version != AR5K_AR5210) {
|
||||
data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
|
||||
|
@ -1071,32 +1072,45 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
data = (channel->hw_value & CHANNEL_CCK) ?
|
||||
((data << 2) / 22) : (data / 10);
|
||||
|
||||
udelay(100 + data);
|
||||
udelay(100 + (2 * data));
|
||||
data = 0;
|
||||
} else {
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable calibration and wait until completion
|
||||
* Perform ADC test (?)
|
||||
*/
|
||||
data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1);
|
||||
ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1);
|
||||
for (i = 0; i <= 20; i++) {
|
||||
if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10))
|
||||
break;
|
||||
udelay(200);
|
||||
}
|
||||
ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1);
|
||||
data = 0;
|
||||
|
||||
/*
|
||||
* Start automatic gain calibration
|
||||
*
|
||||
* During AGC calibration RX path is re-routed to
|
||||
* a signal detector so we don't receive anything.
|
||||
*
|
||||
* This method is used to calibrate some static offsets
|
||||
* used together with on-the fly I/Q calibration (the
|
||||
* one performed via ath5k_hw_phy_calibrate), that doesn't
|
||||
* interrupt rx path.
|
||||
*
|
||||
* If we are in a noisy environment AGC calibration may time
|
||||
* out.
|
||||
*/
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_CAL);
|
||||
|
||||
if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_CAL, 0, false)) {
|
||||
ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
|
||||
channel->center_freq);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* At the same time start I/Q calibration for QAM constellation
|
||||
* -no need for CCK- */
|
||||
ah->ah_calibration = false;
|
||||
|
||||
/* A and G modes can use QAM modulation which requires enabling
|
||||
* I and Q calibration. Don't bother in B mode. */
|
||||
if (!(mode == AR5K_MODE_11B)) {
|
||||
ah->ah_calibration = true;
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
|
||||
|
@ -1105,6 +1119,30 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
AR5K_PHY_IQ_RUN);
|
||||
}
|
||||
|
||||
/* Wait for gain calibration to finish (we check for I/Q calibration
|
||||
* during ath5k_phy_calibrate) */
|
||||
if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_CAL, 0, false)) {
|
||||
ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n",
|
||||
channel->center_freq);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Start noise floor calibration
|
||||
*
|
||||
* If we run NF calibration before AGC, it always times out.
|
||||
* Binary HAL starts NF and AGC calibration at the same time
|
||||
* and only waits for AGC to finish. I believe that's wrong because
|
||||
* during NF calibration, rx path is also routed to a detector, so if
|
||||
* it doesn't finish we won't have RX.
|
||||
*
|
||||
* XXX: Find an interval that's OK for all cards...
|
||||
*/
|
||||
ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Reset queues and start beacon timers at the end of the reset routine
|
||||
*/
|
||||
|
@ -1154,6 +1192,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
|
|||
ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
|
||||
ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
|
||||
ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING);
|
||||
|
||||
data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ;
|
||||
data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ?
|
||||
0x00000f80 : 0x00001380 ;
|
||||
ath5k_hw_reg_write(ah, data, AR5K_USEC_5211);
|
||||
data = 0;
|
||||
}
|
||||
|
||||
if (ah->ah_version == AR5K_AR5212) {
|
||||
|
@ -1226,7 +1270,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
|||
bool set_chip, u16 sleep_duration)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 staid;
|
||||
u32 staid, data;
|
||||
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
|
||||
|
@ -1238,7 +1282,8 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
|||
case AR5K_PM_NETWORK_SLEEP:
|
||||
if (set_chip)
|
||||
ath5k_hw_reg_write(ah,
|
||||
AR5K_SLEEP_CTL_SLE | sleep_duration,
|
||||
AR5K_SLEEP_CTL_SLE_ALLOW |
|
||||
sleep_duration,
|
||||
AR5K_SLEEP_CTL);
|
||||
|
||||
staid |= AR5K_STA_ID1_PWR_SV;
|
||||
|
@ -1253,13 +1298,24 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
|||
break;
|
||||
|
||||
case AR5K_PM_AWAKE:
|
||||
|
||||
staid &= ~AR5K_STA_ID1_PWR_SV;
|
||||
|
||||
if (!set_chip)
|
||||
goto commit;
|
||||
|
||||
ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
|
||||
AR5K_SLEEP_CTL);
|
||||
/* Preserve sleep duration */
|
||||
data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
|
||||
if( data & 0xffc00000 ){
|
||||
data = 0;
|
||||
} else {
|
||||
data = data & 0xfffcffff;
|
||||
}
|
||||
|
||||
for (i = 5000; i > 0; i--) {
|
||||
ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
|
||||
udelay(15);
|
||||
|
||||
for (i = 50; i > 0; i--) {
|
||||
/* Check if the chip did wake up */
|
||||
if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
|
||||
AR5K_PCICFG_SPWR_DN) == 0)
|
||||
|
@ -1267,15 +1323,13 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
|||
|
||||
/* Wait a bit and retry */
|
||||
udelay(200);
|
||||
ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
|
||||
AR5K_SLEEP_CTL);
|
||||
ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL);
|
||||
}
|
||||
|
||||
/* Fail if the chip didn't wake up */
|
||||
if (i <= 0)
|
||||
return -EIO;
|
||||
|
||||
staid &= ~AR5K_STA_ID1_PWR_SV;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1304,6 +1358,7 @@ void ath5k_hw_start_rx(struct ath5k_hw *ah)
|
|||
{
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
|
||||
ath5k_hw_reg_read(ah, AR5K_CR);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1390,6 +1445,7 @@ int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue)
|
|||
}
|
||||
/* Start queue */
|
||||
ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
|
||||
ath5k_hw_reg_read(ah, AR5K_CR);
|
||||
} else {
|
||||
/* Return if queue is disabled */
|
||||
if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
|
||||
|
@ -1687,6 +1743,7 @@ enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask)
|
|||
* (they will be re-enabled afterwards).
|
||||
*/
|
||||
ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
|
||||
ath5k_hw_reg_read(ah, AR5K_IER);
|
||||
|
||||
old_mask = ah->ah_imr;
|
||||
|
||||
|
@ -3363,11 +3420,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||
ath5k_hw_reg_write(ah, ah->ah_turbo ?
|
||||
AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
|
||||
AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
|
||||
/* Set PHY register 0x9844 (??) */
|
||||
/* Set AR5K_PHY_SETTLING */
|
||||
ath5k_hw_reg_write(ah, ah->ah_turbo ?
|
||||
(ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
|
||||
(ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
|
||||
AR5K_PHY(17));
|
||||
(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
|
||||
| 0x38 :
|
||||
(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
|
||||
| 0x1C,
|
||||
AR5K_PHY_SETTLING);
|
||||
/* Set Frame Control Register */
|
||||
ath5k_hw_reg_write(ah, ah->ah_turbo ?
|
||||
(AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
|
||||
|
@ -3488,7 +3547,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
|
|||
if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
|
||||
AR5K_REG_ENABLE_BITS(ah,
|
||||
AR5K_QUEUE_MISC(queue),
|
||||
AR5K_QCU_MISC_TXE);
|
||||
AR5K_QCU_MISC_RDY_VEOL_POLICY);
|
||||
}
|
||||
|
||||
if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
|
||||
|
|
|
@ -489,7 +489,7 @@ static const struct ath5k_ini ar5212_ini[] = {
|
|||
{ AR5K_QUEUE_TXDP(9), 0x00000000 },
|
||||
{ AR5K_DCU_FP, 0x00000000 },
|
||||
{ AR5K_DCU_TXP, 0x00000000 },
|
||||
{ AR5K_DCU_TX_FILTER, 0x00000000 },
|
||||
{ AR5K_DCU_TX_FILTER_0_BASE, 0x00000000 },
|
||||
/* Unknown table */
|
||||
{ 0x1078, 0x00000000 },
|
||||
{ 0x10b8, 0x00000000 },
|
||||
|
@ -679,7 +679,7 @@ static const struct ath5k_ini ar5212_ini[] = {
|
|||
{ AR5K_PHY(645), 0x00106c10 },
|
||||
{ AR5K_PHY(646), 0x009c4060 },
|
||||
{ AR5K_PHY(647), 0x1483800a },
|
||||
/* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */
|
||||
/* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413/2425 */
|
||||
{ AR5K_PHY(648), 0x01831061 },
|
||||
{ AR5K_PHY(649), 0x00000400 },
|
||||
/*{ AR5K_PHY(650), 0x000001b5 },*/
|
||||
|
|
|
@ -1020,6 +1020,74 @@ static const struct ath5k_ini_rfgain rfgain_2413[] = {
|
|||
{ AR5K_RF_GAIN(63), { 0x000000f9 } },
|
||||
};
|
||||
|
||||
/* Initial RF Gain settings for RF2425 */
|
||||
static const struct ath5k_ini_rfgain rfgain_2425[] = {
|
||||
{ AR5K_RF_GAIN(0), { 0x00000000 } },
|
||||
{ AR5K_RF_GAIN(1), { 0x00000040 } },
|
||||
{ AR5K_RF_GAIN(2), { 0x00000080 } },
|
||||
{ AR5K_RF_GAIN(3), { 0x00000181 } },
|
||||
{ AR5K_RF_GAIN(4), { 0x000001c1 } },
|
||||
{ AR5K_RF_GAIN(5), { 0x00000001 } },
|
||||
{ AR5K_RF_GAIN(6), { 0x00000041 } },
|
||||
{ AR5K_RF_GAIN(7), { 0x00000081 } },
|
||||
{ AR5K_RF_GAIN(8), { 0x00000188 } },
|
||||
{ AR5K_RF_GAIN(9), { 0x000001c8 } },
|
||||
{ AR5K_RF_GAIN(10), { 0x00000008 } },
|
||||
{ AR5K_RF_GAIN(11), { 0x00000048 } },
|
||||
{ AR5K_RF_GAIN(12), { 0x00000088 } },
|
||||
{ AR5K_RF_GAIN(13), { 0x00000189 } },
|
||||
{ AR5K_RF_GAIN(14), { 0x000001c9 } },
|
||||
{ AR5K_RF_GAIN(15), { 0x00000009 } },
|
||||
{ AR5K_RF_GAIN(16), { 0x00000049 } },
|
||||
{ AR5K_RF_GAIN(17), { 0x00000089 } },
|
||||
{ AR5K_RF_GAIN(18), { 0x000001b0 } },
|
||||
{ AR5K_RF_GAIN(19), { 0x000001f0 } },
|
||||
{ AR5K_RF_GAIN(20), { 0x00000030 } },
|
||||
{ AR5K_RF_GAIN(21), { 0x00000070 } },
|
||||
{ AR5K_RF_GAIN(22), { 0x00000171 } },
|
||||
{ AR5K_RF_GAIN(23), { 0x000001b1 } },
|
||||
{ AR5K_RF_GAIN(24), { 0x000001f1 } },
|
||||
{ AR5K_RF_GAIN(25), { 0x00000031 } },
|
||||
{ AR5K_RF_GAIN(26), { 0x00000071 } },
|
||||
{ AR5K_RF_GAIN(27), { 0x000001b8 } },
|
||||
{ AR5K_RF_GAIN(28), { 0x000001f8 } },
|
||||
{ AR5K_RF_GAIN(29), { 0x00000038 } },
|
||||
{ AR5K_RF_GAIN(30), { 0x00000078 } },
|
||||
{ AR5K_RF_GAIN(31), { 0x000000b8 } },
|
||||
{ AR5K_RF_GAIN(32), { 0x000001b9 } },
|
||||
{ AR5K_RF_GAIN(33), { 0x000001f9 } },
|
||||
{ AR5K_RF_GAIN(34), { 0x00000039 } },
|
||||
{ AR5K_RF_GAIN(35), { 0x00000079 } },
|
||||
{ AR5K_RF_GAIN(36), { 0x000000b9 } },
|
||||
{ AR5K_RF_GAIN(37), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(38), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(39), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(40), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(41), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(42), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(43), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(44), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(45), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(46), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(47), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(48), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(49), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(50), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(51), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(52), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(53), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(54), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(55), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(56), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(57), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(58), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(59), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(60), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(61), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(62), { 0x000000f9 } },
|
||||
{ AR5K_RF_GAIN(63), { 0x000000f9 } },
|
||||
};
|
||||
|
||||
static const struct ath5k_gain_opt rfgain_opt_5112 = {
|
||||
1,
|
||||
8,
|
||||
|
@ -1588,8 +1656,8 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
|
|||
freq = 0; /* only 2Ghz */
|
||||
break;
|
||||
case AR5K_RF2425:
|
||||
ath5k_rfg = rfgain_2413;
|
||||
size = ARRAY_SIZE(rfgain_2413);
|
||||
ath5k_rfg = rfgain_2425;
|
||||
size = ARRAY_SIZE(rfgain_2425);
|
||||
freq = 0; /* only 2Ghz */
|
||||
break;
|
||||
default:
|
||||
|
@ -1830,9 +1898,6 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
|
|||
data = data0 = data1 = data2 = 0;
|
||||
c = channel->center_freq;
|
||||
|
||||
/*
|
||||
* Set the channel on the RF5112 or newer
|
||||
*/
|
||||
if (c < 4800) {
|
||||
if (!((c - 2224) % 5)) {
|
||||
data0 = ((2 * (c - 704)) - 3040) / 10;
|
||||
|
@ -1844,7 +1909,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
|
|||
return -EINVAL;
|
||||
|
||||
data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
|
||||
} else {
|
||||
} else if ((c - (c % 5)) != 2 || c > 5435) {
|
||||
if (!(c % 20) && c >= 5120) {
|
||||
data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
|
||||
data2 = ath5k_hw_bitswap(3, 2);
|
||||
|
@ -1856,6 +1921,9 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
|
|||
data2 = ath5k_hw_bitswap(1, 2);
|
||||
} else
|
||||
return -EINVAL;
|
||||
} else {
|
||||
data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
|
||||
data2 = ath5k_hw_bitswap(0, 2);
|
||||
}
|
||||
|
||||
data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
|
||||
|
@ -1866,6 +1934,45 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the channel on the RF2425
|
||||
*/
|
||||
static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
u32 data, data0, data2;
|
||||
u16 c;
|
||||
|
||||
data = data0 = data2 = 0;
|
||||
c = channel->center_freq;
|
||||
|
||||
if (c < 4800) {
|
||||
data0 = ath5k_hw_bitswap((c - 2272), 8);
|
||||
data2 = 0;
|
||||
/* ? 5GHz ? */
|
||||
} else if ((c - (c % 5)) != 2 || c > 5435) {
|
||||
if (!(c % 20) && c < 5120)
|
||||
data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
|
||||
else if (!(c % 10))
|
||||
data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
|
||||
else if (!(c % 5))
|
||||
data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
|
||||
else
|
||||
return -EINVAL;
|
||||
data2 = ath5k_hw_bitswap(1, 2);
|
||||
} else {
|
||||
data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8);
|
||||
data2 = ath5k_hw_bitswap(0, 2);
|
||||
}
|
||||
|
||||
data = (data0 << 4) | data2 << 2 | 0x1001;
|
||||
|
||||
ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
|
||||
ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set a channel on the radio chip
|
||||
*/
|
||||
|
@ -1895,6 +2002,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
|
|||
case AR5K_RF5111:
|
||||
ret = ath5k_hw_rf5111_channel(ah, channel);
|
||||
break;
|
||||
case AR5K_RF2425:
|
||||
ret = ath5k_hw_rf2425_channel(ah, channel);
|
||||
break;
|
||||
default:
|
||||
ret = ath5k_hw_rf5112_channel(ah, channel);
|
||||
break;
|
||||
|
@ -1903,6 +2013,15 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Set JAPAN setting for channel 14 */
|
||||
if (channel->center_freq == 2484) {
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
|
||||
AR5K_PHY_CCKTXCTL_JAPAN);
|
||||
} else {
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL,
|
||||
AR5K_PHY_CCKTXCTL_WORLD);
|
||||
}
|
||||
|
||||
ah->ah_current_channel.center_freq = channel->center_freq;
|
||||
ah->ah_current_channel.hw_value = channel->hw_value;
|
||||
ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false;
|
||||
|
@ -1933,6 +2052,8 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
|
|||
* http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
|
||||
* &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
|
||||
*
|
||||
* XXX: Since during noise floor calibration antennas are detached according to
|
||||
* the patent, we should stop tx queues here.
|
||||
*/
|
||||
int
|
||||
ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
|
||||
|
@ -1942,7 +2063,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
|
|||
s32 noise_floor;
|
||||
|
||||
/*
|
||||
* Enable noise floor calibration and wait until completion
|
||||
* Enable noise floor calibration
|
||||
*/
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_NF);
|
||||
|
@ -1952,7 +2073,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
|
|||
if (ret) {
|
||||
ATH5K_ERR(ah->ah_sc,
|
||||
"noise floor calibration timeout (%uMHz)\n", freq);
|
||||
return ret;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* Wait until the noise floor is calibrated and read the value */
|
||||
|
@ -1974,7 +2095,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
|
|||
if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
|
||||
ATH5K_ERR(ah->ah_sc,
|
||||
"noise floor calibration failed (%uMHz)\n", freq);
|
||||
return -EIO;
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ah->ah_noise_floor = noise_floor;
|
||||
|
@ -2087,38 +2208,66 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
|||
}
|
||||
|
||||
/*
|
||||
* Perform a PHY calibration on RF5111/5112
|
||||
* Perform a PHY calibration on RF5111/5112 and newer chips
|
||||
*/
|
||||
static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
u32 i_pwr, q_pwr;
|
||||
s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
|
||||
int i;
|
||||
ATH5K_TRACE(ah->ah_sc);
|
||||
|
||||
if (!ah->ah_calibration ||
|
||||
ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
|
||||
ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
|
||||
goto done;
|
||||
|
||||
ah->ah_calibration = false;
|
||||
/* Calibration has finished, get the results and re-run */
|
||||
for (i = 0; i <= 10; i++) {
|
||||
iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
|
||||
i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
|
||||
q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
|
||||
}
|
||||
|
||||
iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
|
||||
i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
|
||||
q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
|
||||
i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
|
||||
q_coffd = q_pwr >> 6;
|
||||
q_coffd = q_pwr >> 7;
|
||||
|
||||
/* No correction */
|
||||
if (i_coffd == 0 || q_coffd == 0)
|
||||
goto done;
|
||||
|
||||
i_coff = ((-iq_corr) / i_coffd) & 0x3f;
|
||||
q_coff = (((s32)i_pwr / q_coffd) - 64) & 0x1f;
|
||||
|
||||
/* Commit new IQ value */
|
||||
/* Boundary check */
|
||||
if (i_coff > 31)
|
||||
i_coff = 31;
|
||||
if (i_coff < -32)
|
||||
i_coff = -32;
|
||||
|
||||
q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f;
|
||||
|
||||
/* Boundary check */
|
||||
if (q_coff > 15)
|
||||
q_coff = 15;
|
||||
if (q_coff < -16)
|
||||
q_coff = -16;
|
||||
|
||||
/* Commit new I/Q value */
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
|
||||
((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
|
||||
|
||||
/* Re-enable calibration -if we don't we'll commit
|
||||
* the same values again and again */
|
||||
AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
|
||||
AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN);
|
||||
|
||||
done:
|
||||
|
||||
/* TODO: Separate noise floor calibration from I/Q calibration
|
||||
* since noise floor calibration interrupts rx path while I/Q
|
||||
* calibration doesn't. We don't need to run noise floor calibration
|
||||
* as often as I/Q calibration.*/
|
||||
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
|
||||
|
||||
/* Request RF gain */
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -305,9 +305,10 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c)
|
|||
#define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs))
|
||||
|
||||
/* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */
|
||||
#define ipw_write8(ipw, ofs, val) \
|
||||
#define ipw_write8(ipw, ofs, val) do { \
|
||||
IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \
|
||||
_ipw_write8(ipw, ofs, val)
|
||||
_ipw_write8(ipw, ofs, val); \
|
||||
} while (0)
|
||||
|
||||
/* 16-bit direct write (low 4K) */
|
||||
#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs))
|
||||
|
|
|
@ -710,10 +710,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
|
||||
iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Convert 3945's rssi indicator to dBm */
|
||||
rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET;
|
||||
|
@ -775,6 +772,11 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
|
|||
priv->last_rx_noise = rx_status.noise;
|
||||
}
|
||||
|
||||
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
|
||||
iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) {
|
||||
case IEEE80211_FTYPE_MGMT:
|
||||
switch (le16_to_cpu(header->frame_control) &
|
||||
|
|
|
@ -962,16 +962,16 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((iwl_queue_space(q) < q->high_mark)
|
||||
&& priv->mac80211_registered) {
|
||||
if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
|
||||
if (wait_write_ptr) {
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
txq->need_update = 1;
|
||||
iwl_txq_update_write_ptr(priv, txq);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
} else {
|
||||
ieee80211_stop_queue(priv->hw,
|
||||
skb_get_queue_mapping(skb));
|
||||
}
|
||||
|
||||
ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -297,9 +297,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
|
|||
lbs_add_rtap(priv);
|
||||
}
|
||||
priv->monitormode = monitor_mode;
|
||||
}
|
||||
|
||||
else {
|
||||
} else {
|
||||
if (!priv->monitormode)
|
||||
return strlen(buf);
|
||||
priv->monitormode = 0;
|
||||
|
@ -1242,8 +1240,6 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
lbs_pr_err("cannot register ethX device\n");
|
||||
goto done;
|
||||
}
|
||||
if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
|
||||
lbs_pr_err("cannot register lbs_rtap attribute\n");
|
||||
|
||||
lbs_update_channel(priv);
|
||||
|
||||
|
@ -1275,6 +1271,13 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
|
||||
if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
|
||||
lbs_pr_err("cannot register lbs_mesh attribute\n");
|
||||
|
||||
/* While rtap isn't related to mesh, only mesh-enabled
|
||||
* firmware implements the rtap functionality via
|
||||
* CMD_802_11_MONITOR_MODE.
|
||||
*/
|
||||
if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
|
||||
lbs_pr_err("cannot register lbs_rtap attribute\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1306,9 +1309,9 @@ void lbs_stop_card(struct lbs_private *priv)
|
|||
netif_carrier_off(priv->dev);
|
||||
|
||||
lbs_debugfs_remove_one(priv);
|
||||
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
|
||||
if (priv->mesh_tlv) {
|
||||
device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
|
||||
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
|
||||
}
|
||||
|
||||
/* Flush pending command nodes */
|
||||
|
|
|
@ -2518,7 +2518,7 @@ enum {
|
|||
|
||||
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
|
||||
#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \
|
||||
((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data))
|
||||
offsetof(struct prism2_hostapd_param, u.generic_elem.data)
|
||||
|
||||
/* Maximum length for algorithm names (-1 for nul termination)
|
||||
* used in ioctl() */
|
||||
|
|
|
@ -1220,6 +1220,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_CIPHER_ALG, CIPHER_NONE);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
}
|
||||
|
|
|
@ -1376,6 +1376,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
|
||||
EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word);
|
||||
} else {
|
||||
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word);
|
||||
|
@ -1384,9 +1387,6 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
|||
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
|
||||
EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word);
|
||||
} else {
|
||||
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
|
||||
}
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
|
||||
|
|
|
@ -368,6 +368,12 @@ struct rt2x00_intf {
|
|||
#define DELAYED_CONFIG_ERP 0x00000002
|
||||
#define DELAYED_LED_ASSOC 0x00000004
|
||||
|
||||
/*
|
||||
* Software sequence counter, this is only required
|
||||
* for hardware which doesn't support hardware
|
||||
* sequence counting.
|
||||
*/
|
||||
spinlock_t seqlock;
|
||||
u16 seqno;
|
||||
};
|
||||
|
||||
|
|
|
@ -254,6 +254,8 @@ config:
|
|||
libconf.ant.rx = default_ant->rx;
|
||||
else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
|
||||
libconf.ant.rx = ANTENNA_B;
|
||||
else
|
||||
libconf.ant.rx = active_ant->rx;
|
||||
|
||||
if (conf->antenna_sel_tx)
|
||||
libconf.ant.tx = conf->antenna_sel_tx;
|
||||
|
@ -261,6 +263,8 @@ config:
|
|||
libconf.ant.tx = default_ant->tx;
|
||||
else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
|
||||
libconf.ant.tx = ANTENNA_B;
|
||||
else
|
||||
libconf.ant.tx = active_ant->tx;
|
||||
}
|
||||
|
||||
if (flags & CONFIG_UPDATE_SLOT_TIME) {
|
||||
|
|
|
@ -372,9 +372,6 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \
|
|||
if (*offset) \
|
||||
return 0; \
|
||||
\
|
||||
if (!capable(CAP_NET_ADMIN)) \
|
||||
return -EPERM; \
|
||||
\
|
||||
if (intf->offset_##__name >= debug->__name.word_count) \
|
||||
return -EINVAL; \
|
||||
\
|
||||
|
@ -454,7 +451,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
|
|||
data += sprintf(data, "compiled: %s %s\n", __DATE__, __TIME__);
|
||||
blob->size = strlen(blob->data);
|
||||
|
||||
return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
|
||||
return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
|
||||
}
|
||||
|
||||
static struct dentry *rt2x00debug_create_file_chipset(const char *name,
|
||||
|
@ -482,7 +479,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
|
|||
data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
|
||||
blob->size = strlen(blob->data);
|
||||
|
||||
return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob);
|
||||
return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob);
|
||||
}
|
||||
|
||||
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
||||
|
@ -517,7 +514,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
|||
if (IS_ERR(intf->chipset_entry))
|
||||
goto exit;
|
||||
|
||||
intf->dev_flags = debugfs_create_file("dev_flags", S_IRUGO,
|
||||
intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR,
|
||||
intf->driver_folder, intf,
|
||||
&rt2x00debug_fop_dev_flags);
|
||||
if (IS_ERR(intf->dev_flags))
|
||||
|
@ -532,7 +529,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
|||
({ \
|
||||
(__intf)->__name##_off_entry = \
|
||||
debugfs_create_u32(__stringify(__name) "_offset", \
|
||||
S_IRUGO | S_IWUSR, \
|
||||
S_IRUSR | S_IWUSR, \
|
||||
(__intf)->register_folder, \
|
||||
&(__intf)->offset_##__name); \
|
||||
if (IS_ERR((__intf)->__name##_off_entry)) \
|
||||
|
@ -540,7 +537,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
|||
\
|
||||
(__intf)->__name##_val_entry = \
|
||||
debugfs_create_file(__stringify(__name) "_value", \
|
||||
S_IRUGO | S_IWUSR, \
|
||||
S_IRUSR | S_IWUSR, \
|
||||
(__intf)->register_folder, \
|
||||
(__intf), &rt2x00debug_fop_##__name);\
|
||||
if (IS_ERR((__intf)->__name##_val_entry)) \
|
||||
|
@ -560,7 +557,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
|||
goto exit;
|
||||
|
||||
intf->queue_frame_dump_entry =
|
||||
debugfs_create_file("dump", S_IRUGO, intf->queue_folder,
|
||||
debugfs_create_file("dump", S_IRUSR, intf->queue_folder,
|
||||
intf, &rt2x00debug_fop_queue_dump);
|
||||
if (IS_ERR(intf->queue_frame_dump_entry))
|
||||
goto exit;
|
||||
|
@ -569,7 +566,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
|
|||
init_waitqueue_head(&intf->frame_dump_waitqueue);
|
||||
|
||||
intf->queue_stats_entry =
|
||||
debugfs_create_file("queue", S_IRUGO, intf->queue_folder,
|
||||
debugfs_create_file("queue", S_IRUSR, intf->queue_folder,
|
||||
intf, &rt2x00debug_fop_queue_stats);
|
||||
|
||||
return;
|
||||
|
|
|
@ -247,6 +247,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
|
|||
rt2x00dev->intf_sta_count++;
|
||||
|
||||
spin_lock_init(&intf->lock);
|
||||
spin_lock_init(&intf->seqlock);
|
||||
intf->beacon = entry;
|
||||
|
||||
if (conf->type == IEEE80211_IF_TYPE_AP)
|
||||
|
|
|
@ -128,6 +128,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
|||
unsigned int data_length;
|
||||
unsigned int duration;
|
||||
unsigned int residual;
|
||||
unsigned long irqflags;
|
||||
|
||||
memset(txdesc, 0, sizeof(*txdesc));
|
||||
|
||||
|
@ -213,14 +214,14 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
|
|||
* sequence counter given by mac80211.
|
||||
*/
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
|
||||
spin_lock(&intf->lock);
|
||||
spin_lock_irqsave(&intf->seqlock, irqflags);
|
||||
|
||||
if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
|
||||
intf->seqno += 0x10;
|
||||
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
|
||||
hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
|
||||
|
||||
spin_unlock(&intf->lock);
|
||||
spin_unlock_irqrestore(&intf->seqlock, irqflags);
|
||||
|
||||
__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
|
||||
}
|
||||
|
|
|
@ -1003,6 +1003,11 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hardware needs another millisecond before it is ready.
|
||||
*/
|
||||
msleep(1);
|
||||
|
||||
/*
|
||||
* Reset MAC and BBP registers.
|
||||
*/
|
||||
|
|
|
@ -94,6 +94,10 @@ struct rtl8187_priv {
|
|||
const struct rtl818x_rf_ops *rf;
|
||||
struct ieee80211_vif *vif;
|
||||
int mode;
|
||||
/* The mutex protects the TX loopback state.
|
||||
* Any attempt to set channels concurrently locks the device.
|
||||
*/
|
||||
struct mutex conf_mutex;
|
||||
|
||||
/* rtl8187 specific */
|
||||
struct ieee80211_channel channels[14];
|
||||
|
|
|
@ -31,6 +31,8 @@ MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver");
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct usb_device_id rtl8187_table[] __devinitdata = {
|
||||
/* Asus */
|
||||
{USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187},
|
||||
/* Realtek */
|
||||
{USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187},
|
||||
{USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},
|
||||
|
@ -726,6 +728,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
if (priv->is_rtl8187b) {
|
||||
reg = RTL818X_RX_CONF_MGMT |
|
||||
RTL818X_RX_CONF_DATA |
|
||||
|
@ -747,6 +750,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
|
|||
(7 << 0 /* long retry limit */) |
|
||||
(7 << 21 /* MAX TX DMA */));
|
||||
rtl8187_init_urbs(dev);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -790,6 +794,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
|
|||
reg |= RTL818X_CMD_TX_ENABLE;
|
||||
reg |= RTL818X_CMD_RX_ENABLE;
|
||||
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -801,6 +806,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
|
|||
struct sk_buff *skb;
|
||||
u32 reg;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
|
||||
|
||||
reg = rtl818x_ioread8(priv, &priv->map->CMD);
|
||||
|
@ -820,7 +826,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
|
|||
usb_kill_urb(info->urb);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
return;
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
}
|
||||
|
||||
static int rtl8187_add_interface(struct ieee80211_hw *dev,
|
||||
|
@ -840,6 +846,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
priv->vif = conf->vif;
|
||||
|
||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
|
||||
|
@ -848,6 +855,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
|
|||
((u8 *)conf->mac_addr)[i]);
|
||||
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
|
||||
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -855,8 +863,10 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
|
|||
struct ieee80211_if_init_conf *conf)
|
||||
{
|
||||
struct rtl8187_priv *priv = dev->priv;
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
priv->mode = IEEE80211_IF_TYPE_MNTR;
|
||||
priv->vif = NULL;
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
}
|
||||
|
||||
static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
|
||||
|
@ -864,6 +874,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
|
|||
struct rtl8187_priv *priv = dev->priv;
|
||||
u32 reg;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
|
||||
/* Enable TX loopback on MAC level to avoid TX during channel
|
||||
* changes, as this has be seen to causes problems and the
|
||||
|
@ -896,6 +907,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
|
|||
rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
|
||||
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
|
||||
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -907,6 +919,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev,
|
|||
int i;
|
||||
u8 reg;
|
||||
|
||||
mutex_lock(&priv->conf_mutex);
|
||||
for (i = 0; i < ETH_ALEN; i++)
|
||||
rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
|
||||
|
||||
|
@ -920,6 +933,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev,
|
|||
rtl818x_iowrite8(priv, &priv->map->MSR, reg);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->conf_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1187,6 +1201,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
|
|||
printk(KERN_ERR "rtl8187: Cannot register device\n");
|
||||
goto err_free_dev;
|
||||
}
|
||||
mutex_init(&priv->conf_mutex);
|
||||
|
||||
printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n",
|
||||
wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
|
||||
|
|
|
@ -586,6 +586,7 @@ struct ieee80211_local {
|
|||
struct timer_list sta_cleanup;
|
||||
|
||||
unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)];
|
||||
unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)];
|
||||
struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES];
|
||||
struct tasklet_struct tx_pending_tasklet;
|
||||
|
||||
|
|
|
@ -1060,13 +1060,14 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx,
|
|||
static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
|
||||
struct ieee80211_tx_data *tx)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_tx_info *info;
|
||||
int ret, i;
|
||||
|
||||
if (netif_subqueue_stopped(local->mdev, skb))
|
||||
return IEEE80211_TX_AGAIN;
|
||||
|
||||
if (skb) {
|
||||
if (netif_subqueue_stopped(local->mdev, skb))
|
||||
return IEEE80211_TX_AGAIN;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
|
||||
"TX to low-level driver", skb);
|
||||
ret = local->ops->tx(local_to_hw(local), skb);
|
||||
|
@ -1215,6 +1216,7 @@ retry:
|
|||
|
||||
if (ret == IEEE80211_TX_FRAG_AGAIN)
|
||||
skb = NULL;
|
||||
|
||||
set_bit(queue, local->queues_pending);
|
||||
smp_mb();
|
||||
/*
|
||||
|
@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data)
|
|||
netif_tx_lock_bh(dev);
|
||||
for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) {
|
||||
/* Check that this queue is ok */
|
||||
if (__netif_subqueue_stopped(local->mdev, i))
|
||||
if (__netif_subqueue_stopped(local->mdev, i) &&
|
||||
!test_bit(i, local->queues_pending_run))
|
||||
continue;
|
||||
|
||||
if (!test_bit(i, local->queues_pending)) {
|
||||
clear_bit(i, local->queues_pending_run);
|
||||
ieee80211_wake_queue(&local->hw, i);
|
||||
continue;
|
||||
}
|
||||
|
||||
clear_bit(i, local->queues_pending_run);
|
||||
netif_start_subqueue(local->mdev, i);
|
||||
|
||||
store = &local->pending_packet[i];
|
||||
tx.extra_frag = store->extra_frag;
|
||||
tx.num_extra_frag = store->num_extra_frag;
|
||||
|
|
|
@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
|
|||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
|
||||
if (test_bit(queue, local->queues_pending)) {
|
||||
set_bit(queue, local->queues_pending_run);
|
||||
tasklet_schedule(&local->tx_pending_tasklet);
|
||||
} else {
|
||||
netif_wake_subqueue(local->mdev, queue);
|
||||
|
|
|
@ -109,6 +109,25 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB);
|
|||
static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX);
|
||||
static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN);
|
||||
|
||||
static void rfkill_schedule_evsw_rfkillall(int state)
|
||||
{
|
||||
/* EVERY radio type. state != 0 means radios ON */
|
||||
/* handle EPO (emergency power off) through shortcut */
|
||||
if (state) {
|
||||
rfkill_schedule_set(&rfkill_wwan,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_wimax,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_uwb,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_bt,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_wlan,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
} else
|
||||
rfkill_schedule_epo();
|
||||
}
|
||||
|
||||
static void rfkill_event(struct input_handle *handle, unsigned int type,
|
||||
unsigned int code, int data)
|
||||
{
|
||||
|
@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
|
|||
} else if (type == EV_SW) {
|
||||
switch (code) {
|
||||
case SW_RFKILL_ALL:
|
||||
/* EVERY radio type. data != 0 means radios ON */
|
||||
/* handle EPO (emergency power off) through shortcut */
|
||||
if (data) {
|
||||
rfkill_schedule_set(&rfkill_wwan,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_wimax,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_uwb,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_bt,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
rfkill_schedule_set(&rfkill_wlan,
|
||||
RFKILL_STATE_UNBLOCKED);
|
||||
} else
|
||||
rfkill_schedule_epo();
|
||||
rfkill_schedule_evsw_rfkillall(data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
handle->handler = handler;
|
||||
handle->name = "rfkill";
|
||||
|
||||
/* causes rfkill_start() to be called */
|
||||
error = input_register_handle(handle);
|
||||
if (error)
|
||||
goto err_free_handle;
|
||||
|
@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
|
|||
return error;
|
||||
}
|
||||
|
||||
static void rfkill_start(struct input_handle *handle)
|
||||
{
|
||||
/* Take event_lock to guard against configuration changes, we
|
||||
* should be able to deal with concurrency with rfkill_event()
|
||||
* just fine (which event_lock will also avoid). */
|
||||
spin_lock_irq(&handle->dev->event_lock);
|
||||
|
||||
if (test_bit(EV_SW, handle->dev->evbit)) {
|
||||
if (test_bit(SW_RFKILL_ALL, handle->dev->swbit))
|
||||
rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL,
|
||||
handle->dev->sw));
|
||||
/* add resync for further EV_SW events here */
|
||||
}
|
||||
|
||||
spin_unlock_irq(&handle->dev->event_lock);
|
||||
}
|
||||
|
||||
static void rfkill_disconnect(struct input_handle *handle)
|
||||
{
|
||||
input_close_device(handle);
|
||||
|
@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = {
|
|||
.event = rfkill_event,
|
||||
.connect = rfkill_connect,
|
||||
.disconnect = rfkill_disconnect,
|
||||
.start = rfkill_start,
|
||||
.name = "rfkill",
|
||||
.id_table = rfkill_ids,
|
||||
};
|
||||
|
|
|
@ -105,6 +105,16 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
|
|||
#endif /* CONFIG_RFKILL_LEDS */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RFKILL_LEDS
|
||||
static void rfkill_led_trigger_activate(struct led_classdev *led)
|
||||
{
|
||||
struct rfkill *rfkill = container_of(led->trigger,
|
||||
struct rfkill, led_trigger);
|
||||
|
||||
rfkill_led_trigger(rfkill, rfkill->state);
|
||||
}
|
||||
#endif /* CONFIG_RFKILL_LEDS */
|
||||
|
||||
static void notify_rfkill_state_change(struct rfkill *rfkill)
|
||||
{
|
||||
blocking_notifier_call_chain(&rfkill_notifier_list,
|
||||
|
@ -589,7 +599,10 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill)
|
|||
#ifdef CONFIG_RFKILL_LEDS
|
||||
int error;
|
||||
|
||||
rfkill->led_trigger.name = rfkill->dev.bus_id;
|
||||
if (!rfkill->led_trigger.name)
|
||||
rfkill->led_trigger.name = rfkill->dev.bus_id;
|
||||
if (!rfkill->led_trigger.activate)
|
||||
rfkill->led_trigger.activate = rfkill_led_trigger_activate;
|
||||
error = led_trigger_register(&rfkill->led_trigger);
|
||||
if (error)
|
||||
rfkill->led_trigger.name = NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче