Commit e9e80ea5 authored by David S. Miller's avatar David S. Miller
parents 2b12a4c5 56decd3c
...@@ -649,6 +649,7 @@ config RTL8187 ...@@ -649,6 +649,7 @@ config RTL8187
Trendnet TEW-424UB Trendnet TEW-424UB
ASUS P5B Deluxe ASUS P5B Deluxe
Toshiba Satellite Pro series of laptops Toshiba Satellite Pro series of laptops
Asus Wireless Link
Thanks to Realtek for their support! Thanks to Realtek for their support!
......
...@@ -186,11 +186,13 @@ struct ath5k_srev_name { ...@@ -186,11 +186,13 @@ struct ath5k_srev_name {
#define AR5K_SREV_RAD_2111 0x20 #define AR5K_SREV_RAD_2111 0x20
#define AR5K_SREV_RAD_5112 0x30 #define AR5K_SREV_RAD_5112 0x30
#define AR5K_SREV_RAD_5112A 0x35 #define AR5K_SREV_RAD_5112A 0x35
#define AR5K_SREV_RAD_5112B 0x36
#define AR5K_SREV_RAD_2112 0x40 #define AR5K_SREV_RAD_2112 0x40
#define AR5K_SREV_RAD_2112A 0x45 #define AR5K_SREV_RAD_2112A 0x45
#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */ #define AR5K_SREV_RAD_2112B 0x46
#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ #define AR5K_SREV_RAD_SC0 0x50 /* Found on 2413/2414 */
#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */ #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 */ #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
/* IEEE defs */ /* IEEE defs */
......
...@@ -2170,6 +2170,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) ...@@ -2170,6 +2170,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
ath5k_hw_set_intr(ah, 0); ath5k_hw_set_intr(ah, 0);
sc->bmisscount = 0; sc->bmisscount = 0;
sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
if (sc->opmode == IEEE80211_IF_TYPE_STA) { if (sc->opmode == IEEE80211_IF_TYPE_STA) {
sc->imask |= AR5K_INT_BMISS; sc->imask |= AR5K_INT_BMISS;
......
...@@ -129,7 +129,7 @@ static struct reg regs[] = { ...@@ -129,7 +129,7 @@ static struct reg regs[] = {
REG_STRUCT_INIT(AR5K_CPC1), REG_STRUCT_INIT(AR5K_CPC1),
REG_STRUCT_INIT(AR5K_CPC2), REG_STRUCT_INIT(AR5K_CPC2),
REG_STRUCT_INIT(AR5K_CPC3), 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_RESET_CTL),
REG_STRUCT_INIT(AR5K_SLEEP_CTL), REG_STRUCT_INIT(AR5K_SLEEP_CTL),
REG_STRUCT_INIT(AR5K_INTPEND), REG_STRUCT_INIT(AR5K_INTPEND),
......
...@@ -63,7 +63,6 @@ ...@@ -63,7 +63,6 @@
struct ath5k_softc; struct ath5k_softc;
struct ath5k_hw; struct ath5k_hw;
struct ieee80211_hw_mode;
struct sk_buff; struct sk_buff;
struct ath5k_buf; struct ath5k_buf;
......
This diff is collapsed.
...@@ -489,7 +489,7 @@ static const struct ath5k_ini ar5212_ini[] = { ...@@ -489,7 +489,7 @@ static const struct ath5k_ini ar5212_ini[] = {
{ AR5K_QUEUE_TXDP(9), 0x00000000 }, { AR5K_QUEUE_TXDP(9), 0x00000000 },
{ AR5K_DCU_FP, 0x00000000 }, { AR5K_DCU_FP, 0x00000000 },
{ AR5K_DCU_TXP, 0x00000000 }, { AR5K_DCU_TXP, 0x00000000 },
{ AR5K_DCU_TX_FILTER, 0x00000000 }, { AR5K_DCU_TX_FILTER_0_BASE, 0x00000000 },
/* Unknown table */ /* Unknown table */
{ 0x1078, 0x00000000 }, { 0x1078, 0x00000000 },
{ 0x10b8, 0x00000000 }, { 0x10b8, 0x00000000 },
...@@ -679,7 +679,7 @@ static const struct ath5k_ini ar5212_ini[] = { ...@@ -679,7 +679,7 @@ static const struct ath5k_ini ar5212_ini[] = {
{ AR5K_PHY(645), 0x00106c10 }, { AR5K_PHY(645), 0x00106c10 },
{ AR5K_PHY(646), 0x009c4060 }, { AR5K_PHY(646), 0x009c4060 },
{ AR5K_PHY(647), 0x1483800a }, { AR5K_PHY(647), 0x1483800a },
/* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */ /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413/2425 */
{ AR5K_PHY(648), 0x01831061 }, { AR5K_PHY(648), 0x01831061 },
{ AR5K_PHY(649), 0x00000400 }, { AR5K_PHY(649), 0x00000400 },
/*{ AR5K_PHY(650), 0x000001b5 },*/ /*{ AR5K_PHY(650), 0x000001b5 },*/
......
...@@ -1020,6 +1020,74 @@ static const struct ath5k_ini_rfgain rfgain_2413[] = { ...@@ -1020,6 +1020,74 @@ static const struct ath5k_ini_rfgain rfgain_2413[] = {
{ AR5K_RF_GAIN(63), { 0x000000f9 } }, { 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 = { static const struct ath5k_gain_opt rfgain_opt_5112 = {
1, 1,
8, 8,
...@@ -1588,8 +1656,8 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) ...@@ -1588,8 +1656,8 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
freq = 0; /* only 2Ghz */ freq = 0; /* only 2Ghz */
break; break;
case AR5K_RF2425: case AR5K_RF2425:
ath5k_rfg = rfgain_2413; ath5k_rfg = rfgain_2425;
size = ARRAY_SIZE(rfgain_2413); size = ARRAY_SIZE(rfgain_2425);
freq = 0; /* only 2Ghz */ freq = 0; /* only 2Ghz */
break; break;
default: default:
...@@ -1830,9 +1898,6 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, ...@@ -1830,9 +1898,6 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
data = data0 = data1 = data2 = 0; data = data0 = data1 = data2 = 0;
c = channel->center_freq; c = channel->center_freq;
/*
* Set the channel on the RF5112 or newer
*/
if (c < 4800) { if (c < 4800) {
if (!((c - 2224) % 5)) { if (!((c - 2224) % 5)) {
data0 = ((2 * (c - 704)) - 3040) / 10; data0 = ((2 * (c - 704)) - 3040) / 10;
...@@ -1844,7 +1909,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, ...@@ -1844,7 +1909,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
return -EINVAL; return -EINVAL;
data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
} else { } else if ((c - (c % 5)) != 2 || c > 5435) {
if (!(c % 20) && c >= 5120) { if (!(c % 20) && c >= 5120) {
data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
data2 = ath5k_hw_bitswap(3, 2); data2 = ath5k_hw_bitswap(3, 2);
...@@ -1856,6 +1921,9 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, ...@@ -1856,6 +1921,9 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
data2 = ath5k_hw_bitswap(1, 2); data2 = ath5k_hw_bitswap(1, 2);
} else } else
return -EINVAL; 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; data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
...@@ -1866,6 +1934,45 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, ...@@ -1866,6 +1934,45 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
return 0; 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 * Set a channel on the radio chip
*/ */
...@@ -1895,6 +2002,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) ...@@ -1895,6 +2002,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
case AR5K_RF5111: case AR5K_RF5111:
ret = ath5k_hw_rf5111_channel(ah, channel); ret = ath5k_hw_rf5111_channel(ah, channel);
break; break;
case AR5K_RF2425:
ret = ath5k_hw_rf2425_channel(ah, channel);
break;
default: default:
ret = ath5k_hw_rf5112_channel(ah, channel); ret = ath5k_hw_rf5112_channel(ah, channel);
break; break;
...@@ -1903,6 +2013,15 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) ...@@ -1903,6 +2013,15 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
if (ret) if (ret)
return 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.center_freq = channel->center_freq;
ah->ah_current_channel.hw_value = channel->hw_value; ah->ah_current_channel.hw_value = channel->hw_value;
ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; 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) ...@@ -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 \ * 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 * &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 int
ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) 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) ...@@ -1942,7 +2063,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
s32 noise_floor; s32 noise_floor;
/* /*
* Enable noise floor calibration and wait until completion * Enable noise floor calibration
*/ */
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
AR5K_PHY_AGCCTL_NF); AR5K_PHY_AGCCTL_NF);
...@@ -1952,7 +2073,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) ...@@ -1952,7 +2073,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
if (ret) { if (ret) {
ATH5K_ERR(ah->ah_sc, ATH5K_ERR(ah->ah_sc,
"noise floor calibration timeout (%uMHz)\n", freq); "noise floor calibration timeout (%uMHz)\n", freq);
return ret; return -EAGAIN;
} }
/* Wait until the noise floor is calibrated and read the value */ /* 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) ...@@ -1974,7 +2095,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
ATH5K_ERR(ah->ah_sc, ATH5K_ERR(ah->ah_sc,
"noise floor calibration failed (%uMHz)\n", freq); "noise floor calibration failed (%uMHz)\n", freq);
return -EIO; return -EAGAIN;
} }
ah->ah_noise_floor = noise_floor; ah->ah_noise_floor = noise_floor;
...@@ -2087,38 +2208,66 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, ...@@ -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, static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
struct ieee80211_channel *channel) struct ieee80211_channel *channel)
{ {
u32 i_pwr, q_pwr; u32 i_pwr, q_pwr;
s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
int i;
ATH5K_TRACE(ah->ah_sc); ATH5K_TRACE(ah->ah_sc);
if (!ah->ah_calibration || 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; 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; 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) if (i_coffd == 0 || q_coffd == 0)
goto done; goto done;
i_coff = ((-iq_corr) / i_coffd) & 0x3f; 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 | 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)); ((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: 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); ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
/* Request RF gain */ /* Request RF gain */
......
This diff is collapsed.
...@@ -305,9 +305,10 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) ...@@ -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)) #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 */ /* 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_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) */ /* 16-bit direct write (low 4K) */
#define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs)) #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, ...@@ -710,10 +710,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
return; 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 */ /* Convert 3945's rssi indicator to dBm */
rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET; rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET;
...@@ -775,6 +772,11 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, ...@@ -775,6 +772,11 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
priv->last_rx_noise = rx_status.noise; 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) { switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) {
case IEEE80211_FTYPE_MGMT: case IEEE80211_FTYPE_MGMT:
switch (le16_to_cpu(header->frame_control) & switch (le16_to_cpu(header->frame_control) &
......
...@@ -962,16 +962,16 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) ...@@ -962,16 +962,16 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
if (ret) if (ret)
return ret; return ret;
if ((iwl_queue_space(q) < q->high_mark) if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
&& priv->mac80211_registered) {
if (wait_write_ptr) { if (wait_write_ptr) {
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
txq->need_update = 1; txq->need_update = 1;
iwl_txq_update_write_ptr(priv, txq); iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags); 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; return 0;
......
...@@ -297,9 +297,7 @@ static ssize_t lbs_rtap_set(struct device *dev, ...@@ -297,9 +297,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
lbs_add_rtap(priv); lbs_add_rtap(priv);
} }
priv->monitormode = monitor_mode; priv->monitormode = monitor_mode;
} } else {
else {
if (!priv->monitormode) if (!priv->monitormode)
return strlen(buf); return strlen(buf);
priv->monitormode = 0; priv->monitormode = 0;
...@@ -1242,8 +1240,6 @@ int lbs_start_card(struct lbs_private *priv) ...@@ -1242,8 +1240,6 @@ int lbs_start_card(struct lbs_private *priv)
lbs_pr_err("cannot register ethX device\n"); lbs_pr_err("cannot register ethX device\n");
goto done; 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); lbs_update_channel(priv);
...@@ -1275,6 +1271,13 @@ int lbs_start_card(struct lbs_private *priv) ...@@ -1275,6 +1271,13 @@ int lbs_start_card(struct lbs_private *priv)
if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
lbs_pr_err("cannot register lbs_mesh attribute\n"); 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) ...@@ -1306,9 +1309,9 @@ void lbs_stop_card(struct lbs_private *priv)
netif_carrier_off(priv->dev); netif_carrier_off(priv->dev);
lbs_debugfs_remove_one(priv); lbs_debugfs_remove_one(priv);
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
if (priv->mesh_tlv) { if (priv->mesh_tlv) {
device_remove_file(&dev->dev, &dev_attr_lbs_mesh); device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
} }
/* Flush pending command nodes */ /* Flush pending command nodes */
......
...@@ -2518,7 +2518,7 @@ enum { ...@@ -2518,7 +2518,7 @@ enum {
#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 #define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024
#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ #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) /* Maximum length for algorithm names (-1 for nul termination)
* used in ioctl() */ * used in ioctl() */
......
...@@ -1220,6 +1220,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, ...@@ -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_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); 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_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word); rt2x00_desc_write(txd, 0, word);
} }
......
...@@ -1376,6 +1376,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) ...@@ -1376,6 +1376,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word);
EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", 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); rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word);
...@@ -1384,9 +1387,6 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) ...@@ -1384,9 +1387,6 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41); rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41);
rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word);
EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", 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); rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word);
......
...@@ -368,6 +368,12 @@ struct rt2x00_intf { ...@@ -368,6 +368,12 @@ struct rt2x00_intf {
#define DELAYED_CONFIG_ERP 0x00000002 #define DELAYED_CONFIG_ERP 0x00000002
#define DELAYED_LED_ASSOC 0x00000004 #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; u16 seqno;
}; };
......
...@@ -254,6 +254,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, ...@@ -254,6 +254,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
libconf.ant.rx = default_ant->rx; libconf.ant.rx = default_ant->rx;
else if (active_ant->rx == ANTENNA_SW_DIVERSITY) else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
libconf.ant.rx = ANTENNA_B; libconf.ant.rx = ANTENNA_B;
else
libconf.ant.rx = active_ant->rx;
if (conf->antenna_sel_tx) if (conf->antenna_sel_tx)
libconf.ant.tx = conf->antenna_sel_tx; libconf.ant.tx = conf->antenna_sel_tx;
...@@ -261,6 +263,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, ...@@ -261,6 +263,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
libconf.ant.tx = default_ant->tx; libconf.ant.tx = default_ant->tx;
else if (active_ant->tx == ANTENNA_SW_DIVERSITY) else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
libconf.ant.tx = ANTENNA_B; libconf.ant.tx = ANTENNA_B;
else
libconf.ant.tx = active_ant->tx;
} }
if (flags & CONFIG_UPDATE_SLOT_TIME) { if (flags & CONFIG_UPDATE_SLOT_TIME) {
......
...@@ -372,9 +372,6 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \ ...@@ -372,9 +372,6 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \
if (*offset) \ if (*offset) \
return 0; \ return 0; \
\ \
if (!capable(CAP_NET_ADMIN)) \
return -EPERM; \
\
if (intf->offset_##__name >= debug->__name.word_count) \ if (intf->offset_##__name >= debug->__name.word_count) \
return -EINVAL; \ return -EINVAL; \
\ \
...@@ -454,7 +451,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name, ...@@ -454,7 +451,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name,
data += sprintf(data, "compiled: %s %s\n", __DATE__, __TIME__); data += sprintf(data, "compiled: %s %s\n", __DATE__, __TIME__);
blob->size = strlen(blob->data); 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, static struct dentry *rt2x00debug_create_file_chipset(const char *name,
...@@ -482,7 +479,7 @@ 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); data += sprintf(data, "rf length: %d\n", debug->rf.word_count);
blob->size = strlen(blob->data); 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) void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
...@@ -517,7 +514,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) ...@@ -517,7 +514,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
if (IS_ERR(intf->chipset_entry)) if (IS_ERR(intf->chipset_entry))
goto exit; 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, intf->driver_folder, intf,
&rt2x00debug_fop_dev_flags); &rt2x00debug_fop_dev_flags);
if (IS_ERR(intf->dev_flags)) if (IS_ERR(intf->dev_flags))
...@@ -532,7 +529,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) ...@@ -532,7 +529,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
({ \ ({ \
(__intf)->__name##_off_entry = \ (__intf)->__name##_off_entry = \
debugfs_create_u32(__stringify(__name) "_offset", \ debugfs_create_u32(__stringify(__name) "_offset", \
S_IRUGO | S_IWUSR, \ S_IRUSR | S_IWUSR, \
(__intf)->register_folder, \ (__intf)->register_folder, \
&(__intf)->offset_##__name); \ &(__intf)->offset_##__name); \
if (IS_ERR((__intf)->__name##_off_entry)) \ if (IS_ERR((__intf)->__name##_off_entry)) \
...@@ -540,7 +537,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) ...@@ -540,7 +537,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
\ \
(__intf)->__name##_val_entry = \ (__intf)->__name##_val_entry = \
debugfs_create_file(__stringify(__name) "_value", \ debugfs_create_file(__stringify(__name) "_value", \
S_IRUGO | S_IWUSR, \ S_IRUSR | S_IWUSR, \
(__intf)->register_folder, \ (__intf)->register_folder, \
(__intf), &rt2x00debug_fop_##__name);\ (__intf), &rt2x00debug_fop_##__name);\
if (IS_ERR((__intf)->__name##_val_entry)) \ if (IS_ERR((__intf)->__name##_val_entry)) \
...@@ -560,7 +557,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) ...@@ -560,7 +557,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
goto exit; goto exit;
intf->queue_frame_dump_entry = 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); intf, &rt2x00debug_fop_queue_dump);
if (IS_ERR(intf->queue_frame_dump_entry)) if (IS_ERR(intf->queue_frame_dump_entry))
goto exit; goto exit;
...@@ -569,7 +566,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) ...@@ -569,7 +566,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
init_waitqueue_head(&intf->frame_dump_waitqueue); init_waitqueue_head(&intf->frame_dump_waitqueue);
intf->queue_stats_entry = 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); intf, &rt2x00debug_fop_queue_stats);
return; return;
......
...@@ -247,6 +247,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, ...@@ -247,6 +247,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
rt2x00dev->intf_sta_count++; rt2x00dev->intf_sta_count++;
spin_lock_init(&intf->lock); spin_lock_init(&intf->lock);
spin_lock_init(&intf->seqlock);
intf->beacon = entry; intf->beacon = entry;
if (conf->type == IEEE80211_IF_TYPE_AP) if (conf->type == IEEE80211_IF_TYPE_AP)
......
...@@ -128,6 +128,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, ...@@ -128,6 +128,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
unsigned int data_length; unsigned int data_length;
unsigned int duration; unsigned int duration;
unsigned int residual; unsigned int residual;
unsigned long irqflags;
memset(txdesc, 0, sizeof(*txdesc)); memset(txdesc, 0, sizeof(*txdesc));
...@@ -213,14 +214,14 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, ...@@ -213,14 +214,14 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
* sequence counter given by mac80211. * sequence counter given by mac80211.
*/ */
if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 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)) if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
intf->seqno += 0x10; intf->seqno += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(intf->seqno); 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); __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
} }
......
...@@ -1003,6 +1003,11 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, ...@@ -1003,6 +1003,11 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
return -EBUSY; return -EBUSY;
} }
/*
* Hardware needs another millisecond before it is ready.
*/
msleep(1);
/* /*
* Reset MAC and BBP registers. * Reset MAC and BBP registers.
*/ */
......
...@@ -94,6 +94,10 @@ struct rtl8187_priv { ...@@ -94,6 +94,10 @@ struct rtl8187_priv {
const struct rtl818x_rf_ops *rf; const struct rtl818x_rf_ops *rf;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
int mode; int mode;
/* The mutex protects the TX loopback state.
* Any attempt to set channels concurrently locks the device.
*/
struct mutex conf_mutex;
/* rtl8187 specific */ /* rtl8187 specific */
struct ieee80211_channel channels[14]; struct ieee80211_channel channels[14];
......
...@@ -31,6 +31,8 @@ MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); ...@@ -31,6 +31,8 @@ MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static struct usb_device_id rtl8187_table[] __devinitdata = { static struct usb_device_id rtl8187_table[] __devinitdata = {
/* Asus */
{USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187},
/* Realtek */ /* Realtek */
{USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187},
{USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B},
...@@ -726,6 +728,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) ...@@ -726,6 +728,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
if (ret) if (ret)
return ret; return ret;
mutex_lock(&priv->conf_mutex);
if (priv->is_rtl8187b) { if (priv->is_rtl8187b) {
reg = RTL818X_RX_CONF_MGMT | reg = RTL818X_RX_CONF_MGMT |
RTL818X_RX_CONF_DATA | RTL818X_RX_CONF_DATA |
...@@ -747,6 +750,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) ...@@ -747,6 +750,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
(7 << 0 /* long retry limit */) | (7 << 0 /* long retry limit */) |
(7 << 21 /* MAX TX DMA */)); (7 << 21 /* MAX TX DMA */));
rtl8187_init_urbs(dev); rtl8187_init_urbs(dev);
mutex_unlock(&priv->conf_mutex);
return 0; return 0;
} }
...@@ -790,6 +794,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) ...@@ -790,6 +794,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
reg |= RTL818X_CMD_TX_ENABLE; reg |= RTL818X_CMD_TX_ENABLE;
reg |= RTL818X_CMD_RX_ENABLE; reg |= RTL818X_CMD_RX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg); rtl818x_iowrite8(priv, &priv->map->CMD, reg);
mutex_unlock(&priv->conf_mutex);
return 0; return 0;
} }
...@@ -801,6 +806,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) ...@@ -801,6 +806,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
struct sk_buff *skb; struct sk_buff *skb;
u32 reg; u32 reg;
mutex_lock(&priv->conf_mutex);
rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
reg = rtl818x_ioread8(priv, &priv->map->CMD); reg = rtl818x_ioread8(priv, &priv->map->CMD);
...@@ -820,7 +826,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) ...@@ -820,7 +826,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
usb_kill_urb(info->urb); usb_kill_urb(info->urb);
kfree_skb(skb); kfree_skb(skb);
} }
return; mutex_unlock(&priv->conf_mutex);
} }
static int rtl8187_add_interface(struct ieee80211_hw *dev, static int rtl8187_add_interface(struct ieee80211_hw *dev,
...@@ -840,6 +846,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, ...@@ -840,6 +846,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
mutex_lock(&priv->conf_mutex);
priv->vif = conf->vif; priv->vif = conf->vif;
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
...@@ -848,6 +855,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, ...@@ -848,6 +855,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev,
((u8 *)conf->mac_addr)[i]); ((u8 *)conf->mac_addr)[i]);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
mutex_unlock(&priv->conf_mutex);
return 0; return 0;
} }
...@@ -855,8 +863,10 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev, ...@@ -855,8 +863,10 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf) struct ieee80211_if_init_conf *conf)
{ {
struct rtl8187_priv *priv = dev->priv; struct rtl8187_priv *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
priv->mode = IEEE80211_IF_TYPE_MNTR; priv->mode = IEEE80211_IF_TYPE_MNTR;
priv->vif = NULL; priv->vif = NULL;
mutex_unlock(&priv->conf_mutex);
} }
static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) 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) ...@@ -864,6 +874,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
struct rtl8187_priv *priv = dev->priv; struct rtl8187_priv *priv = dev->priv;
u32 reg; u32 reg;
mutex_lock(&priv->conf_mutex);
reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
/* Enable TX loopback on MAC level to avoid TX during channel /* Enable TX loopback on MAC level to avoid TX during channel
* changes, as this has be seen to causes problems and the * 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) ...@@ -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->ATIMTR_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100);
mutex_unlock(&priv->conf_mutex);
return 0; return 0;
} }
...@@ -907,6 +919,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, ...@@ -907,6 +919,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev,
int i; int i;
u8 reg; u8 reg;
mutex_lock(&priv->conf_mutex);
for (i = 0; i < ETH_ALEN; i++) for (i = 0; i < ETH_ALEN; i++)
rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
...@@ -920,6 +933,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, ...@@ -920,6 +933,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev,
rtl818x_iowrite8(priv, &priv->map->MSR, reg); rtl818x_iowrite8(priv, &priv->map->MSR, reg);
} }
mutex_unlock(&priv->conf_mutex);
return 0; return 0;
} }
...@@ -1187,6 +1201,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, ...@@ -1187,6 +1201,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
printk(KERN_ERR "rtl8187: Cannot register device\n"); printk(KERN_ERR "rtl8187: Cannot register device\n");
goto err_free_dev; goto err_free_dev;
} }
mutex_init(&priv->conf_mutex);
printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n", printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n",
wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
......
...@@ -586,6 +586,7 @@ struct ieee80211_local { ...@@ -586,6 +586,7 @@ struct ieee80211_local {
struct timer_list sta_cleanup; struct timer_list sta_cleanup;
unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; 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 ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES];
struct tasklet_struct tx_pending_tasklet; struct tasklet_struct tx_pending_tasklet;
......
...@@ -1060,13 +1060,14 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, ...@@ -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, static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb,
struct ieee80211_tx_data *tx) struct ieee80211_tx_data *tx)
{ {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info;
int ret, i; int ret, i;
if (netif_subqueue_stopped(local->mdev, skb))
return IEEE80211_TX_AGAIN;
if (skb) { 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), ieee80211_dump_frame(wiphy_name(local->hw.wiphy),
"TX to low-level driver", skb); "TX to low-level driver", skb);
ret = local->ops->tx(local_to_hw(local), skb); ret = local->ops->tx(local_to_hw(local), skb);
...@@ -1215,6 +1216,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) ...@@ -1215,6 +1216,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb)
if (ret == IEEE80211_TX_FRAG_AGAIN) if (ret == IEEE80211_TX_FRAG_AGAIN)
skb = NULL; skb = NULL;
set_bit(queue, local->queues_pending); set_bit(queue, local->queues_pending);
smp_mb(); smp_mb();
/* /*
...@@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data) ...@@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data)
netif_tx_lock_bh(dev); netif_tx_lock_bh(dev);
for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) {
/* Check that this queue is ok */ /* 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; continue;
if (!test_bit(i, local->queues_pending)) { if (!test_bit(i, local->queues_pending)) {
clear_bit(i, local->queues_pending_run);
ieee80211_wake_queue(&local->hw, i); ieee80211_wake_queue(&local->hw, i);
continue; continue;
} }
clear_bit(i, local->queues_pending_run);
netif_start_subqueue(local->mdev, i);
store = &local->pending_packet[i]; store = &local->pending_packet[i];
tx.extra_frag = store->extra_frag; tx.extra_frag = store->extra_frag;
tx.num_extra_frag = store->num_extra_frag; tx.num_extra_frag = store->num_extra_frag;
......
...@@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) ...@@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_local *local = hw_to_local(hw);
if (test_bit(queue, local->queues_pending)) { if (test_bit(queue, local->queues_pending)) {
set_bit(queue, local->queues_pending_run);
tasklet_schedule(&local->tx_pending_tasklet); tasklet_schedule(&local->tx_pending_tasklet);
} else { } else {
netif_wake_subqueue(local->mdev, queue); netif_wake_subqueue(local->mdev, queue);
......
...@@ -109,6 +109,25 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); ...@@ -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_wimax, RFKILL_TYPE_WIMAX);
static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); 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, static void rfkill_event(struct input_handle *handle, unsigned int type,
unsigned int code, int data) unsigned int code, int data)
{ {
...@@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, ...@@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type,
} else if (type == EV_SW) { } else if (type == EV_SW) {
switch (code) { switch (code) {
case SW_RFKILL_ALL: case SW_RFKILL_ALL:
/* EVERY radio type. data != 0 means radios ON */ rfkill_schedule_evsw_rfkillall(data);
/* 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();
break; break;
default: default:
break; break;
...@@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
handle->handler = handler; handle->handler = handler;
handle->name = "rfkill"; handle->name = "rfkill";
/* causes rfkill_start() to be called */
error = input_register_handle(handle); error = input_register_handle(handle);
if (error) if (error)
goto err_free_handle; goto err_free_handle;
...@@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, ...@@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev,
return error; 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) static void rfkill_disconnect(struct input_handle *handle)
{ {
input_close_device(handle); input_close_device(handle);
...@@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = { ...@@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = {
.event = rfkill_event, .event = rfkill_event,
.connect = rfkill_connect, .connect = rfkill_connect,
.disconnect = rfkill_disconnect, .disconnect = rfkill_disconnect,
.start = rfkill_start,
.name = "rfkill", .name = "rfkill",
.id_table = rfkill_ids, .id_table = rfkill_ids,
}; };
......
...@@ -105,6 +105,16 @@ static void rfkill_led_trigger(struct rfkill *rfkill, ...@@ -105,6 +105,16 @@ static void rfkill_led_trigger(struct rfkill *rfkill,
#endif /* CONFIG_RFKILL_LEDS */ #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) static void notify_rfkill_state_change(struct rfkill *rfkill)
{ {
blocking_notifier_call_chain(&rfkill_notifier_list, blocking_notifier_call_chain(&rfkill_notifier_list,
...@@ -589,7 +599,10 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill) ...@@ -589,7 +599,10 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill)
#ifdef CONFIG_RFKILL_LEDS #ifdef CONFIG_RFKILL_LEDS
int error; 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); error = led_trigger_register(&rfkill->led_trigger);
if (error) if (error)
rfkill->led_trigger.name = NULL; rfkill->led_trigger.name = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment