Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
820ae8a80e
|
@ -110,6 +110,8 @@ static struct usb_device_id ar9170_usb_ids[] = {
|
|||
{ USB_DEVICE(0x0409, 0x0249) },
|
||||
/* AVM FRITZ!WLAN USB Stick N 2.4 */
|
||||
{ USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY },
|
||||
/* Qwest/Actiontec 802AIN Wireless N USB Network Adapter */
|
||||
{ USB_DEVICE(0x1668, 0x1200) },
|
||||
|
||||
/* terminate */
|
||||
{}
|
||||
|
|
|
@ -1932,12 +1932,6 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
|
||||
sc->stats.rx_all_count++;
|
||||
|
||||
if (unlikely(rs.rs_more)) {
|
||||
ATH5K_WARN(sc, "unsupported jumbo\n");
|
||||
sc->stats.rxerr_jumbo++;
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (unlikely(rs.rs_status)) {
|
||||
if (rs.rs_status & AR5K_RXERR_CRC)
|
||||
sc->stats.rxerr_crc++;
|
||||
|
@ -1977,6 +1971,12 @@ ath5k_tasklet_rx(unsigned long data)
|
|||
sc->opmode != NL80211_IFTYPE_MONITOR)
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (unlikely(rs.rs_more)) {
|
||||
sc->stats.rxerr_jumbo++;
|
||||
goto next;
|
||||
|
||||
}
|
||||
accept:
|
||||
next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr);
|
||||
|
||||
|
|
|
@ -38,6 +38,9 @@
|
|||
#define AR_SWITCH_TABLE_ALL (0xfff)
|
||||
#define AR_SWITCH_TABLE_ALL_S (0)
|
||||
|
||||
#define LE16(x) __constant_cpu_to_le16(x)
|
||||
#define LE32(x) __constant_cpu_to_le32(x)
|
||||
|
||||
static const struct ar9300_eeprom ar9300_default = {
|
||||
.eepromVersion = 2,
|
||||
.templateVersion = 2,
|
||||
|
@ -45,7 +48,7 @@ static const struct ar9300_eeprom ar9300_default = {
|
|||
.custData = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
.baseEepHeader = {
|
||||
.regDmn = {0, 0x1f},
|
||||
.regDmn = { LE16(0), LE16(0x1f) },
|
||||
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
|
||||
.opCapFlags = {
|
||||
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
|
||||
|
@ -76,15 +79,15 @@ static const struct ar9300_eeprom ar9300_default = {
|
|||
.modalHeader2G = {
|
||||
/* ar9300_modal_eep_header 2g */
|
||||
/* 4 idle,t1,t2,b(4 bits per setting) */
|
||||
.antCtrlCommon = 0x110,
|
||||
.antCtrlCommon = LE32(0x110),
|
||||
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
|
||||
.antCtrlCommon2 = 0x22222,
|
||||
.antCtrlCommon2 = LE32(0x22222),
|
||||
|
||||
/*
|
||||
* antCtrlChain[AR9300_MAX_CHAINS]; 6 idle, t, r,
|
||||
* rx1, rx12, b (2 bits each)
|
||||
*/
|
||||
.antCtrlChain = {0x150, 0x150, 0x150},
|
||||
.antCtrlChain = { LE16(0x150), LE16(0x150), LE16(0x150) },
|
||||
|
||||
/*
|
||||
* xatten1DB[AR9300_MAX_CHAINS]; 3 xatten1_db
|
||||
|
@ -287,12 +290,12 @@ static const struct ar9300_eeprom ar9300_default = {
|
|||
},
|
||||
.modalHeader5G = {
|
||||
/* 4 idle,t1,t2,b (4 bits per setting) */
|
||||
.antCtrlCommon = 0x110,
|
||||
.antCtrlCommon = LE32(0x110),
|
||||
/* 4 ra1l1, ra2l1, ra1l2,ra2l2,ra12 */
|
||||
.antCtrlCommon2 = 0x22222,
|
||||
.antCtrlCommon2 = LE32(0x22222),
|
||||
/* antCtrlChain 6 idle, t,r,rx1,rx12,b (2 bits each) */
|
||||
.antCtrlChain = {
|
||||
0x000, 0x000, 0x000,
|
||||
LE16(0x000), LE16(0x000), LE16(0x000),
|
||||
},
|
||||
/* xatten1DB 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
|
||||
.xatten1DB = {0, 0, 0},
|
||||
|
@ -620,9 +623,9 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
|
|||
case EEP_MAC_MSW:
|
||||
return eep->macAddr[4] << 8 | eep->macAddr[5];
|
||||
case EEP_REG_0:
|
||||
return pBase->regDmn[0];
|
||||
return le16_to_cpu(pBase->regDmn[0]);
|
||||
case EEP_REG_1:
|
||||
return pBase->regDmn[1];
|
||||
return le16_to_cpu(pBase->regDmn[1]);
|
||||
case EEP_OP_CAP:
|
||||
return pBase->deviceCap;
|
||||
case EEP_OP_MODE:
|
||||
|
@ -640,93 +643,80 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
|
|||
/* Bit 4 is internal regulator flag */
|
||||
return (pBase->featureEnable & 0x10) >> 4;
|
||||
case EEP_SWREG:
|
||||
return pBase->swreg;
|
||||
return le32_to_cpu(pBase->swreg);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
static void ar9300_swap_eeprom(struct ar9300_eeprom *eep)
|
||||
static bool ar9300_eeprom_read_byte(struct ath_common *common, int address,
|
||||
u8 *buffer)
|
||||
{
|
||||
u32 dword;
|
||||
u16 word;
|
||||
int i;
|
||||
u16 val;
|
||||
|
||||
word = swab16(eep->baseEepHeader.regDmn[0]);
|
||||
eep->baseEepHeader.regDmn[0] = word;
|
||||
if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
|
||||
return false;
|
||||
|
||||
word = swab16(eep->baseEepHeader.regDmn[1]);
|
||||
eep->baseEepHeader.regDmn[1] = word;
|
||||
|
||||
dword = swab32(eep->baseEepHeader.swreg);
|
||||
eep->baseEepHeader.swreg = dword;
|
||||
|
||||
dword = swab32(eep->modalHeader2G.antCtrlCommon);
|
||||
eep->modalHeader2G.antCtrlCommon = dword;
|
||||
|
||||
dword = swab32(eep->modalHeader2G.antCtrlCommon2);
|
||||
eep->modalHeader2G.antCtrlCommon2 = dword;
|
||||
|
||||
dword = swab32(eep->modalHeader5G.antCtrlCommon);
|
||||
eep->modalHeader5G.antCtrlCommon = dword;
|
||||
|
||||
dword = swab32(eep->modalHeader5G.antCtrlCommon2);
|
||||
eep->modalHeader5G.antCtrlCommon2 = dword;
|
||||
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
word = swab16(eep->modalHeader2G.antCtrlChain[i]);
|
||||
eep->modalHeader2G.antCtrlChain[i] = word;
|
||||
|
||||
word = swab16(eep->modalHeader5G.antCtrlChain[i]);
|
||||
eep->modalHeader5G.antCtrlChain[i] = word;
|
||||
}
|
||||
*buffer = (val >> (8 * (address % 2))) & 0xff;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ar9300_hw_read_eeprom(struct ath_hw *ah,
|
||||
long address, u8 *buffer, int many)
|
||||
static bool ar9300_eeprom_read_word(struct ath_common *common, int address,
|
||||
u8 *buffer)
|
||||
{
|
||||
int i;
|
||||
u8 value[2];
|
||||
unsigned long eepAddr;
|
||||
unsigned long byteAddr;
|
||||
u16 *svalue;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u16 val;
|
||||
|
||||
if ((address < 0) || ((address + many) > AR9300_EEPROM_SIZE - 1)) {
|
||||
if (unlikely(!ath9k_hw_nvram_read(common, address / 2, &val)))
|
||||
return false;
|
||||
|
||||
buffer[0] = val >> 8;
|
||||
buffer[1] = val & 0xff;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ar9300_read_eeprom(struct ath_hw *ah, int address, u8 *buffer,
|
||||
int count)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int i;
|
||||
|
||||
if ((address < 0) || ((address + count) / 2 > AR9300_EEPROM_SIZE - 1)) {
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"eeprom address not in range\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < many; i++) {
|
||||
eepAddr = (u16) (address + i) / 2;
|
||||
byteAddr = (u16) (address + i) % 2;
|
||||
svalue = (u16 *) value;
|
||||
if (!ath9k_hw_nvram_read(common, eepAddr, svalue)) {
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"unable to read eeprom region\n");
|
||||
return false;
|
||||
}
|
||||
*svalue = le16_to_cpu(*svalue);
|
||||
buffer[i] = value[byteAddr];
|
||||
/*
|
||||
* Since we're reading the bytes in reverse order from a little-endian
|
||||
* word stream, an even address means we only use the lower half of
|
||||
* the 16-bit word at that address
|
||||
*/
|
||||
if (address % 2 == 0) {
|
||||
if (!ar9300_eeprom_read_byte(common, address--, buffer++))
|
||||
goto error;
|
||||
|
||||
count--;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < count / 2; i++) {
|
||||
if (!ar9300_eeprom_read_word(common, address, buffer))
|
||||
goto error;
|
||||
|
||||
static bool ar9300_read_eeprom(struct ath_hw *ah,
|
||||
int address, u8 *buffer, int many)
|
||||
{
|
||||
int it;
|
||||
address -= 2;
|
||||
buffer += 2;
|
||||
}
|
||||
|
||||
if (count % 2)
|
||||
if (!ar9300_eeprom_read_byte(common, address, buffer))
|
||||
goto error;
|
||||
|
||||
for (it = 0; it < many; it++)
|
||||
if (!ar9300_hw_read_eeprom(ah,
|
||||
(address - it),
|
||||
(buffer + it), 1))
|
||||
return false;
|
||||
return true;
|
||||
|
||||
error:
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"unable to read eeprom region at offset %d\n", address);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ar9300_comp_hdr_unpack(u8 *best, int *code, int *reference,
|
||||
|
@ -927,30 +917,13 @@ fail:
|
|||
*/
|
||||
static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
|
||||
{
|
||||
u8 *mptr = NULL;
|
||||
int mdata_size;
|
||||
u8 *mptr = (u8 *) &ah->eeprom.ar9300_eep;
|
||||
|
||||
mptr = (u8 *) &ah->eeprom.ar9300_eep;
|
||||
mdata_size = sizeof(struct ar9300_eeprom);
|
||||
if (ar9300_eeprom_restore_internal(ah, mptr,
|
||||
sizeof(struct ar9300_eeprom)) < 0)
|
||||
return false;
|
||||
|
||||
if (mptr && mdata_size > 0) {
|
||||
/* At this point, mptr points to the eeprom data structure
|
||||
* in it's "default" state. If this is big endian, swap the
|
||||
* data structures back to "little endian"
|
||||
*/
|
||||
/* First swap, default to Little Endian */
|
||||
#ifdef __BIG_ENDIAN
|
||||
ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
|
||||
#endif
|
||||
if (ar9300_eeprom_restore_internal(ah, mptr, mdata_size) >= 0)
|
||||
return true;
|
||||
|
||||
/* Second Swap, back to Big Endian */
|
||||
#ifdef __BIG_ENDIAN
|
||||
ar9300_swap_eeprom((struct ar9300_eeprom *)mptr);
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* XXX: review hardware docs */
|
||||
|
@ -998,21 +971,25 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
|
|||
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
|
||||
{
|
||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||
__le32 val;
|
||||
|
||||
if (is2ghz)
|
||||
return eep->modalHeader2G.antCtrlCommon;
|
||||
val = eep->modalHeader2G.antCtrlCommon;
|
||||
else
|
||||
return eep->modalHeader5G.antCtrlCommon;
|
||||
val = eep->modalHeader5G.antCtrlCommon;
|
||||
return le32_to_cpu(val);
|
||||
}
|
||||
|
||||
static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
|
||||
{
|
||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||
__le32 val;
|
||||
|
||||
if (is2ghz)
|
||||
return eep->modalHeader2G.antCtrlCommon2;
|
||||
val = eep->modalHeader2G.antCtrlCommon2;
|
||||
else
|
||||
return eep->modalHeader5G.antCtrlCommon2;
|
||||
val = eep->modalHeader5G.antCtrlCommon2;
|
||||
return le32_to_cpu(val);
|
||||
}
|
||||
|
||||
static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
|
||||
|
@ -1020,15 +997,16 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
|
|||
bool is2ghz)
|
||||
{
|
||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||
__le16 val = 0;
|
||||
|
||||
if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
|
||||
if (is2ghz)
|
||||
return eep->modalHeader2G.antCtrlChain[chain];
|
||||
val = eep->modalHeader2G.antCtrlChain[chain];
|
||||
else
|
||||
return eep->modalHeader5G.antCtrlChain[chain];
|
||||
val = eep->modalHeader5G.antCtrlChain[chain];
|
||||
}
|
||||
|
||||
return 0;
|
||||
return le16_to_cpu(val);
|
||||
}
|
||||
|
||||
static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
|
||||
|
|
|
@ -169,7 +169,7 @@ enum CompressAlgorithm {
|
|||
};
|
||||
|
||||
struct ar9300_base_eep_hdr {
|
||||
u16 regDmn[2];
|
||||
__le16 regDmn[2];
|
||||
/* 4 bits tx and 4 bits rx */
|
||||
u8 txrxMask;
|
||||
struct eepFlags opCapFlags;
|
||||
|
@ -199,16 +199,16 @@ struct ar9300_base_eep_hdr {
|
|||
u8 rxBandSelectGpio;
|
||||
u8 txrxgain;
|
||||
/* SW controlled internal regulator fields */
|
||||
u32 swreg;
|
||||
__le32 swreg;
|
||||
} __packed;
|
||||
|
||||
struct ar9300_modal_eep_header {
|
||||
/* 4 idle, t1, t2, b (4 bits per setting) */
|
||||
u32 antCtrlCommon;
|
||||
__le32 antCtrlCommon;
|
||||
/* 4 ra1l1, ra2l1, ra1l2, ra2l2, ra12 */
|
||||
u32 antCtrlCommon2;
|
||||
__le32 antCtrlCommon2;
|
||||
/* 6 idle, t, r, rx1, rx12, b (2 bits each) */
|
||||
u16 antCtrlChain[AR9300_MAX_CHAINS];
|
||||
__le16 antCtrlChain[AR9300_MAX_CHAINS];
|
||||
/* 3 xatten1_db for AR9280 (0xa20c/b20c 5:0) */
|
||||
u8 xatten1DB[AR9300_MAX_CHAINS];
|
||||
/* 3 xatten1_margin for merlin (0xa20c/b20c 16:12 */
|
||||
|
|
|
@ -25,8 +25,11 @@ static const u32 ar9300_2p0_radio_postamble[][5] = {
|
|||
{0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800},
|
||||
{0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20},
|
||||
{0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
|
||||
{0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
|
||||
{0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008},
|
||||
};
|
||||
|
||||
static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = {
|
||||
|
@ -97,13 +100,13 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = {
|
|||
{0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
|
||||
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016048, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61},
|
||||
{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016448, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61},
|
||||
{0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
|
||||
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016848, 0x60001a61, 0x60001a61, 0x60001a61, 0x60001a61},
|
||||
{0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
|
@ -129,7 +132,7 @@ static const u32 ar9300_2p0_radio_core[][2] = {
|
|||
{0x00016040, 0x7f80fff8},
|
||||
{0x0001604c, 0x76d005b5},
|
||||
{0x00016050, 0x556cf031},
|
||||
{0x00016054, 0x43449440},
|
||||
{0x00016054, 0x13449440},
|
||||
{0x00016058, 0x0c51c92c},
|
||||
{0x0001605c, 0x3db7fffc},
|
||||
{0x00016060, 0xfffffffc},
|
||||
|
@ -152,12 +155,11 @@ static const u32 ar9300_2p0_radio_core[][2] = {
|
|||
{0x00016100, 0x3fffbe01},
|
||||
{0x00016104, 0xfff80000},
|
||||
{0x00016108, 0x00080010},
|
||||
{0x00016140, 0x10804008},
|
||||
{0x00016144, 0x02084080},
|
||||
{0x00016148, 0x00000000},
|
||||
{0x00016280, 0x058a0001},
|
||||
{0x00016284, 0x3d840208},
|
||||
{0x00016288, 0x01a20408},
|
||||
{0x00016288, 0x05a20408},
|
||||
{0x0001628c, 0x00038c07},
|
||||
{0x00016290, 0x40000004},
|
||||
{0x00016294, 0x458aa14f},
|
||||
|
@ -190,7 +192,7 @@ static const u32 ar9300_2p0_radio_core[][2] = {
|
|||
{0x00016440, 0x7f80fff8},
|
||||
{0x0001644c, 0x76d005b5},
|
||||
{0x00016450, 0x556cf031},
|
||||
{0x00016454, 0x43449440},
|
||||
{0x00016454, 0x13449440},
|
||||
{0x00016458, 0x0c51c92c},
|
||||
{0x0001645c, 0x3db7fffc},
|
||||
{0x00016460, 0xfffffffc},
|
||||
|
@ -199,7 +201,6 @@ static const u32 ar9300_2p0_radio_core[][2] = {
|
|||
{0x00016500, 0x3fffbe01},
|
||||
{0x00016504, 0xfff80000},
|
||||
{0x00016508, 0x00080010},
|
||||
{0x00016540, 0x10804008},
|
||||
{0x00016544, 0x02084080},
|
||||
{0x00016548, 0x00000000},
|
||||
{0x00016780, 0x00000000},
|
||||
|
@ -231,7 +232,7 @@ static const u32 ar9300_2p0_radio_core[][2] = {
|
|||
{0x00016840, 0x7f80fff8},
|
||||
{0x0001684c, 0x76d005b5},
|
||||
{0x00016850, 0x556cf031},
|
||||
{0x00016854, 0x43449440},
|
||||
{0x00016854, 0x13449440},
|
||||
{0x00016858, 0x0c51c92c},
|
||||
{0x0001685c, 0x3db7fffc},
|
||||
{0x00016860, 0xfffffffc},
|
||||
|
@ -240,7 +241,6 @@ static const u32 ar9300_2p0_radio_core[][2] = {
|
|||
{0x00016900, 0x3fffbe01},
|
||||
{0x00016904, 0xfff80000},
|
||||
{0x00016908, 0x00080010},
|
||||
{0x00016940, 0x10804008},
|
||||
{0x00016944, 0x02084080},
|
||||
{0x00016948, 0x00000000},
|
||||
{0x00016b80, 0x00000000},
|
||||
|
@ -588,12 +588,12 @@ static const u32 ar9200_merlin_2p0_radio_core[][2] = {
|
|||
|
||||
static const u32 ar9300_2p0_baseband_postamble[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800b},
|
||||
{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011},
|
||||
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e},
|
||||
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
|
||||
{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
|
||||
{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
|
||||
{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x00000b9c},
|
||||
{0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c},
|
||||
{0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044},
|
||||
{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
|
||||
{0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
|
||||
|
@ -604,8 +604,8 @@ static const u32 ar9300_2p0_baseband_postamble[][5] = {
|
|||
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
|
||||
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
|
||||
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
|
||||
{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
|
||||
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
|
||||
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
|
||||
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
|
||||
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
|
||||
{0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
|
||||
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
|
||||
|
@ -674,7 +674,7 @@ static const u32 ar9300_2p0_baseband_core[][2] = {
|
|||
{0x00009d10, 0x01834061},
|
||||
{0x00009d14, 0x00c0040b},
|
||||
{0x00009d18, 0x00000000},
|
||||
{0x00009e08, 0x0038233c},
|
||||
{0x00009e08, 0x0038230c},
|
||||
{0x00009e24, 0x990bb515},
|
||||
{0x00009e28, 0x0c6f0000},
|
||||
{0x00009e30, 0x06336f77},
|
||||
|
@ -901,13 +901,13 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
|
|||
{0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec},
|
||||
{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
|
||||
{0x00016048, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61},
|
||||
{0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
|
||||
{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
|
||||
{0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
|
||||
{0x00016448, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61},
|
||||
{0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
|
||||
{0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
|
||||
{0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
|
||||
{0x00016848, 0xae481a61, 0xae481a61, 0xae481a61, 0xae481a61},
|
||||
{0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001},
|
||||
{0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
|
||||
};
|
||||
|
||||
|
@ -979,13 +979,13 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = {
|
|||
{0x0000a5f8, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5fc, 0x7584ff56, 0x7584ff56, 0x56801eec, 0x56801eec},
|
||||
{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
|
||||
{0x00016048, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61},
|
||||
{0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
|
||||
{0x00016448, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61},
|
||||
{0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
|
||||
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
|
||||
{0x00016848, 0x8e481a61, 0x8e481a61, 0x8e481a61, 0x8e481a61},
|
||||
{0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001},
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
|
@ -995,22 +995,22 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a004, 0x00030002},
|
||||
{0x0000a008, 0x00050004},
|
||||
{0x0000a00c, 0x00810080},
|
||||
{0x0000a010, 0x01800082},
|
||||
{0x0000a014, 0x01820181},
|
||||
{0x0000a018, 0x01840183},
|
||||
{0x0000a01c, 0x01880185},
|
||||
{0x0000a020, 0x018a0189},
|
||||
{0x0000a024, 0x02850284},
|
||||
{0x0000a028, 0x02890288},
|
||||
{0x0000a02c, 0x028b028a},
|
||||
{0x0000a030, 0x028d028c},
|
||||
{0x0000a034, 0x02910290},
|
||||
{0x0000a038, 0x02930292},
|
||||
{0x0000a03c, 0x03910390},
|
||||
{0x0000a040, 0x03930392},
|
||||
{0x0000a044, 0x03950394},
|
||||
{0x0000a048, 0x00000396},
|
||||
{0x0000a04c, 0x00000000},
|
||||
{0x0000a010, 0x00830082},
|
||||
{0x0000a014, 0x01810180},
|
||||
{0x0000a018, 0x01830182},
|
||||
{0x0000a01c, 0x01850184},
|
||||
{0x0000a020, 0x01890188},
|
||||
{0x0000a024, 0x018b018a},
|
||||
{0x0000a028, 0x018d018c},
|
||||
{0x0000a02c, 0x01910190},
|
||||
{0x0000a030, 0x01930192},
|
||||
{0x0000a034, 0x01950194},
|
||||
{0x0000a038, 0x038a0196},
|
||||
{0x0000a03c, 0x038c038b},
|
||||
{0x0000a040, 0x0390038d},
|
||||
{0x0000a044, 0x03920391},
|
||||
{0x0000a048, 0x03940393},
|
||||
{0x0000a04c, 0x03960395},
|
||||
{0x0000a050, 0x00000000},
|
||||
{0x0000a054, 0x00000000},
|
||||
{0x0000a058, 0x00000000},
|
||||
|
@ -1023,14 +1023,14 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a074, 0x00000000},
|
||||
{0x0000a078, 0x00000000},
|
||||
{0x0000a07c, 0x00000000},
|
||||
{0x0000a080, 0x28282828},
|
||||
{0x0000a084, 0x21212128},
|
||||
{0x0000a088, 0x21212121},
|
||||
{0x0000a08c, 0x1c1c1c21},
|
||||
{0x0000a090, 0x1c1c1c1c},
|
||||
{0x0000a094, 0x17171c1c},
|
||||
{0x0000a098, 0x02020212},
|
||||
{0x0000a09c, 0x02020202},
|
||||
{0x0000a080, 0x22222229},
|
||||
{0x0000a084, 0x1d1d1d1d},
|
||||
{0x0000a088, 0x1d1d1d1d},
|
||||
{0x0000a08c, 0x1d1d1d1d},
|
||||
{0x0000a090, 0x171d1d1d},
|
||||
{0x0000a094, 0x11111717},
|
||||
{0x0000a098, 0x00030311},
|
||||
{0x0000a09c, 0x00000000},
|
||||
{0x0000a0a0, 0x00000000},
|
||||
{0x0000a0a4, 0x00000000},
|
||||
{0x0000a0a8, 0x00000000},
|
||||
|
@ -1040,26 +1040,26 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a0b8, 0x00000000},
|
||||
{0x0000a0bc, 0x00000000},
|
||||
{0x0000a0c0, 0x001f0000},
|
||||
{0x0000a0c4, 0x011f0100},
|
||||
{0x0000a0c8, 0x011d011e},
|
||||
{0x0000a0cc, 0x011b011c},
|
||||
{0x0000a0c4, 0x01000101},
|
||||
{0x0000a0c8, 0x011e011f},
|
||||
{0x0000a0cc, 0x011c011d},
|
||||
{0x0000a0d0, 0x02030204},
|
||||
{0x0000a0d4, 0x02010202},
|
||||
{0x0000a0d8, 0x021f0200},
|
||||
{0x0000a0dc, 0x021d021e},
|
||||
{0x0000a0e0, 0x03010302},
|
||||
{0x0000a0e4, 0x031f0300},
|
||||
{0x0000a0e8, 0x0402031e},
|
||||
{0x0000a0dc, 0x0302021e},
|
||||
{0x0000a0e0, 0x03000301},
|
||||
{0x0000a0e4, 0x031e031f},
|
||||
{0x0000a0e8, 0x0402031d},
|
||||
{0x0000a0ec, 0x04000401},
|
||||
{0x0000a0f0, 0x041e041f},
|
||||
{0x0000a0f4, 0x05010502},
|
||||
{0x0000a0f8, 0x051f0500},
|
||||
{0x0000a0fc, 0x0602051e},
|
||||
{0x0000a100, 0x06000601},
|
||||
{0x0000a104, 0x061e061f},
|
||||
{0x0000a108, 0x0703061d},
|
||||
{0x0000a10c, 0x07010702},
|
||||
{0x0000a110, 0x00000700},
|
||||
{0x0000a0f4, 0x0502041d},
|
||||
{0x0000a0f8, 0x05000501},
|
||||
{0x0000a0fc, 0x051e051f},
|
||||
{0x0000a100, 0x06010602},
|
||||
{0x0000a104, 0x061f0600},
|
||||
{0x0000a108, 0x061d061e},
|
||||
{0x0000a10c, 0x07020703},
|
||||
{0x0000a110, 0x07000701},
|
||||
{0x0000a114, 0x00000000},
|
||||
{0x0000a118, 0x00000000},
|
||||
{0x0000a11c, 0x00000000},
|
||||
|
@ -1072,26 +1072,26 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a138, 0x00000000},
|
||||
{0x0000a13c, 0x00000000},
|
||||
{0x0000a140, 0x001f0000},
|
||||
{0x0000a144, 0x011f0100},
|
||||
{0x0000a148, 0x011d011e},
|
||||
{0x0000a14c, 0x011b011c},
|
||||
{0x0000a144, 0x01000101},
|
||||
{0x0000a148, 0x011e011f},
|
||||
{0x0000a14c, 0x011c011d},
|
||||
{0x0000a150, 0x02030204},
|
||||
{0x0000a154, 0x02010202},
|
||||
{0x0000a158, 0x021f0200},
|
||||
{0x0000a15c, 0x021d021e},
|
||||
{0x0000a160, 0x03010302},
|
||||
{0x0000a164, 0x031f0300},
|
||||
{0x0000a168, 0x0402031e},
|
||||
{0x0000a15c, 0x0302021e},
|
||||
{0x0000a160, 0x03000301},
|
||||
{0x0000a164, 0x031e031f},
|
||||
{0x0000a168, 0x0402031d},
|
||||
{0x0000a16c, 0x04000401},
|
||||
{0x0000a170, 0x041e041f},
|
||||
{0x0000a174, 0x05010502},
|
||||
{0x0000a178, 0x051f0500},
|
||||
{0x0000a17c, 0x0602051e},
|
||||
{0x0000a180, 0x06000601},
|
||||
{0x0000a184, 0x061e061f},
|
||||
{0x0000a188, 0x0703061d},
|
||||
{0x0000a18c, 0x07010702},
|
||||
{0x0000a190, 0x00000700},
|
||||
{0x0000a174, 0x0502041d},
|
||||
{0x0000a178, 0x05000501},
|
||||
{0x0000a17c, 0x051e051f},
|
||||
{0x0000a180, 0x06010602},
|
||||
{0x0000a184, 0x061f0600},
|
||||
{0x0000a188, 0x061d061e},
|
||||
{0x0000a18c, 0x07020703},
|
||||
{0x0000a190, 0x07000701},
|
||||
{0x0000a194, 0x00000000},
|
||||
{0x0000a198, 0x00000000},
|
||||
{0x0000a19c, 0x00000000},
|
||||
|
@ -1317,13 +1317,13 @@ static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = {
|
|||
{0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec},
|
||||
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016048, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61},
|
||||
{0x00016048, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016448, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61},
|
||||
{0x00016448, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
|
||||
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016848, 0x64001a61, 0x64001a61, 0x64001a61, 0x64001a61},
|
||||
{0x00016848, 0x64000001, 0x64000001, 0x64000001, 0x64000001},
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
|
@ -1497,22 +1497,22 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a004, 0x00030002},
|
||||
{0x0000a008, 0x00050004},
|
||||
{0x0000a00c, 0x00810080},
|
||||
{0x0000a010, 0x01800082},
|
||||
{0x0000a014, 0x01820181},
|
||||
{0x0000a018, 0x01840183},
|
||||
{0x0000a01c, 0x01880185},
|
||||
{0x0000a020, 0x018a0189},
|
||||
{0x0000a024, 0x02850284},
|
||||
{0x0000a028, 0x02890288},
|
||||
{0x0000a02c, 0x03850384},
|
||||
{0x0000a030, 0x03890388},
|
||||
{0x0000a034, 0x038b038a},
|
||||
{0x0000a038, 0x038d038c},
|
||||
{0x0000a03c, 0x03910390},
|
||||
{0x0000a040, 0x03930392},
|
||||
{0x0000a044, 0x03950394},
|
||||
{0x0000a048, 0x00000396},
|
||||
{0x0000a04c, 0x00000000},
|
||||
{0x0000a010, 0x00830082},
|
||||
{0x0000a014, 0x01810180},
|
||||
{0x0000a018, 0x01830182},
|
||||
{0x0000a01c, 0x01850184},
|
||||
{0x0000a020, 0x01890188},
|
||||
{0x0000a024, 0x018b018a},
|
||||
{0x0000a028, 0x018d018c},
|
||||
{0x0000a02c, 0x03820190},
|
||||
{0x0000a030, 0x03840383},
|
||||
{0x0000a034, 0x03880385},
|
||||
{0x0000a038, 0x038a0389},
|
||||
{0x0000a03c, 0x038c038b},
|
||||
{0x0000a040, 0x0390038d},
|
||||
{0x0000a044, 0x03920391},
|
||||
{0x0000a048, 0x03940393},
|
||||
{0x0000a04c, 0x03960395},
|
||||
{0x0000a050, 0x00000000},
|
||||
{0x0000a054, 0x00000000},
|
||||
{0x0000a058, 0x00000000},
|
||||
|
@ -1525,15 +1525,15 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a074, 0x00000000},
|
||||
{0x0000a078, 0x00000000},
|
||||
{0x0000a07c, 0x00000000},
|
||||
{0x0000a080, 0x28282828},
|
||||
{0x0000a084, 0x28282828},
|
||||
{0x0000a088, 0x28282828},
|
||||
{0x0000a08c, 0x28282828},
|
||||
{0x0000a090, 0x28282828},
|
||||
{0x0000a094, 0x21212128},
|
||||
{0x0000a098, 0x171c1c1c},
|
||||
{0x0000a09c, 0x02020212},
|
||||
{0x0000a0a0, 0x00000202},
|
||||
{0x0000a080, 0x29292929},
|
||||
{0x0000a084, 0x29292929},
|
||||
{0x0000a088, 0x29292929},
|
||||
{0x0000a08c, 0x29292929},
|
||||
{0x0000a090, 0x22292929},
|
||||
{0x0000a094, 0x1d1d2222},
|
||||
{0x0000a098, 0x0c111117},
|
||||
{0x0000a09c, 0x00030303},
|
||||
{0x0000a0a0, 0x00000000},
|
||||
{0x0000a0a4, 0x00000000},
|
||||
{0x0000a0a8, 0x00000000},
|
||||
{0x0000a0ac, 0x00000000},
|
||||
|
@ -1542,26 +1542,26 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a0b8, 0x00000000},
|
||||
{0x0000a0bc, 0x00000000},
|
||||
{0x0000a0c0, 0x001f0000},
|
||||
{0x0000a0c4, 0x011f0100},
|
||||
{0x0000a0c8, 0x011d011e},
|
||||
{0x0000a0cc, 0x011b011c},
|
||||
{0x0000a0c4, 0x01000101},
|
||||
{0x0000a0c8, 0x011e011f},
|
||||
{0x0000a0cc, 0x011c011d},
|
||||
{0x0000a0d0, 0x02030204},
|
||||
{0x0000a0d4, 0x02010202},
|
||||
{0x0000a0d8, 0x021f0200},
|
||||
{0x0000a0dc, 0x021d021e},
|
||||
{0x0000a0e0, 0x03010302},
|
||||
{0x0000a0e4, 0x031f0300},
|
||||
{0x0000a0e8, 0x0402031e},
|
||||
{0x0000a0dc, 0x0302021e},
|
||||
{0x0000a0e0, 0x03000301},
|
||||
{0x0000a0e4, 0x031e031f},
|
||||
{0x0000a0e8, 0x0402031d},
|
||||
{0x0000a0ec, 0x04000401},
|
||||
{0x0000a0f0, 0x041e041f},
|
||||
{0x0000a0f4, 0x05010502},
|
||||
{0x0000a0f8, 0x051f0500},
|
||||
{0x0000a0fc, 0x0602051e},
|
||||
{0x0000a100, 0x06000601},
|
||||
{0x0000a104, 0x061e061f},
|
||||
{0x0000a108, 0x0703061d},
|
||||
{0x0000a10c, 0x07010702},
|
||||
{0x0000a110, 0x00000700},
|
||||
{0x0000a0f4, 0x0502041d},
|
||||
{0x0000a0f8, 0x05000501},
|
||||
{0x0000a0fc, 0x051e051f},
|
||||
{0x0000a100, 0x06010602},
|
||||
{0x0000a104, 0x061f0600},
|
||||
{0x0000a108, 0x061d061e},
|
||||
{0x0000a10c, 0x07020703},
|
||||
{0x0000a110, 0x07000701},
|
||||
{0x0000a114, 0x00000000},
|
||||
{0x0000a118, 0x00000000},
|
||||
{0x0000a11c, 0x00000000},
|
||||
|
@ -1574,26 +1574,26 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a138, 0x00000000},
|
||||
{0x0000a13c, 0x00000000},
|
||||
{0x0000a140, 0x001f0000},
|
||||
{0x0000a144, 0x011f0100},
|
||||
{0x0000a148, 0x011d011e},
|
||||
{0x0000a14c, 0x011b011c},
|
||||
{0x0000a144, 0x01000101},
|
||||
{0x0000a148, 0x011e011f},
|
||||
{0x0000a14c, 0x011c011d},
|
||||
{0x0000a150, 0x02030204},
|
||||
{0x0000a154, 0x02010202},
|
||||
{0x0000a158, 0x021f0200},
|
||||
{0x0000a15c, 0x021d021e},
|
||||
{0x0000a160, 0x03010302},
|
||||
{0x0000a164, 0x031f0300},
|
||||
{0x0000a168, 0x0402031e},
|
||||
{0x0000a15c, 0x0302021e},
|
||||
{0x0000a160, 0x03000301},
|
||||
{0x0000a164, 0x031e031f},
|
||||
{0x0000a168, 0x0402031d},
|
||||
{0x0000a16c, 0x04000401},
|
||||
{0x0000a170, 0x041e041f},
|
||||
{0x0000a174, 0x05010502},
|
||||
{0x0000a178, 0x051f0500},
|
||||
{0x0000a17c, 0x0602051e},
|
||||
{0x0000a180, 0x06000601},
|
||||
{0x0000a184, 0x061e061f},
|
||||
{0x0000a188, 0x0703061d},
|
||||
{0x0000a18c, 0x07010702},
|
||||
{0x0000a190, 0x00000700},
|
||||
{0x0000a174, 0x0502041d},
|
||||
{0x0000a178, 0x05000501},
|
||||
{0x0000a17c, 0x051e051f},
|
||||
{0x0000a180, 0x06010602},
|
||||
{0x0000a184, 0x061f0600},
|
||||
{0x0000a188, 0x061d061e},
|
||||
{0x0000a18c, 0x07020703},
|
||||
{0x0000a190, 0x07000701},
|
||||
{0x0000a194, 0x00000000},
|
||||
{0x0000a198, 0x00000000},
|
||||
{0x0000a19c, 0x00000000},
|
||||
|
@ -1620,7 +1620,7 @@ static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = {
|
|||
{0x0000a1f0, 0x00000396},
|
||||
{0x0000a1f4, 0x00000396},
|
||||
{0x0000a1f8, 0x00000396},
|
||||
{0x0000a1fc, 0x00000296},
|
||||
{0x0000a1fc, 0x00000196},
|
||||
{0x0000b000, 0x00010000},
|
||||
{0x0000b004, 0x00030002},
|
||||
{0x0000b008, 0x00050004},
|
||||
|
|
|
@ -78,6 +78,90 @@ static const struct file_operations fops_debug = {
|
|||
|
||||
#define DMA_BUF_LEN 1024
|
||||
|
||||
static ssize_t read_file_tx_chainmask(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", common->tx_chainmask);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_tx_chainmask(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
unsigned long mask;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, &mask))
|
||||
return -EINVAL;
|
||||
|
||||
common->tx_chainmask = mask;
|
||||
sc->sc_ah->caps.tx_chainmask = mask;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_tx_chainmask = {
|
||||
.read = read_file_tx_chainmask,
|
||||
.write = write_file_tx_chainmask,
|
||||
.open = ath9k_debugfs_open,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
|
||||
static ssize_t read_file_rx_chainmask(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", common->rx_chainmask);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_rx_chainmask(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
unsigned long mask;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, &mask))
|
||||
return -EINVAL;
|
||||
|
||||
common->rx_chainmask = mask;
|
||||
sc->sc_ah->caps.rx_chainmask = mask;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_rx_chainmask = {
|
||||
.read = read_file_rx_chainmask,
|
||||
.write = write_file_rx_chainmask,
|
||||
.open = ath9k_debugfs_open,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
|
||||
static ssize_t read_file_dma(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
|
@ -711,6 +795,86 @@ static const struct file_operations fops_recv = {
|
|||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.regidx);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_regidx(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
unsigned long regidx;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, ®idx))
|
||||
return -EINVAL;
|
||||
|
||||
sc->debug.regidx = regidx;
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_regidx = {
|
||||
.read = read_file_regidx,
|
||||
.write = write_file_regidx,
|
||||
.open = ath9k_debugfs_open,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static ssize_t read_file_regval(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
char buf[32];
|
||||
unsigned int len;
|
||||
u32 regval;
|
||||
|
||||
regval = REG_READ_D(ah, sc->debug.regidx);
|
||||
len = snprintf(buf, sizeof(buf), "0x%08x\n", regval);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
unsigned long regval;
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EINVAL;
|
||||
|
||||
buf[len] = '\0';
|
||||
if (strict_strtoul(buf, 0, ®val))
|
||||
return -EINVAL;
|
||||
|
||||
REG_WRITE_D(ah, sc->debug.regidx, regval);
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_regval = {
|
||||
.read = read_file_regval,
|
||||
.write = write_file_regval,
|
||||
.open = ath9k_debugfs_open,
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
@ -722,54 +886,55 @@ int ath9k_init_debug(struct ath_hw *ah)
|
|||
sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
|
||||
ath9k_debugfs_root);
|
||||
if (!sc->debug.debugfs_phy)
|
||||
goto err;
|
||||
return -ENOMEM;
|
||||
|
||||
#ifdef CONFIG_ATH_DEBUG
|
||||
sc->debug.debugfs_debug = debugfs_create_file("debug",
|
||||
S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
|
||||
if (!sc->debug.debugfs_debug)
|
||||
if (!debugfs_create_file("debug", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_debug))
|
||||
goto err;
|
||||
#endif
|
||||
|
||||
sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_dma);
|
||||
if (!sc->debug.debugfs_dma)
|
||||
if (!debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy,
|
||||
sc, &fops_dma))
|
||||
goto err;
|
||||
|
||||
sc->debug.debugfs_interrupt = debugfs_create_file("interrupt",
|
||||
S_IRUSR,
|
||||
sc->debug.debugfs_phy,
|
||||
sc, &fops_interrupt);
|
||||
if (!sc->debug.debugfs_interrupt)
|
||||
if (!debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy,
|
||||
sc, &fops_interrupt))
|
||||
goto err;
|
||||
|
||||
sc->debug.debugfs_rcstat = debugfs_create_file("rcstat",
|
||||
S_IRUSR,
|
||||
sc->debug.debugfs_phy,
|
||||
sc, &fops_rcstat);
|
||||
if (!sc->debug.debugfs_rcstat)
|
||||
if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy,
|
||||
sc, &fops_rcstat))
|
||||
goto err;
|
||||
|
||||
sc->debug.debugfs_wiphy = debugfs_create_file(
|
||||
"wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_wiphy);
|
||||
if (!sc->debug.debugfs_wiphy)
|
||||
if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_wiphy))
|
||||
goto err;
|
||||
|
||||
sc->debug.debugfs_xmit = debugfs_create_file("xmit",
|
||||
S_IRUSR,
|
||||
sc->debug.debugfs_phy,
|
||||
sc, &fops_xmit);
|
||||
if (!sc->debug.debugfs_xmit)
|
||||
if (!debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy,
|
||||
sc, &fops_xmit))
|
||||
goto err;
|
||||
|
||||
sc->debug.debugfs_recv = debugfs_create_file("recv",
|
||||
S_IRUSR,
|
||||
sc->debug.debugfs_phy,
|
||||
sc, &fops_recv);
|
||||
if (!sc->debug.debugfs_recv)
|
||||
if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy,
|
||||
sc, &fops_recv))
|
||||
goto err;
|
||||
|
||||
if (!debugfs_create_file("rx_chainmask", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_rx_chainmask))
|
||||
goto err;
|
||||
|
||||
if (!debugfs_create_file("tx_chainmask", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_tx_chainmask))
|
||||
goto err;
|
||||
|
||||
if (!debugfs_create_file("regidx", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_regidx))
|
||||
goto err;
|
||||
|
||||
if (!debugfs_create_file("regval", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc, &fops_regval))
|
||||
goto err;
|
||||
|
||||
sc->debug.regidx = 0;
|
||||
return 0;
|
||||
err:
|
||||
ath9k_exit_debug(ah);
|
||||
|
@ -781,14 +946,7 @@ void ath9k_exit_debug(struct ath_hw *ah)
|
|||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_softc *sc = (struct ath_softc *) common->priv;
|
||||
|
||||
debugfs_remove(sc->debug.debugfs_recv);
|
||||
debugfs_remove(sc->debug.debugfs_xmit);
|
||||
debugfs_remove(sc->debug.debugfs_wiphy);
|
||||
debugfs_remove(sc->debug.debugfs_rcstat);
|
||||
debugfs_remove(sc->debug.debugfs_interrupt);
|
||||
debugfs_remove(sc->debug.debugfs_dma);
|
||||
debugfs_remove(sc->debug.debugfs_debug);
|
||||
debugfs_remove(sc->debug.debugfs_phy);
|
||||
debugfs_remove_recursive(sc->debug.debugfs_phy);
|
||||
}
|
||||
|
||||
int ath9k_debug_create_root(void)
|
||||
|
|
|
@ -153,13 +153,7 @@ struct ath_stats {
|
|||
|
||||
struct ath9k_debug {
|
||||
struct dentry *debugfs_phy;
|
||||
struct dentry *debugfs_debug;
|
||||
struct dentry *debugfs_dma;
|
||||
struct dentry *debugfs_interrupt;
|
||||
struct dentry *debugfs_rcstat;
|
||||
struct dentry *debugfs_wiphy;
|
||||
struct dentry *debugfs_xmit;
|
||||
struct dentry *debugfs_recv;
|
||||
u32 regidx;
|
||||
struct ath_stats stats;
|
||||
};
|
||||
|
||||
|
|
|
@ -735,6 +735,14 @@ err:
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
usb_kill_anchored_urbs(&hif_dev->regout_submitted);
|
||||
ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
|
||||
ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
|
||||
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
|
||||
}
|
||||
|
||||
static int ath9k_hif_usb_download_fw(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
int transfer, err;
|
||||
|
@ -794,14 +802,6 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev,
|
|||
goto err_fw_req;
|
||||
}
|
||||
|
||||
/* Download firmware */
|
||||
ret = ath9k_hif_usb_download_fw(hif_dev);
|
||||
if (ret) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Firmware - %s download failed\n", fw_name);
|
||||
goto err_fw_download;
|
||||
}
|
||||
|
||||
/* Alloc URBs */
|
||||
ret = ath9k_hif_usb_alloc_urbs(hif_dev);
|
||||
if (ret) {
|
||||
|
@ -810,25 +810,25 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev,
|
|||
goto err_urb;
|
||||
}
|
||||
|
||||
/* Download firmware */
|
||||
ret = ath9k_hif_usb_download_fw(hif_dev);
|
||||
if (ret) {
|
||||
dev_err(&hif_dev->udev->dev,
|
||||
"ath9k_htc: Firmware - %s download failed\n", fw_name);
|
||||
goto err_fw_download;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_urb:
|
||||
/* Nothing */
|
||||
err_fw_download:
|
||||
ath9k_hif_usb_dealloc_urbs(hif_dev);
|
||||
err_urb:
|
||||
release_firmware(hif_dev->firmware);
|
||||
err_fw_req:
|
||||
hif_dev->firmware = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_dealloc_urbs(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
usb_kill_anchored_urbs(&hif_dev->regout_submitted);
|
||||
ath9k_hif_usb_dealloc_reg_in_urb(hif_dev);
|
||||
ath9k_hif_usb_dealloc_tx_urbs(hif_dev);
|
||||
ath9k_hif_usb_dealloc_rx_urbs(hif_dev);
|
||||
}
|
||||
|
||||
static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev)
|
||||
{
|
||||
ath9k_hif_usb_dealloc_urbs(hif_dev);
|
||||
|
@ -859,21 +859,21 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
|||
#endif
|
||||
usb_set_intfdata(interface, hif_dev);
|
||||
|
||||
hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev, &hif_usb,
|
||||
&hif_dev->udev->dev);
|
||||
if (hif_dev->htc_handle == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_htc_hw_alloc;
|
||||
}
|
||||
|
||||
ret = ath9k_hif_usb_dev_init(hif_dev, fw_name);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto err_hif_init_usb;
|
||||
}
|
||||
|
||||
hif_dev->htc_handle = ath9k_htc_hw_alloc(hif_dev);
|
||||
if (hif_dev->htc_handle == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_htc_hw_alloc;
|
||||
}
|
||||
|
||||
ret = ath9k_htc_hw_init(&hif_usb, hif_dev->htc_handle, hif_dev,
|
||||
&hif_dev->udev->dev, hif_dev->device_id,
|
||||
ATH9K_HIF_USB);
|
||||
ret = ath9k_htc_hw_init(hif_dev->htc_handle,
|
||||
&hif_dev->udev->dev, hif_dev->device_id);
|
||||
if (ret) {
|
||||
ret = -EINVAL;
|
||||
goto err_htc_hw_init;
|
||||
|
@ -884,10 +884,10 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
|
|||
return 0;
|
||||
|
||||
err_htc_hw_init:
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
err_htc_hw_alloc:
|
||||
ath9k_hif_usb_dev_deinit(hif_dev);
|
||||
err_hif_init_usb:
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
err_htc_hw_alloc:
|
||||
usb_set_intfdata(interface, NULL);
|
||||
kfree(hif_dev);
|
||||
usb_put_dev(udev);
|
||||
|
|
|
@ -81,6 +81,11 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
|
|||
{
|
||||
int time_left;
|
||||
|
||||
if (atomic_read(&priv->htc->tgt_ready) > 0) {
|
||||
atomic_dec(&priv->htc->tgt_ready);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Firmware can take up to 50ms to get ready, to be safe use 1 second */
|
||||
time_left = wait_for_completion_timeout(&priv->htc->target_wait, HZ);
|
||||
if (!time_left) {
|
||||
|
@ -88,6 +93,8 @@ static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
atomic_dec(&priv->htc->tgt_ready);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1452,6 +1452,8 @@ static void ath9k_htc_sta_notify(struct ieee80211_hw *hw,
|
|||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
ret = ath9k_htc_add_station(priv, vif, sta);
|
||||
|
@ -1464,6 +1466,8 @@ static void ath9k_htc_sta_notify(struct ieee80211_hw *hw,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
static int ath9k_htc_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
|
|
|
@ -39,7 +39,7 @@ static struct htc_endpoint *get_next_avail_ep(struct htc_endpoint *endpoint)
|
|||
{
|
||||
enum htc_endpoint_id avail_epid;
|
||||
|
||||
for (avail_epid = ENDPOINT_MAX; avail_epid > ENDPOINT0; avail_epid--)
|
||||
for (avail_epid = (ENDPOINT_MAX - 1); avail_epid > ENDPOINT0; avail_epid--)
|
||||
if (endpoint[avail_epid].service_id == 0)
|
||||
return &endpoint[avail_epid];
|
||||
return NULL;
|
||||
|
@ -95,6 +95,7 @@ static void htc_process_target_rdy(struct htc_target *target,
|
|||
endpoint = &target->endpoint[ENDPOINT0];
|
||||
endpoint->service_id = HTC_CTRL_RSVD_SVC;
|
||||
endpoint->max_msglen = HTC_MAX_CONTROL_MESSAGE_LENGTH;
|
||||
atomic_inc(&target->tgt_ready);
|
||||
complete(&target->target_wait);
|
||||
}
|
||||
|
||||
|
@ -116,7 +117,7 @@ static void htc_process_conn_rsp(struct htc_target *target,
|
|||
max_msglen = be16_to_cpu(svc_rspmsg->max_msg_len);
|
||||
endpoint = &target->endpoint[epid];
|
||||
|
||||
for (tepid = ENDPOINT_MAX; tepid > ENDPOINT0; tepid--) {
|
||||
for (tepid = (ENDPOINT_MAX - 1); tepid > ENDPOINT0; tepid--) {
|
||||
tmp_endpoint = &target->endpoint[tepid];
|
||||
if (tmp_endpoint->service_id == service_id) {
|
||||
tmp_endpoint->service_id = 0;
|
||||
|
@ -124,7 +125,7 @@ static void htc_process_conn_rsp(struct htc_target *target,
|
|||
}
|
||||
}
|
||||
|
||||
if (!tmp_endpoint)
|
||||
if (tepid == ENDPOINT0)
|
||||
return;
|
||||
|
||||
endpoint->service_id = service_id;
|
||||
|
@ -297,7 +298,7 @@ void htc_stop(struct htc_target *target)
|
|||
enum htc_endpoint_id epid;
|
||||
struct htc_endpoint *endpoint;
|
||||
|
||||
for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) {
|
||||
for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
|
||||
endpoint = &target->endpoint[epid];
|
||||
if (endpoint->service_id != 0)
|
||||
target->hif->stop(target->hif_dev, endpoint->ul_pipeid);
|
||||
|
@ -309,7 +310,7 @@ void htc_start(struct htc_target *target)
|
|||
enum htc_endpoint_id epid;
|
||||
struct htc_endpoint *endpoint;
|
||||
|
||||
for (epid = ENDPOINT0; epid <= ENDPOINT_MAX; epid++) {
|
||||
for (epid = ENDPOINT0; epid < ENDPOINT_MAX; epid++) {
|
||||
endpoint = &target->endpoint[epid];
|
||||
if (endpoint->service_id != 0)
|
||||
target->hif->start(target->hif_dev,
|
||||
|
@ -425,29 +426,19 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
|
|||
}
|
||||
}
|
||||
|
||||
struct htc_target *ath9k_htc_hw_alloc(void *hif_handle)
|
||||
struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
|
||||
struct ath9k_htc_hif *hif,
|
||||
struct device *dev)
|
||||
{
|
||||
struct htc_endpoint *endpoint;
|
||||
struct htc_target *target;
|
||||
|
||||
target = kzalloc(sizeof(struct htc_target), GFP_KERNEL);
|
||||
if (!target)
|
||||
if (!target) {
|
||||
printk(KERN_ERR "Unable to allocate memory for"
|
||||
"target device\n");
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
void ath9k_htc_hw_free(struct htc_target *htc)
|
||||
{
|
||||
kfree(htc);
|
||||
}
|
||||
|
||||
int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target,
|
||||
void *hif_handle, struct device *dev, u16 devid,
|
||||
enum ath9k_hif_transports transport)
|
||||
{
|
||||
struct htc_endpoint *endpoint;
|
||||
int err = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
init_completion(&target->target_wait);
|
||||
init_completion(&target->cmd_wait);
|
||||
|
@ -461,8 +452,20 @@ int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target,
|
|||
endpoint->ul_pipeid = hif->control_ul_pipe;
|
||||
endpoint->dl_pipeid = hif->control_dl_pipe;
|
||||
|
||||
err = ath9k_htc_probe_device(target, dev, devid);
|
||||
if (err) {
|
||||
atomic_set(&target->tgt_ready, 0);
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
void ath9k_htc_hw_free(struct htc_target *htc)
|
||||
{
|
||||
kfree(htc);
|
||||
}
|
||||
|
||||
int ath9k_htc_hw_init(struct htc_target *target,
|
||||
struct device *dev, u16 devid)
|
||||
{
|
||||
if (ath9k_htc_probe_device(target, dev, devid)) {
|
||||
printk(KERN_ERR "Failed to initialize the device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -123,9 +123,6 @@ struct htc_endpoint {
|
|||
#define HTC_CONTROL_BUFFER_SIZE \
|
||||
(HTC_MAX_CONTROL_MESSAGE_LENGTH + sizeof(struct htc_frame_hdr))
|
||||
|
||||
#define NUM_CONTROL_BUFFERS 8
|
||||
#define HST_ENDPOINT_MAX 8
|
||||
|
||||
struct htc_control_buf {
|
||||
struct htc_packet htc_pkt;
|
||||
u8 buf[HTC_CONTROL_BUFFER_SIZE];
|
||||
|
@ -139,7 +136,7 @@ struct htc_target {
|
|||
struct ath9k_htc_priv *drv_priv;
|
||||
struct device *dev;
|
||||
struct ath9k_htc_hif *hif;
|
||||
struct htc_endpoint endpoint[HST_ENDPOINT_MAX];
|
||||
struct htc_endpoint endpoint[ENDPOINT_MAX];
|
||||
struct completion target_wait;
|
||||
struct completion cmd_wait;
|
||||
struct list_head list;
|
||||
|
@ -147,6 +144,7 @@ struct htc_target {
|
|||
u16 credits;
|
||||
u16 credit_size;
|
||||
u8 htc_flags;
|
||||
atomic_t tgt_ready;
|
||||
};
|
||||
|
||||
enum htc_msg_id {
|
||||
|
@ -236,11 +234,12 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
|
|||
void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
|
||||
struct sk_buff *skb, bool txok);
|
||||
|
||||
struct htc_target *ath9k_htc_hw_alloc(void *hif_handle);
|
||||
struct htc_target *ath9k_htc_hw_alloc(void *hif_handle,
|
||||
struct ath9k_htc_hif *hif,
|
||||
struct device *dev);
|
||||
void ath9k_htc_hw_free(struct htc_target *htc);
|
||||
int ath9k_htc_hw_init(struct ath9k_htc_hif *hif, struct htc_target *target,
|
||||
void *hif_handle, struct device *dev, u16 devid,
|
||||
enum ath9k_hif_transports transport);
|
||||
int ath9k_htc_hw_init(struct htc_target *target,
|
||||
struct device *dev, u16 devid);
|
||||
void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug);
|
||||
|
||||
#endif /* HTC_HST_H */
|
||||
|
|
|
@ -150,11 +150,9 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc,
|
|||
static void ath_rx_addbuffer_edma(struct ath_softc *sc,
|
||||
enum ath9k_rx_qtype qtype, int size)
|
||||
{
|
||||
struct ath_rx_edma *rx_edma;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
u32 nbuf = 0;
|
||||
|
||||
rx_edma = &sc->rx.rx_edma[qtype];
|
||||
if (list_empty(&sc->rx.rxbuf)) {
|
||||
ath_print(common, ATH_DBG_QUEUE, "No free rx buf available\n");
|
||||
return;
|
||||
|
@ -718,6 +716,7 @@ static bool ath_edma_get_buffers(struct ath_softc *sc,
|
|||
__skb_unlink(skb, &rx_edma->rx_fifo);
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
ath_rx_edma_buf_link(sc, qtype);
|
||||
return true;
|
||||
}
|
||||
skb_queue_tail(&rx_edma->rx_buffers, skb);
|
||||
|
||||
|
|
|
@ -355,8 +355,7 @@ static struct hostap_bss_info *__hostap_add_bss(local_info_t *local, u8 *bssid,
|
|||
list_del(&bss->list);
|
||||
local->num_bss_info--;
|
||||
} else {
|
||||
bss = (struct hostap_bss_info *)
|
||||
kmalloc(sizeof(*bss), GFP_ATOMIC);
|
||||
bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
|
||||
if (bss == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -3039,8 +3039,7 @@ static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p)
|
|||
p->length > 1024 || !p->pointer)
|
||||
return -EINVAL;
|
||||
|
||||
param = (struct prism2_download_param *)
|
||||
kmalloc(p->length, GFP_KERNEL);
|
||||
param = kmalloc(p->length, GFP_KERNEL);
|
||||
if (param == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
|||
.temperature = iwlagn_temperature,
|
||||
.set_ct_kill = iwl1000_set_ct_threshold,
|
||||
},
|
||||
.add_bcast_station = iwl_add_bcast_station,
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -224,7 +224,6 @@ static struct iwl_lib_ops iwl1000_lib = {
|
|||
};
|
||||
|
||||
static const struct iwl_ops iwl1000_ops = {
|
||||
.ucode = &iwlagn_ucode,
|
||||
.lib = &iwl1000_lib,
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
|
@ -260,6 +259,9 @@ struct iwl_cfg iwl1000_bgn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 128,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl1000_bg_cfg = {
|
||||
|
@ -289,6 +291,9 @@ struct iwl_cfg iwl1000_bg_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 128,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
|
||||
|
|
|
@ -391,6 +391,67 @@ static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* iwl3945_good_plcp_health - checks for plcp error.
|
||||
*
|
||||
* When the plcp error is exceeding the thresholds, reset the radio
|
||||
* to improve the throughput.
|
||||
*/
|
||||
static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
bool rc = true;
|
||||
struct iwl3945_notif_statistics current_stat;
|
||||
int combined_plcp_delta;
|
||||
unsigned int plcp_msec;
|
||||
unsigned long plcp_received_jiffies;
|
||||
|
||||
memcpy(¤t_stat, pkt->u.raw, sizeof(struct
|
||||
iwl3945_notif_statistics));
|
||||
/*
|
||||
* check for plcp_err and trigger radio reset if it exceeds
|
||||
* the plcp error threshold plcp_delta.
|
||||
*/
|
||||
plcp_received_jiffies = jiffies;
|
||||
plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
|
||||
(long) priv->plcp_jiffies);
|
||||
priv->plcp_jiffies = plcp_received_jiffies;
|
||||
/*
|
||||
* check to make sure plcp_msec is not 0 to prevent division
|
||||
* by zero.
|
||||
*/
|
||||
if (plcp_msec) {
|
||||
combined_plcp_delta =
|
||||
(le32_to_cpu(current_stat.rx.ofdm.plcp_err) -
|
||||
le32_to_cpu(priv->_3945.statistics.rx.ofdm.plcp_err));
|
||||
|
||||
if ((combined_plcp_delta > 0) &&
|
||||
((combined_plcp_delta * 100) / plcp_msec) >
|
||||
priv->cfg->plcp_delta_threshold) {
|
||||
/*
|
||||
* if plcp_err exceed the threshold, the following
|
||||
* data is printed in csv format:
|
||||
* Text: plcp_err exceeded %d,
|
||||
* Received ofdm.plcp_err,
|
||||
* Current ofdm.plcp_err,
|
||||
* combined_plcp_delta,
|
||||
* plcp_msec
|
||||
*/
|
||||
IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
|
||||
"%u, %d, %u mSecs\n",
|
||||
priv->cfg->plcp_delta_threshold,
|
||||
le32_to_cpu(current_stat.rx.ofdm.plcp_err),
|
||||
combined_plcp_delta, plcp_msec);
|
||||
/*
|
||||
* Reset the RF radio due to the high plcp
|
||||
* error rate
|
||||
*/
|
||||
rc = false;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
|
@ -402,6 +463,7 @@ void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
|||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
|
||||
#endif
|
||||
iwl_recover_from_statistics(priv, pkt);
|
||||
|
||||
memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
|
||||
}
|
||||
|
@ -885,7 +947,8 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
|
|||
tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
|
||||
}
|
||||
|
||||
u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
|
||||
static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
|
||||
u16 tx_rate, u8 flags)
|
||||
{
|
||||
unsigned long flags_spin;
|
||||
struct iwl_station_entry *station;
|
||||
|
@ -1715,6 +1778,11 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
|
|||
int ref_temp;
|
||||
int temperature = priv->temperature;
|
||||
|
||||
if (priv->disable_tx_power_cal ||
|
||||
test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
/* do not perform tx power calibration */
|
||||
return 0;
|
||||
}
|
||||
/* set up new Tx power info for each and every channel, 2.4 and 5.x */
|
||||
for (i = 0; i < priv->channel_count; i++) {
|
||||
ch_info = &priv->channel_info[i];
|
||||
|
@ -1925,7 +1993,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
"configuration (%d).\n", rc);
|
||||
return rc;
|
||||
}
|
||||
iwl_clear_ucode_stations(priv, false);
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
}
|
||||
|
||||
|
@ -1958,7 +2026,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
|
||||
|
||||
if (!new_assoc) {
|
||||
iwl_clear_ucode_stations(priv, false);
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
}
|
||||
|
||||
|
@ -2391,6 +2459,30 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
|
|||
return (u16)sizeof(struct iwl3945_addsta_cmd);
|
||||
}
|
||||
|
||||
static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add)
|
||||
{
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
int ret;
|
||||
|
||||
if (add) {
|
||||
ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
|
||||
(priv->band == IEEE80211_BAND_5GHZ) ?
|
||||
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
|
||||
CMD_ASYNC);
|
||||
iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
|
||||
vif->bss_conf.bssid);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
|
||||
|
@ -2720,51 +2812,12 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define IWL3945_UCODE_GET(item) \
|
||||
static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\
|
||||
u32 api_ver) \
|
||||
{ \
|
||||
return le32_to_cpu(ucode->u.v1.item); \
|
||||
}
|
||||
|
||||
static u32 iwl3945_ucode_get_header_size(u32 api_ver)
|
||||
{
|
||||
return UCODE_HEADER_SIZE(1);
|
||||
}
|
||||
static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode,
|
||||
u32 api_ver)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode,
|
||||
u32 api_ver)
|
||||
{
|
||||
return (u8 *) ucode->u.v1.data;
|
||||
}
|
||||
|
||||
IWL3945_UCODE_GET(inst_size);
|
||||
IWL3945_UCODE_GET(data_size);
|
||||
IWL3945_UCODE_GET(init_size);
|
||||
IWL3945_UCODE_GET(init_data_size);
|
||||
IWL3945_UCODE_GET(boot_size);
|
||||
|
||||
static struct iwl_hcmd_ops iwl3945_hcmd = {
|
||||
.rxon_assoc = iwl3945_send_rxon_assoc,
|
||||
.commit_rxon = iwl3945_commit_rxon,
|
||||
.send_bt_config = iwl_send_bt_config,
|
||||
};
|
||||
|
||||
static struct iwl_ucode_ops iwl3945_ucode = {
|
||||
.get_header_size = iwl3945_ucode_get_header_size,
|
||||
.get_build = iwl3945_ucode_get_build,
|
||||
.get_inst_size = iwl3945_ucode_get_inst_size,
|
||||
.get_data_size = iwl3945_ucode_get_data_size,
|
||||
.get_init_size = iwl3945_ucode_get_init_size,
|
||||
.get_init_data_size = iwl3945_ucode_get_init_data_size,
|
||||
.get_boot_size = iwl3945_ucode_get_boot_size,
|
||||
.get_data = iwl3945_ucode_get_data,
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl3945_lib = {
|
||||
.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
|
||||
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
|
||||
|
@ -2798,7 +2851,8 @@ static struct iwl_lib_ops iwl3945_lib = {
|
|||
.post_associate = iwl3945_post_associate,
|
||||
.isr = iwl_isr_legacy,
|
||||
.config_ap = iwl3945_config_ap,
|
||||
.add_bcast_station = iwl3945_add_bcast_station,
|
||||
.manage_ibss_station = iwl3945_manage_ibss_station,
|
||||
.check_plcp_health = iwl3945_good_plcp_health,
|
||||
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl3945_ucode_rx_stats_read,
|
||||
|
@ -2815,7 +2869,6 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
|
|||
};
|
||||
|
||||
static const struct iwl_ops iwl3945_ops = {
|
||||
.ucode = &iwl3945_ucode,
|
||||
.lib = &iwl3945_lib,
|
||||
.hcmd = &iwl3945_hcmd,
|
||||
.utils = &iwl3945_hcmd_utils,
|
||||
|
@ -2840,9 +2893,10 @@ static struct iwl_cfg iwl3945_bg_cfg = {
|
|||
.ht_greenfield_support = false,
|
||||
.led_compensation = 64,
|
||||
.broken_powersave = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.tx_power_by_driver = true,
|
||||
};
|
||||
|
||||
static struct iwl_cfg iwl3945_abg_cfg = {
|
||||
|
@ -2860,9 +2914,10 @@ static struct iwl_cfg iwl3945_abg_cfg = {
|
|||
.ht_greenfield_support = false,
|
||||
.led_compensation = 64,
|
||||
.broken_powersave = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.tx_power_by_driver = true,
|
||||
};
|
||||
|
||||
DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
|
||||
|
|
|
@ -106,7 +106,12 @@ struct iwl3945_rs_sta {
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
* The common struct MUST be first because it is shared between
|
||||
* 3945 and agn!
|
||||
*/
|
||||
struct iwl3945_sta_priv {
|
||||
struct iwl_station_priv_common common;
|
||||
struct iwl3945_rs_sta rs_sta;
|
||||
};
|
||||
|
||||
|
@ -211,13 +216,6 @@ extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
|
|||
char **buf, bool display);
|
||||
extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
|
||||
|
||||
/*
|
||||
* Currently used by iwl-3945-rs... look at restructuring so that it doesn't
|
||||
* call this... todo... fix that.
|
||||
*/
|
||||
extern u8 iwl3945_sync_station(struct iwl_priv *priv, int sta_id,
|
||||
u16 tx_rate, u8 flags);
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Functions implemented in iwl-[34]*.c which are forward declared here
|
||||
|
@ -268,8 +266,10 @@ void iwl3945_reply_statistics(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb);
|
||||
extern void iwl3945_disable_events(struct iwl_priv *priv);
|
||||
extern int iwl4965_get_temperature(const struct iwl_priv *priv);
|
||||
extern void iwl3945_post_associate(struct iwl_priv *priv);
|
||||
extern void iwl3945_config_ap(struct iwl_priv *priv);
|
||||
extern void iwl3945_post_associate(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
extern void iwl3945_config_ap(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
|
||||
/**
|
||||
* iwl3945_hw_find_station - Find station id for a given BSSID
|
||||
|
@ -288,8 +288,6 @@ extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
|
|||
extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
|
||||
extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
|
||||
extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
|
||||
extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
|
||||
u16 tx_rate, u8 flags);
|
||||
|
||||
extern const struct iwl_channel_info *iwl3945_get_channel_info(
|
||||
const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
|
||||
|
@ -297,7 +295,7 @@ extern const struct iwl_channel_info *iwl3945_get_channel_info(
|
|||
extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
|
||||
|
||||
/* scanning */
|
||||
void iwl3945_request_scan(struct iwl_priv *priv);
|
||||
void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
|
||||
/* Requires full declaration of iwl_priv before including */
|
||||
#include "iwl-io.h"
|
||||
|
|
|
@ -1953,6 +1953,60 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
|
||||
{
|
||||
int i;
|
||||
int start = 0;
|
||||
int ret = IWL_INVALID_STATION;
|
||||
unsigned long flags;
|
||||
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
|
||||
(priv->iw_mode == NL80211_IFTYPE_AP))
|
||||
start = IWL_STA_ID;
|
||||
|
||||
if (is_broadcast_ether_addr(addr))
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
for (i = start; i < priv->hw_params.max_stations; i++)
|
||||
if (priv->stations[i].used &&
|
||||
(!compare_ether_addr(priv->stations[i].sta.sta.addr,
|
||||
addr))) {
|
||||
ret = i;
|
||||
goto out;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
|
||||
addr, priv->num_stations);
|
||||
|
||||
out:
|
||||
/*
|
||||
* It may be possible that more commands interacting with stations
|
||||
* arrive before we completed processing the adding of
|
||||
* station
|
||||
*/
|
||||
if (ret != IWL_INVALID_STATION &&
|
||||
(!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
|
||||
((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
|
||||
(priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
|
||||
IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
|
||||
ret);
|
||||
ret = IWL_INVALID_STATION;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
|
||||
{
|
||||
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
|
||||
return IWL_AP_ID;
|
||||
} else {
|
||||
u8 *da = ieee80211_get_DA(hdr);
|
||||
return iwl_find_station(priv, da);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
|
||||
*/
|
||||
|
@ -2112,34 +2166,6 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
|
|||
cancel_work_sync(&priv->txpower_work);
|
||||
}
|
||||
|
||||
#define IWL4965_UCODE_GET(item) \
|
||||
static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\
|
||||
u32 api_ver) \
|
||||
{ \
|
||||
return le32_to_cpu(ucode->u.v1.item); \
|
||||
}
|
||||
|
||||
static u32 iwl4965_ucode_get_header_size(u32 api_ver)
|
||||
{
|
||||
return UCODE_HEADER_SIZE(1);
|
||||
}
|
||||
static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode,
|
||||
u32 api_ver)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode,
|
||||
u32 api_ver)
|
||||
{
|
||||
return (u8 *) ucode->u.v1.data;
|
||||
}
|
||||
|
||||
IWL4965_UCODE_GET(inst_size);
|
||||
IWL4965_UCODE_GET(data_size);
|
||||
IWL4965_UCODE_GET(init_size);
|
||||
IWL4965_UCODE_GET(init_data_size);
|
||||
IWL4965_UCODE_GET(boot_size);
|
||||
|
||||
static struct iwl_hcmd_ops iwl4965_hcmd = {
|
||||
.rxon_assoc = iwl4965_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
|
@ -2147,16 +2173,6 @@ static struct iwl_hcmd_ops iwl4965_hcmd = {
|
|||
.send_bt_config = iwl_send_bt_config,
|
||||
};
|
||||
|
||||
static struct iwl_ucode_ops iwl4965_ucode = {
|
||||
.get_header_size = iwl4965_ucode_get_header_size,
|
||||
.get_build = iwl4965_ucode_get_build,
|
||||
.get_inst_size = iwl4965_ucode_get_inst_size,
|
||||
.get_data_size = iwl4965_ucode_get_data_size,
|
||||
.get_init_size = iwl4965_ucode_get_init_size,
|
||||
.get_init_data_size = iwl4965_ucode_get_init_data_size,
|
||||
.get_boot_size = iwl4965_ucode_get_boot_size,
|
||||
.get_data = iwl4965_ucode_get_data,
|
||||
};
|
||||
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
|
||||
.get_hcmd_size = iwl4965_get_hcmd_size,
|
||||
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
|
||||
|
@ -2218,7 +2234,7 @@ static struct iwl_lib_ops iwl4965_lib = {
|
|||
.temperature = iwl4965_temperature_calib,
|
||||
.set_ct_kill = iwl4965_set_ct_threshold,
|
||||
},
|
||||
.add_bcast_station = iwl_add_bcast_station,
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -2228,7 +2244,6 @@ static struct iwl_lib_ops iwl4965_lib = {
|
|||
};
|
||||
|
||||
static const struct iwl_ops iwl4965_ops = {
|
||||
.ucode = &iwl4965_ucode,
|
||||
.lib = &iwl4965_lib,
|
||||
.hcmd = &iwl4965_hcmd,
|
||||
.utils = &iwl4965_hcmd_utils,
|
||||
|
@ -2262,7 +2277,10 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
|||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.temperature_kelvin = true,
|
||||
.max_event_log_size = 512,
|
||||
|
||||
.tx_power_by_driver = true,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
/*
|
||||
* Force use of chains B and C for scan RX on 5 GHz band
|
||||
* because the device has off-channel reception on chain A.
|
||||
|
|
|
@ -351,7 +351,7 @@ static struct iwl_lib_ops iwl5000_lib = {
|
|||
.temperature = iwlagn_temperature,
|
||||
.set_ct_kill = iwl5000_set_ct_threshold,
|
||||
},
|
||||
.add_bcast_station = iwl_add_bcast_station,
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -413,7 +413,7 @@ static struct iwl_lib_ops iwl5150_lib = {
|
|||
.temperature = iwl5150_temperature,
|
||||
.set_ct_kill = iwl5150_set_ct_threshold,
|
||||
},
|
||||
.add_bcast_station = iwl_add_bcast_station,
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -425,7 +425,6 @@ static struct iwl_lib_ops iwl5150_lib = {
|
|||
};
|
||||
|
||||
static const struct iwl_ops iwl5000_ops = {
|
||||
.ucode = &iwlagn_ucode,
|
||||
.lib = &iwl5000_lib,
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
|
@ -433,7 +432,6 @@ static const struct iwl_ops iwl5000_ops = {
|
|||
};
|
||||
|
||||
static const struct iwl_ops iwl5150_ops = {
|
||||
.ucode = &iwlagn_ucode,
|
||||
.lib = &iwl5150_lib,
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
|
@ -466,6 +464,9 @@ struct iwl_cfg iwl5300_agn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_bgn_cfg = {
|
||||
|
@ -494,6 +495,9 @@ struct iwl_cfg iwl5100_bgn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_abg_cfg = {
|
||||
|
@ -520,6 +524,9 @@ struct iwl_cfg iwl5100_abg_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5100_agn_cfg = {
|
||||
|
@ -548,6 +555,9 @@ struct iwl_cfg iwl5100_agn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5350_agn_cfg = {
|
||||
|
@ -576,6 +586,9 @@ struct iwl_cfg iwl5350_agn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5150_agn_cfg = {
|
||||
|
@ -604,6 +617,9 @@ struct iwl_cfg iwl5150_agn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl5150_abg_cfg = {
|
||||
|
@ -630,6 +646,9 @@ struct iwl_cfg iwl5150_abg_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
|
||||
|
|
|
@ -67,9 +67,10 @@
|
|||
#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode"
|
||||
#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
|
||||
|
||||
#define IWL6000G2_FW_PRE "iwlwifi-6005-"
|
||||
#define _IWL6000G2_MODULE_FIRMWARE(api) IWL6000G2_FW_PRE #api ".ucode"
|
||||
#define IWL6000G2_MODULE_FIRMWARE(api) _IWL6000G2_MODULE_FIRMWARE(api)
|
||||
#define IWL6000G2A_FW_PRE "iwlwifi-6000g2a-"
|
||||
#define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE #api ".ucode"
|
||||
#define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api)
|
||||
|
||||
|
||||
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
||||
{
|
||||
|
@ -316,7 +317,7 @@ static struct iwl_lib_ops iwl6000_lib = {
|
|||
.temperature = iwlagn_temperature,
|
||||
.set_ct_kill = iwl6000_set_ct_threshold,
|
||||
},
|
||||
.add_bcast_station = iwl_add_bcast_station,
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -328,7 +329,6 @@ static struct iwl_lib_ops iwl6000_lib = {
|
|||
};
|
||||
|
||||
static const struct iwl_ops iwl6000_ops = {
|
||||
.ucode = &iwlagn_ucode,
|
||||
.lib = &iwl6000_lib,
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
|
@ -389,7 +389,7 @@ static struct iwl_lib_ops iwl6050_lib = {
|
|||
.set_ct_kill = iwl6000_set_ct_threshold,
|
||||
.set_calib_version = iwl6050_set_calib_version,
|
||||
},
|
||||
.add_bcast_station = iwl_add_bcast_station,
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
|
@ -401,19 +401,16 @@ static struct iwl_lib_ops iwl6050_lib = {
|
|||
};
|
||||
|
||||
static const struct iwl_ops iwl6050_ops = {
|
||||
.ucode = &iwlagn_ucode,
|
||||
.lib = &iwl6050_lib,
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* "i": Internal configuration, use internal Power Amplifier
|
||||
*/
|
||||
struct iwl_cfg iwl6000g2_2agn_cfg = {
|
||||
.name = "6000 Series 2x2 AGN Gen2",
|
||||
.fw_name_pre = IWL6000G2_FW_PRE,
|
||||
|
||||
struct iwl_cfg iwl6000g2a_2agn_cfg = {
|
||||
.name = "6000 Series 2x2 AGN Gen2a",
|
||||
.fw_name_pre = IWL6000G2A_FW_PRE,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
|
@ -442,9 +439,15 @@ struct iwl_cfg iwl6000g2_2agn_cfg = {
|
|||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 1024,
|
||||
.max_event_log_size = 512,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
/*
|
||||
* "i": Internal configuration, use internal Power Amplifier
|
||||
*/
|
||||
struct iwl_cfg iwl6000i_2agn_cfg = {
|
||||
.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
|
||||
.fw_name_pre = IWL6000_FW_PRE,
|
||||
|
@ -477,6 +480,9 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 1024,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2abg_cfg = {
|
||||
|
@ -509,6 +515,9 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 1024,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
|
@ -541,6 +550,9 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 1024,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
|
@ -575,6 +587,9 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
|||
.chain_noise_scale = 1500,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 1024,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
|
@ -607,6 +622,9 @@ struct iwl_cfg iwl6050_2abg_cfg = {
|
|||
.chain_noise_scale = 1500,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 1024,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
|
@ -641,8 +659,11 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
|||
.chain_noise_scale = 1000,
|
||||
.monitor_recover_period = IWL_MONITORING_PERIOD,
|
||||
.max_event_log_size = 1024,
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6000G2_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
|
||||
|
|
|
@ -709,6 +709,22 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
|
|||
delta_tx->agg.rx_ba_rsp_cnt,
|
||||
max_tx->agg.rx_ba_rsp_cnt);
|
||||
|
||||
if (tx->tx_power.ant_a || tx->tx_power.ant_b || tx->tx_power.ant_c) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"tx power: (1/2 dB step)\n");
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) && tx->tx_power.ant_a)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna A: 0x%X\n",
|
||||
tx->tx_power.ant_a);
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) && tx->tx_power.ant_b)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna B: 0x%X\n",
|
||||
tx->tx_power.ant_b);
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) && tx->tx_power.ant_c)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna C: 0x%X\n",
|
||||
tx->tx_power.ant_c);
|
||||
}
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "iwl-helpers.h"
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-sta.h"
|
||||
|
||||
static inline u32 iwlagn_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
|
||||
{
|
||||
|
@ -1113,8 +1114,9 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
{
|
||||
const struct ieee80211_supported_band *sband;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
|
@ -1130,7 +1132,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
active_dwell = iwl_get_active_dwell_time(priv, band, 0);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
|
||||
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
@ -1179,6 +1181,7 @@ static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
|
|||
}
|
||||
|
||||
static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_band band,
|
||||
u8 is_active, u8 n_probes,
|
||||
struct iwl_scan_channel *scan_ch)
|
||||
|
@ -1196,7 +1199,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
|||
return 0;
|
||||
|
||||
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
|
||||
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
@ -1256,7 +1259,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
|
|||
return added;
|
||||
}
|
||||
|
||||
void iwlagn_request_scan(struct iwl_priv *priv)
|
||||
void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_SCAN_CMD,
|
||||
|
@ -1342,7 +1345,7 @@ void iwlagn_request_scan(struct iwl_priv *priv)
|
|||
|
||||
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
interval = priv->beacon_int;
|
||||
interval = vif ? vif->bss_conf.beacon_int : 0;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
scan->suspend_time = 0;
|
||||
|
@ -1473,12 +1476,12 @@ void iwlagn_request_scan(struct iwl_priv *priv)
|
|||
|
||||
if (priv->is_internal_short_scan) {
|
||||
scan->channel_count =
|
||||
iwl_get_single_channel_for_scan(priv, band,
|
||||
iwl_get_single_channel_for_scan(priv, vif, band,
|
||||
(void *)&scan->data[le16_to_cpu(
|
||||
scan->tx_cmd.len)]);
|
||||
} else {
|
||||
scan->channel_count =
|
||||
iwl_get_channels_for_scan(priv, band,
|
||||
iwl_get_channels_for_scan(priv, vif, band,
|
||||
is_active, n_probes,
|
||||
(void *)&scan->data[le16_to_cpu(
|
||||
scan->tx_cmd.len)]);
|
||||
|
@ -1513,3 +1516,15 @@ void iwlagn_request_scan(struct iwl_priv *priv)
|
|||
/* inform mac80211 scan aborted */
|
||||
queue_work(priv->workqueue, &priv->scan_completed);
|
||||
}
|
||||
|
||||
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add)
|
||||
{
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
||||
if (add)
|
||||
return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true,
|
||||
&vif_priv->ibss_bssid_sta_id);
|
||||
return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
|
||||
vif->bss_conf.bssid);
|
||||
}
|
||||
|
|
|
@ -566,11 +566,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find (or create) index into station table for destination station */
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED)
|
||||
/* Find index into station table for destination station */
|
||||
if (!info->control.sta)
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
else
|
||||
sta_id = iwl_get_sta_id(priv, hdr);
|
||||
sta_id = iwl_sta_id(info->control.sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
@ -961,7 +961,8 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
|
||||
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
||||
{
|
||||
int sta_id;
|
||||
int tx_fifo;
|
||||
|
@ -975,9 +976,9 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
|
|||
return tx_fifo;
|
||||
|
||||
IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
|
||||
__func__, ra, tid);
|
||||
__func__, sta->addr, tid);
|
||||
|
||||
sta_id = iwl_find_station(priv, ra);
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Start AGG on invalid station\n");
|
||||
return -ENXIO;
|
||||
|
@ -1011,7 +1012,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
|
|||
if (tid_data->tfds_in_queue == 0) {
|
||||
IWL_DEBUG_HT(priv, "HW queue is empty\n");
|
||||
tid_data->agg.state = IWL_AGG_ON;
|
||||
ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid);
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
} else {
|
||||
IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n",
|
||||
tid_data->tfds_in_queue);
|
||||
|
@ -1020,23 +1021,19 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
|
||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
int tx_fifo_id, txq_id, sta_id, ssn = -1;
|
||||
struct iwl_tid_data *tid_data;
|
||||
int write_ptr, read_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ra) {
|
||||
IWL_ERR(priv, "ra = NULL\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tx_fifo_id = get_fifo_from_tid(tid);
|
||||
if (unlikely(tx_fifo_id < 0))
|
||||
return tx_fifo_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, ra);
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
|
||||
|
@ -1046,7 +1043,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
|
|||
if (priv->stations[sta_id].tid[tid].agg.state ==
|
||||
IWL_EMPTYING_HW_QUEUE_ADDBA) {
|
||||
IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
|
||||
return 0;
|
||||
}
|
||||
|
@ -1083,7 +1080,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
|
|||
tx_fifo_id);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,37 @@ static const s8 iwlagn_default_queue_to_tx_fifo[] = {
|
|||
IWL_TX_FIFO_UNUSED,
|
||||
};
|
||||
|
||||
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
|
||||
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
|
||||
0, COEX_UNASSOC_IDLE_FLAGS},
|
||||
{COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP,
|
||||
0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
|
||||
{COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP,
|
||||
0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
|
||||
{COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP,
|
||||
0, COEX_CALIBRATION_FLAGS},
|
||||
{COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP,
|
||||
0, COEX_PERIODIC_CALIBRATION_FLAGS},
|
||||
{COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP,
|
||||
0, COEX_CONNECTION_ESTAB_FLAGS},
|
||||
{COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP,
|
||||
0, COEX_ASSOCIATED_IDLE_FLAGS},
|
||||
{COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP,
|
||||
0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
|
||||
{COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP,
|
||||
0, COEX_ASSOC_AUTO_SCAN_FLAGS},
|
||||
{COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP,
|
||||
0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
|
||||
{COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS},
|
||||
{COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS},
|
||||
{COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP,
|
||||
0, COEX_STAND_ALONE_DEBUG_FLAGS},
|
||||
{COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP,
|
||||
0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
|
||||
{COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS},
|
||||
{COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS}
|
||||
};
|
||||
|
||||
/*
|
||||
* ucode
|
||||
*/
|
||||
|
@ -151,55 +182,6 @@ int iwlagn_load_ucode(struct iwl_priv *priv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define IWL_UCODE_GET(item) \
|
||||
static u32 iwlagn_ucode_get_##item(const struct iwl_ucode_header *ucode,\
|
||||
u32 api_ver) \
|
||||
{ \
|
||||
if (api_ver <= 2) \
|
||||
return le32_to_cpu(ucode->u.v1.item); \
|
||||
return le32_to_cpu(ucode->u.v2.item); \
|
||||
}
|
||||
|
||||
static u32 iwlagn_ucode_get_header_size(u32 api_ver)
|
||||
{
|
||||
if (api_ver <= 2)
|
||||
return UCODE_HEADER_SIZE(1);
|
||||
return UCODE_HEADER_SIZE(2);
|
||||
}
|
||||
|
||||
static u32 iwlagn_ucode_get_build(const struct iwl_ucode_header *ucode,
|
||||
u32 api_ver)
|
||||
{
|
||||
if (api_ver <= 2)
|
||||
return 0;
|
||||
return le32_to_cpu(ucode->u.v2.build);
|
||||
}
|
||||
|
||||
static u8 *iwlagn_ucode_get_data(const struct iwl_ucode_header *ucode,
|
||||
u32 api_ver)
|
||||
{
|
||||
if (api_ver <= 2)
|
||||
return (u8 *) ucode->u.v1.data;
|
||||
return (u8 *) ucode->u.v2.data;
|
||||
}
|
||||
|
||||
IWL_UCODE_GET(inst_size);
|
||||
IWL_UCODE_GET(data_size);
|
||||
IWL_UCODE_GET(init_size);
|
||||
IWL_UCODE_GET(init_data_size);
|
||||
IWL_UCODE_GET(boot_size);
|
||||
|
||||
struct iwl_ucode_ops iwlagn_ucode = {
|
||||
.get_header_size = iwlagn_ucode_get_header_size,
|
||||
.get_build = iwlagn_ucode_get_build,
|
||||
.get_inst_size = iwlagn_ucode_get_inst_size,
|
||||
.get_data_size = iwlagn_ucode_get_data_size,
|
||||
.get_init_size = iwlagn_ucode_get_init_size,
|
||||
.get_init_data_size = iwlagn_ucode_get_init_data_size,
|
||||
.get_boot_size = iwlagn_ucode_get_boot_size,
|
||||
.get_data = iwlagn_ucode_get_data,
|
||||
};
|
||||
|
||||
/*
|
||||
* Calibration
|
||||
*/
|
||||
|
@ -320,6 +302,33 @@ restart:
|
|||
queue_work(priv->workqueue, &priv->restart);
|
||||
}
|
||||
|
||||
static int iwlagn_send_wimax_coex(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_wimax_coex_cmd coex_cmd;
|
||||
|
||||
if (priv->cfg->support_wimax_coexist) {
|
||||
/* UnMask wake up src at associated sleep */
|
||||
coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
|
||||
|
||||
/* UnMask wake up src at unassociated sleep */
|
||||
coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK;
|
||||
memcpy(coex_cmd.sta_prio, cu_priorities,
|
||||
sizeof(struct iwl_wimax_coex_event_entry) *
|
||||
COEX_NUM_OF_EVENTS);
|
||||
|
||||
/* enabling the coexistence feature */
|
||||
coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK;
|
||||
|
||||
/* enabling the priorities tables */
|
||||
coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK;
|
||||
} else {
|
||||
/* coexistence is disabled */
|
||||
memset(&coex_cmd, 0, sizeof(coex_cmd));
|
||||
}
|
||||
return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
|
||||
sizeof(coex_cmd), &coex_cmd);
|
||||
}
|
||||
|
||||
int iwlagn_alive_notify(struct iwl_priv *priv)
|
||||
{
|
||||
u32 a;
|
||||
|
@ -407,7 +416,7 @@ int iwlagn_alive_notify(struct iwl_priv *priv)
|
|||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl_send_wimax_coex(priv);
|
||||
iwlagn_send_wimax_coex(priv);
|
||||
|
||||
iwlagn_set_Xtal_calib(priv);
|
||||
iwl_send_calib_results(priv);
|
||||
|
|
|
@ -157,7 +157,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
iwl_clear_ucode_stations(priv, false);
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
ret = iwl_restore_default_wep_keys(priv);
|
||||
if (ret) {
|
||||
|
@ -189,7 +189,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
|
|||
}
|
||||
IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
|
||||
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
|
||||
iwl_clear_ucode_stations(priv, false);
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_restore_stations(priv);
|
||||
ret = iwl_restore_default_wep_keys(priv);
|
||||
if (ret) {
|
||||
|
@ -1506,9 +1506,13 @@ static void iwl_nic_start(struct iwl_priv *priv)
|
|||
iwl_write32(priv, CSR_RESET, 0);
|
||||
}
|
||||
|
||||
struct iwlagn_ucode_capabilities {
|
||||
u32 max_probe_length;
|
||||
};
|
||||
|
||||
static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context);
|
||||
static int iwl_mac_setup_register(struct iwl_priv *priv);
|
||||
static int iwl_mac_setup_register(struct iwl_priv *priv,
|
||||
struct iwlagn_ucode_capabilities *capa);
|
||||
|
||||
static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
|
||||
{
|
||||
|
@ -1535,6 +1539,199 @@ static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first)
|
|||
iwl_ucode_callback);
|
||||
}
|
||||
|
||||
struct iwlagn_firmware_pieces {
|
||||
const void *inst, *data, *init, *init_data, *boot;
|
||||
size_t inst_size, data_size, init_size, init_data_size, boot_size;
|
||||
|
||||
u32 build;
|
||||
};
|
||||
|
||||
static int iwlagn_load_legacy_firmware(struct iwl_priv *priv,
|
||||
const struct firmware *ucode_raw,
|
||||
struct iwlagn_firmware_pieces *pieces)
|
||||
{
|
||||
struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
|
||||
u32 api_ver, hdr_size;
|
||||
const u8 *src;
|
||||
|
||||
priv->ucode_ver = le32_to_cpu(ucode->ver);
|
||||
api_ver = IWL_UCODE_API(priv->ucode_ver);
|
||||
|
||||
switch (api_ver) {
|
||||
default:
|
||||
/*
|
||||
* 4965 doesn't revision the firmware file format
|
||||
* along with the API version, it always uses v1
|
||||
* file format.
|
||||
*/
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) !=
|
||||
CSR_HW_REV_TYPE_4965) {
|
||||
hdr_size = 28;
|
||||
if (ucode_raw->size < hdr_size) {
|
||||
IWL_ERR(priv, "File size too small!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pieces->build = le32_to_cpu(ucode->u.v2.build);
|
||||
pieces->inst_size = le32_to_cpu(ucode->u.v2.inst_size);
|
||||
pieces->data_size = le32_to_cpu(ucode->u.v2.data_size);
|
||||
pieces->init_size = le32_to_cpu(ucode->u.v2.init_size);
|
||||
pieces->init_data_size = le32_to_cpu(ucode->u.v2.init_data_size);
|
||||
pieces->boot_size = le32_to_cpu(ucode->u.v2.boot_size);
|
||||
src = ucode->u.v2.data;
|
||||
break;
|
||||
}
|
||||
/* fall through for 4965 */
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
hdr_size = 24;
|
||||
if (ucode_raw->size < hdr_size) {
|
||||
IWL_ERR(priv, "File size too small!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
pieces->build = 0;
|
||||
pieces->inst_size = le32_to_cpu(ucode->u.v1.inst_size);
|
||||
pieces->data_size = le32_to_cpu(ucode->u.v1.data_size);
|
||||
pieces->init_size = le32_to_cpu(ucode->u.v1.init_size);
|
||||
pieces->init_data_size = le32_to_cpu(ucode->u.v1.init_data_size);
|
||||
pieces->boot_size = le32_to_cpu(ucode->u.v1.boot_size);
|
||||
src = ucode->u.v1.data;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Verify size of file vs. image size info in file's header */
|
||||
if (ucode_raw->size != hdr_size + pieces->inst_size +
|
||||
pieces->data_size + pieces->init_size +
|
||||
pieces->init_data_size + pieces->boot_size) {
|
||||
|
||||
IWL_ERR(priv,
|
||||
"uCode file size %d does not match expected size\n",
|
||||
(int)ucode_raw->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pieces->inst = src;
|
||||
src += pieces->inst_size;
|
||||
pieces->data = src;
|
||||
src += pieces->data_size;
|
||||
pieces->init = src;
|
||||
src += pieces->init_size;
|
||||
pieces->init_data = src;
|
||||
src += pieces->init_data_size;
|
||||
pieces->boot = src;
|
||||
src += pieces->boot_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwlagn_wanted_ucode_alternative = 1;
|
||||
|
||||
static int iwlagn_load_firmware(struct iwl_priv *priv,
|
||||
const struct firmware *ucode_raw,
|
||||
struct iwlagn_firmware_pieces *pieces,
|
||||
struct iwlagn_ucode_capabilities *capa)
|
||||
{
|
||||
struct iwl_tlv_ucode_header *ucode = (void *)ucode_raw->data;
|
||||
struct iwl_ucode_tlv *tlv;
|
||||
size_t len = ucode_raw->size;
|
||||
const u8 *data;
|
||||
int wanted_alternative = iwlagn_wanted_ucode_alternative, tmp;
|
||||
u64 alternatives;
|
||||
|
||||
if (len < sizeof(*ucode))
|
||||
return -EINVAL;
|
||||
|
||||
if (ucode->magic != cpu_to_le32(IWL_TLV_UCODE_MAGIC))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Check which alternatives are present, and "downgrade"
|
||||
* when the chosen alternative is not present, warning
|
||||
* the user when that happens. Some files may not have
|
||||
* any alternatives, so don't warn in that case.
|
||||
*/
|
||||
alternatives = le64_to_cpu(ucode->alternatives);
|
||||
tmp = wanted_alternative;
|
||||
if (wanted_alternative > 63)
|
||||
wanted_alternative = 63;
|
||||
while (wanted_alternative && !(alternatives & BIT(wanted_alternative)))
|
||||
wanted_alternative--;
|
||||
if (wanted_alternative && wanted_alternative != tmp)
|
||||
IWL_WARN(priv,
|
||||
"uCode alternative %d not available, choosing %d\n",
|
||||
tmp, wanted_alternative);
|
||||
|
||||
priv->ucode_ver = le32_to_cpu(ucode->ver);
|
||||
pieces->build = le32_to_cpu(ucode->build);
|
||||
data = ucode->data;
|
||||
|
||||
len -= sizeof(*ucode);
|
||||
|
||||
while (len >= sizeof(*tlv)) {
|
||||
u32 tlv_len;
|
||||
enum iwl_ucode_tlv_type tlv_type;
|
||||
u16 tlv_alt;
|
||||
const u8 *tlv_data;
|
||||
|
||||
len -= sizeof(*tlv);
|
||||
tlv = (void *)data;
|
||||
|
||||
tlv_len = le32_to_cpu(tlv->length);
|
||||
tlv_type = le16_to_cpu(tlv->type);
|
||||
tlv_alt = le16_to_cpu(tlv->alternative);
|
||||
tlv_data = tlv->data;
|
||||
|
||||
if (len < tlv_len)
|
||||
return -EINVAL;
|
||||
len -= ALIGN(tlv_len, 4);
|
||||
data += sizeof(*tlv) + ALIGN(tlv_len, 4);
|
||||
|
||||
/*
|
||||
* Alternative 0 is always valid.
|
||||
*
|
||||
* Skip alternative TLVs that are not selected.
|
||||
*/
|
||||
if (tlv_alt != 0 && tlv_alt != wanted_alternative)
|
||||
continue;
|
||||
|
||||
switch (tlv_type) {
|
||||
case IWL_UCODE_TLV_INST:
|
||||
pieces->inst = tlv_data;
|
||||
pieces->inst_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_DATA:
|
||||
pieces->data = tlv_data;
|
||||
pieces->data_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT:
|
||||
pieces->init = tlv_data;
|
||||
pieces->init_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_INIT_DATA:
|
||||
pieces->init_data = tlv_data;
|
||||
pieces->init_data_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_BOOT:
|
||||
pieces->boot = tlv_data;
|
||||
pieces->boot_size = tlv_len;
|
||||
break;
|
||||
case IWL_UCODE_TLV_PROBE_MAX_LEN:
|
||||
if (tlv_len != 4)
|
||||
return -EINVAL;
|
||||
capa->max_probe_length =
|
||||
le32_to_cpup((__le32 *)tlv_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (len)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_ucode_callback - callback when firmware was loaded
|
||||
*
|
||||
|
@ -1545,14 +1742,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
{
|
||||
struct iwl_priv *priv = context;
|
||||
struct iwl_ucode_header *ucode;
|
||||
int err;
|
||||
struct iwlagn_firmware_pieces pieces;
|
||||
const unsigned int api_max = priv->cfg->ucode_api_max;
|
||||
const unsigned int api_min = priv->cfg->ucode_api_min;
|
||||
u8 *src;
|
||||
size_t len;
|
||||
u32 api_ver, build;
|
||||
u32 inst_size, data_size, init_size, init_data_size, boot_size;
|
||||
int err;
|
||||
u16 eeprom_ver;
|
||||
u32 api_ver;
|
||||
char buildstr[25];
|
||||
u32 build;
|
||||
struct iwlagn_ucode_capabilities ucode_capa = {
|
||||
.max_probe_length = 200,
|
||||
};
|
||||
|
||||
memset(&pieces, 0, sizeof(pieces));
|
||||
|
||||
if (!ucode_raw) {
|
||||
IWL_ERR(priv, "request for firmware file '%s' failed.\n",
|
||||
|
@ -1563,8 +1764,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
|
||||
priv->firmware_name, ucode_raw->size);
|
||||
|
||||
/* Make sure that we got at least the v1 header! */
|
||||
if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
|
||||
/* Make sure that we got at least the API version number */
|
||||
if (ucode_raw->size < 4) {
|
||||
IWL_ERR(priv, "File size way too small!\n");
|
||||
goto try_again;
|
||||
}
|
||||
|
@ -1572,21 +1773,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
/* Data from ucode file: header followed by uCode images */
|
||||
ucode = (struct iwl_ucode_header *)ucode_raw->data;
|
||||
|
||||
priv->ucode_ver = le32_to_cpu(ucode->ver);
|
||||
if (ucode->ver)
|
||||
err = iwlagn_load_legacy_firmware(priv, ucode_raw, &pieces);
|
||||
else
|
||||
err = iwlagn_load_firmware(priv, ucode_raw, &pieces,
|
||||
&ucode_capa);
|
||||
|
||||
if (err)
|
||||
goto try_again;
|
||||
|
||||
api_ver = IWL_UCODE_API(priv->ucode_ver);
|
||||
build = priv->cfg->ops->ucode->get_build(ucode, api_ver);
|
||||
inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
|
||||
data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
|
||||
init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
|
||||
init_data_size =
|
||||
priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
|
||||
boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
|
||||
src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
|
||||
build = pieces.build;
|
||||
|
||||
/* api_ver should match the api version forming part of the
|
||||
/*
|
||||
* api_ver should match the api version forming part of the
|
||||
* firmware filename ... but we don't check for that and only rely
|
||||
* on the API version read from firmware header from here on forward */
|
||||
|
||||
* on the API version read from firmware header from here on forward
|
||||
*/
|
||||
if (api_ver < api_min || api_ver > api_max) {
|
||||
IWL_ERR(priv, "Driver unable to support your firmware API. "
|
||||
"Driver supports v%u, firmware is v%u.\n",
|
||||
|
@ -1600,40 +1803,26 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
"from http://www.intellinuxwireless.org.\n",
|
||||
api_max, api_ver);
|
||||
|
||||
IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
|
||||
IWL_UCODE_MAJOR(priv->ucode_ver),
|
||||
IWL_UCODE_MINOR(priv->ucode_ver),
|
||||
IWL_UCODE_API(priv->ucode_ver),
|
||||
IWL_UCODE_SERIAL(priv->ucode_ver));
|
||||
if (build)
|
||||
sprintf(buildstr, " build %u", build);
|
||||
else
|
||||
buildstr[0] = '\0';
|
||||
|
||||
snprintf(priv->hw->wiphy->fw_version,
|
||||
sizeof(priv->hw->wiphy->fw_version),
|
||||
"%u.%u.%u.%u",
|
||||
IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u%s\n",
|
||||
IWL_UCODE_MAJOR(priv->ucode_ver),
|
||||
IWL_UCODE_MINOR(priv->ucode_ver),
|
||||
IWL_UCODE_API(priv->ucode_ver),
|
||||
IWL_UCODE_SERIAL(priv->ucode_ver));
|
||||
IWL_UCODE_SERIAL(priv->ucode_ver),
|
||||
buildstr);
|
||||
|
||||
if (build)
|
||||
IWL_DEBUG_INFO(priv, "Build %u\n", build);
|
||||
|
||||
eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
|
||||
IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n",
|
||||
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
? "OTP" : "EEPROM", eeprom_ver);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
|
||||
priv->ucode_ver);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
|
||||
inst_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n",
|
||||
data_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n",
|
||||
init_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n",
|
||||
init_data_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
|
||||
boot_size);
|
||||
snprintf(priv->hw->wiphy->fw_version,
|
||||
sizeof(priv->hw->wiphy->fw_version),
|
||||
"%u.%u.%u.%u%s",
|
||||
IWL_UCODE_MAJOR(priv->ucode_ver),
|
||||
IWL_UCODE_MINOR(priv->ucode_ver),
|
||||
IWL_UCODE_API(priv->ucode_ver),
|
||||
IWL_UCODE_SERIAL(priv->ucode_ver),
|
||||
buildstr);
|
||||
|
||||
/*
|
||||
* For any of the failures below (before allocating pci memory)
|
||||
|
@ -1641,43 +1830,47 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
* user just got a corrupted version of the latest API.
|
||||
*/
|
||||
|
||||
/* Verify size of file vs. image size info in file's header */
|
||||
if (ucode_raw->size !=
|
||||
priv->cfg->ops->ucode->get_header_size(api_ver) +
|
||||
inst_size + data_size + init_size +
|
||||
init_data_size + boot_size) {
|
||||
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"uCode file size %d does not match expected size\n",
|
||||
(int)ucode_raw->size);
|
||||
goto try_again;
|
||||
}
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
|
||||
priv->ucode_ver);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n",
|
||||
pieces.inst_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n",
|
||||
pieces.data_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n",
|
||||
pieces.init_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
|
||||
pieces.init_data_size);
|
||||
IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n",
|
||||
pieces.boot_size);
|
||||
|
||||
/* Verify that uCode images will fit in card's SRAM */
|
||||
if (inst_size > priv->hw_params.max_inst_size) {
|
||||
IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
|
||||
inst_size);
|
||||
if (pieces.inst_size > priv->hw_params.max_inst_size) {
|
||||
IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
|
||||
pieces.inst_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (data_size > priv->hw_params.max_data_size) {
|
||||
IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
|
||||
data_size);
|
||||
if (pieces.data_size > priv->hw_params.max_data_size) {
|
||||
IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
|
||||
pieces.data_size);
|
||||
goto try_again;
|
||||
}
|
||||
if (init_size > priv->hw_params.max_inst_size) {
|
||||
IWL_INFO(priv, "uCode init instr len %d too large to fit in\n",
|
||||
init_size);
|
||||
|
||||
if (pieces.init_size > priv->hw_params.max_inst_size) {
|
||||
IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
|
||||
pieces.init_size);
|
||||
goto try_again;
|
||||
}
|
||||
if (init_data_size > priv->hw_params.max_data_size) {
|
||||
IWL_INFO(priv, "uCode init data len %d too large to fit in\n",
|
||||
init_data_size);
|
||||
|
||||
if (pieces.init_data_size > priv->hw_params.max_data_size) {
|
||||
IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
|
||||
pieces.init_data_size);
|
||||
goto try_again;
|
||||
}
|
||||
if (boot_size > priv->hw_params.max_bsm_size) {
|
||||
IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n",
|
||||
boot_size);
|
||||
|
||||
if (pieces.boot_size > priv->hw_params.max_bsm_size) {
|
||||
IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n",
|
||||
pieces.boot_size);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
|
@ -1686,13 +1879,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
/* Runtime instructions and 2 copies of data:
|
||||
* 1) unmodified from disk
|
||||
* 2) backup cache for save/restore during power-downs */
|
||||
priv->ucode_code.len = inst_size;
|
||||
priv->ucode_code.len = pieces.inst_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
|
||||
|
||||
priv->ucode_data.len = data_size;
|
||||
priv->ucode_data.len = pieces.data_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
|
||||
|
||||
priv->ucode_data_backup.len = data_size;
|
||||
priv->ucode_data_backup.len = pieces.data_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
|
||||
|
||||
if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
|
||||
|
@ -1700,11 +1893,11 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
goto err_pci_alloc;
|
||||
|
||||
/* Initialization instructions and data */
|
||||
if (init_size && init_data_size) {
|
||||
priv->ucode_init.len = init_size;
|
||||
if (pieces.init_size && pieces.init_data_size) {
|
||||
priv->ucode_init.len = pieces.init_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
|
||||
|
||||
priv->ucode_init_data.len = init_data_size;
|
||||
priv->ucode_init_data.len = pieces.init_data_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
|
||||
|
||||
if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
|
||||
|
@ -1712,8 +1905,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
}
|
||||
|
||||
/* Bootstrap (instructions only, no data) */
|
||||
if (boot_size) {
|
||||
priv->ucode_boot.len = boot_size;
|
||||
if (pieces.boot_size) {
|
||||
priv->ucode_boot.len = pieces.boot_size;
|
||||
iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
|
||||
|
||||
if (!priv->ucode_boot.v_addr)
|
||||
|
@ -1723,51 +1916,48 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
/* Copy images into buffers for card's bus-master reads ... */
|
||||
|
||||
/* Runtime instructions (first block of data in file) */
|
||||
len = inst_size;
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len);
|
||||
memcpy(priv->ucode_code.v_addr, src, len);
|
||||
src += len;
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n",
|
||||
pieces.inst_size);
|
||||
memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
|
||||
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
|
||||
|
||||
/* Runtime data (2nd block)
|
||||
* NOTE: Copy into backup buffer will be done in iwl_up() */
|
||||
len = data_size;
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len);
|
||||
memcpy(priv->ucode_data.v_addr, src, len);
|
||||
memcpy(priv->ucode_data_backup.v_addr, src, len);
|
||||
src += len;
|
||||
/*
|
||||
* Runtime data
|
||||
* NOTE: Copy into backup buffer will be done in iwl_up()
|
||||
*/
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n",
|
||||
pieces.data_size);
|
||||
memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size);
|
||||
memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
|
||||
|
||||
/* Initialization instructions (3rd block) */
|
||||
if (init_size) {
|
||||
len = init_size;
|
||||
/* Initialization instructions */
|
||||
if (pieces.init_size) {
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n",
|
||||
len);
|
||||
memcpy(priv->ucode_init.v_addr, src, len);
|
||||
src += len;
|
||||
pieces.init_size);
|
||||
memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size);
|
||||
}
|
||||
|
||||
/* Initialization data (4th block) */
|
||||
if (init_data_size) {
|
||||
len = init_data_size;
|
||||
/* Initialization data */
|
||||
if (pieces.init_data_size) {
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n",
|
||||
len);
|
||||
memcpy(priv->ucode_init_data.v_addr, src, len);
|
||||
src += len;
|
||||
pieces.init_data_size);
|
||||
memcpy(priv->ucode_init_data.v_addr, pieces.init_data,
|
||||
pieces.init_data_size);
|
||||
}
|
||||
|
||||
/* Bootstrap instructions (5th block) */
|
||||
len = boot_size;
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len);
|
||||
memcpy(priv->ucode_boot.v_addr, src, len);
|
||||
/* Bootstrap instructions */
|
||||
IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n",
|
||||
pieces.boot_size);
|
||||
memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
|
||||
|
||||
/**************************************************
|
||||
* This is still part of probe() in a sense...
|
||||
*
|
||||
* 9. Setup and register with mac80211 and debugfs
|
||||
**************************************************/
|
||||
err = iwl_mac_setup_register(priv);
|
||||
err = iwl_mac_setup_register(priv, &ucode_capa);
|
||||
if (err)
|
||||
goto out_unbind;
|
||||
|
||||
|
@ -1777,6 +1967,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
|
||||
/* We have our copies now, allow OS release its copies */
|
||||
release_firmware(ucode_raw);
|
||||
complete(&priv->_agn.firmware_loading_complete);
|
||||
return;
|
||||
|
||||
try_again:
|
||||
|
@ -1790,6 +1981,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
|
|||
IWL_ERR(priv, "failed to allocate pci memory\n");
|
||||
iwl_dealloc_ucode_pci(priv);
|
||||
out_unbind:
|
||||
complete(&priv->_agn.firmware_loading_complete);
|
||||
device_release_driver(&priv->pci_dev->dev);
|
||||
release_firmware(ucode_raw);
|
||||
}
|
||||
|
@ -2165,7 +2357,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
|
|||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
} else {
|
||||
/* Initialize our rx_config data */
|
||||
iwl_connection_init_rx_config(priv, priv->iw_mode);
|
||||
iwl_connection_init_rx_config(priv, NULL);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
@ -2212,7 +2404,9 @@ static void __iwl_down(struct iwl_priv *priv)
|
|||
if (!exit_pending)
|
||||
set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
iwl_clear_ucode_stations(priv, true);
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_dealloc_bcast_station(priv);
|
||||
iwl_clear_driver_stations(priv);
|
||||
|
||||
/* Unblock any waiting calls */
|
||||
wake_up_interruptible_all(&priv->wait_command_queue);
|
||||
|
@ -2359,6 +2553,10 @@ static int __iwl_up(struct iwl_priv *priv)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
ret = iwl_alloc_bcast_station(priv, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iwl_prepare_card_hw(priv);
|
||||
|
||||
if (!priv->hw_ready) {
|
||||
|
@ -2537,12 +2735,15 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
|
|||
|
||||
#define IWL_DELAY_NEXT_SCAN (HZ*2)
|
||||
|
||||
void iwl_post_associate(struct iwl_priv *priv)
|
||||
void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_AP) {
|
||||
if (!vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
@ -2550,10 +2751,6 @@ void iwl_post_associate(struct iwl_priv *priv)
|
|||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
|
||||
if (!priv->vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
@ -2561,7 +2758,7 @@ void iwl_post_associate(struct iwl_priv *priv)
|
|||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
||||
iwl_setup_rxon_timing(priv);
|
||||
iwl_setup_rxon_timing(priv, vif);
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
|
||||
sizeof(priv->rxon_timing), &priv->rxon_timing);
|
||||
if (ret)
|
||||
|
@ -2575,49 +2772,41 @@ void iwl_post_associate(struct iwl_priv *priv)
|
|||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
priv->assoc_id, priv->beacon_int);
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
|
||||
priv->assoc_id, priv->active_rxon.bssid_addr);
|
||||
vif->bss_conf.aid, priv->active_rxon.bssid_addr);
|
||||
|
||||
switch (priv->iw_mode) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
break;
|
||||
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
|
||||
/* assume default assoc id */
|
||||
priv->assoc_id = 1;
|
||||
|
||||
iwl_add_local_station(priv, priv->bssid, true);
|
||||
iwl_send_beacon_cmd(priv);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_ERR(priv, "%s Should not be called in %d mode\n",
|
||||
__func__, priv->iw_mode);
|
||||
__func__, vif->type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2645,7 +2834,8 @@ void iwl_post_associate(struct iwl_priv *priv)
|
|||
* Not a mac80211 entry point function, but it fits in with all the
|
||||
* other mac80211 functions grouped here.
|
||||
*/
|
||||
static int iwl_mac_setup_register(struct iwl_priv *priv)
|
||||
static int iwl_mac_setup_register(struct iwl_priv *priv,
|
||||
struct iwlagn_ucode_capabilities *capa)
|
||||
{
|
||||
int ret;
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
|
@ -2665,6 +2855,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)
|
|||
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
|
||||
|
||||
hw->sta_data_size = sizeof(struct iwl_station_priv);
|
||||
hw->vif_data_size = sizeof(struct iwl_vif_priv);
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
@ -2680,7 +2872,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)
|
|||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
|
||||
/* we create the 802.11 header and a zero-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
|
||||
hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2;
|
||||
|
||||
/* Default value; 4 EDCA QOS priorities */
|
||||
hw->queues = 4;
|
||||
|
@ -2793,7 +2985,7 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
void iwl_config_ap(struct iwl_priv *priv)
|
||||
void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
@ -2808,7 +3000,7 @@ void iwl_config_ap(struct iwl_priv *priv)
|
|||
iwlcore_commit_rxon(priv);
|
||||
|
||||
/* RXON Timing */
|
||||
iwl_setup_rxon_timing(priv);
|
||||
iwl_setup_rxon_timing(priv, vif);
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
|
||||
sizeof(priv->rxon_timing), &priv->rxon_timing);
|
||||
if (ret)
|
||||
|
@ -2822,9 +3014,10 @@ void iwl_config_ap(struct iwl_priv *priv)
|
|||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
||||
/* FIXME: what should be the assoc_id for AP? */
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
|
||||
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
priv->staging_rxon.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
|
@ -2832,22 +3025,21 @@ void iwl_config_ap(struct iwl_priv *priv)
|
|||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (priv->assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* restore RXON assoc */
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
iwl_add_bcast_station(priv);
|
||||
}
|
||||
iwl_send_beacon_cmd(priv);
|
||||
|
||||
|
@ -2866,8 +3058,7 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
|
|||
struct iwl_priv *priv = hw->priv;
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
iwl_update_tkip_key(priv, keyconf,
|
||||
sta ? sta->addr : iwl_bcast_addr,
|
||||
iwl_update_tkip_key(priv, keyconf, sta,
|
||||
iv32, phase1key);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
@ -2879,7 +3070,6 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
const u8 *addr;
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
bool is_default_wep_key = false;
|
||||
|
@ -2890,13 +3080,17 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
addr = sta ? sta->addr : iwl_bcast_addr;
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
|
||||
if (sta) {
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
@ -2945,8 +3139,8 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
|
||||
static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
int ret;
|
||||
|
@ -2960,17 +3154,17 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||
switch (action) {
|
||||
case IEEE80211_AMPDU_RX_START:
|
||||
IWL_DEBUG_HT(priv, "start Rx\n");
|
||||
return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn);
|
||||
return iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
|
||||
case IEEE80211_AMPDU_RX_STOP:
|
||||
IWL_DEBUG_HT(priv, "stop Rx\n");
|
||||
ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid);
|
||||
ret = iwl_sta_rx_agg_stop(priv, sta, tid);
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return 0;
|
||||
else
|
||||
return ret;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
IWL_DEBUG_HT(priv, "start Tx\n");
|
||||
ret = iwlagn_tx_agg_start(priv, sta->addr, tid, ssn);
|
||||
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
|
||||
if (ret == 0) {
|
||||
priv->_agn.agg_tids_count++;
|
||||
IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
|
||||
|
@ -2979,7 +3173,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
|||
return ret;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
IWL_DEBUG_HT(priv, "stop Tx\n");
|
||||
ret = iwlagn_tx_agg_stop(priv, sta->addr, tid);
|
||||
ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
|
||||
if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) {
|
||||
priv->_agn.agg_tids_count--;
|
||||
IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
|
||||
|
@ -3021,7 +3215,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
|
|||
if (!sta_priv->asleep)
|
||||
break;
|
||||
sta_priv->asleep = false;
|
||||
sta_id = iwl_find_station(priv, sta->addr);
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id != IWL_INVALID_STATION)
|
||||
iwl_sta_modify_ps_wake(priv, sta_id);
|
||||
break;
|
||||
|
@ -3036,10 +3230,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
|||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION;
|
||||
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
|
||||
sta_priv->common.sta_id = IWL_INVALID_STATION;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
|
||||
sta->addr);
|
||||
|
||||
|
@ -3056,12 +3252,14 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
|||
return ret;
|
||||
}
|
||||
|
||||
sta_priv->common.sta_id = sta_id;
|
||||
|
||||
/* Initialize rate scaling */
|
||||
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
|
||||
sta->addr);
|
||||
iwl_rs_rate_init(priv, sta, sta_id);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -3586,6 +3784,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
|||
iwl_power_initialize(priv);
|
||||
iwl_tt_initialize(priv);
|
||||
|
||||
init_completion(&priv->_agn.firmware_loading_complete);
|
||||
|
||||
err = iwl_request_firmware(priv, true);
|
||||
if (err)
|
||||
goto out_remove_sysfs;
|
||||
|
@ -3626,6 +3826,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
|||
if (!priv)
|
||||
return;
|
||||
|
||||
wait_for_completion(&priv->_agn.firmware_loading_complete);
|
||||
|
||||
IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
|
||||
|
||||
iwl_dbgfs_unregister(priv);
|
||||
|
@ -3783,11 +3985,10 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
|||
{IWL_PCI_DEVICE(0x4239, 0x1311, iwl6000i_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
|
||||
|
||||
/* 6x00 Series Gen2 */
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1321, iwl6000g2_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1311, iwl6000g2_2agn_cfg)},
|
||||
/* 6x00 Series Gen2a */
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)},
|
||||
|
||||
/* 6x50 WiFi/WiMax Series */
|
||||
{IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)},
|
||||
|
@ -3900,3 +4101,8 @@ MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
|
|||
module_param_named(
|
||||
disable_hw_scan, iwlagn_mod_params.disable_hw_scan, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
|
||||
|
||||
module_param_named(ucode_alternative, iwlagn_wanted_ucode_alternative, int,
|
||||
S_IRUGO);
|
||||
MODULE_PARM_DESC(ucode_alternative,
|
||||
"specify ucode alternative to use from ucode file");
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include "iwl-dev.h"
|
||||
|
||||
extern struct iwl_mod_params iwlagn_mod_params;
|
||||
extern struct iwl_ucode_ops iwlagn_ucode;
|
||||
extern struct iwl_hcmd_ops iwlagn_hcmd;
|
||||
extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
|
||||
|
||||
|
@ -136,9 +135,10 @@ void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
|
|||
void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
|
||||
struct ieee80211_tx_info *info);
|
||||
int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
||||
int iwlagn_tx_agg_start(struct iwl_priv *priv,
|
||||
const u8 *ra, u16 tid, u16 *ssn);
|
||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
|
||||
int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
|
||||
int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, u16 tid);
|
||||
int iwlagn_txq_check_empty(struct iwl_priv *priv,
|
||||
int sta_id, u8 tid, int txq_id);
|
||||
void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
|
@ -172,6 +172,10 @@ static inline bool iwl_is_tx_success(u32 status)
|
|||
}
|
||||
|
||||
/* scan */
|
||||
void iwlagn_request_scan(struct iwl_priv *priv);
|
||||
void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
|
||||
/* station mgmt */
|
||||
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add);
|
||||
|
||||
#endif /* __iwl_agn_h__ */
|
||||
|
|
|
@ -2668,7 +2668,6 @@ struct iwl_ssid_ie {
|
|||
#define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff)
|
||||
#define IWL_MAX_SCAN_SIZE 1024
|
||||
#define IWL_MAX_CMD_SIZE 4096
|
||||
#define IWL_MAX_PROBE_REQUEST 200
|
||||
|
||||
/*
|
||||
* REPLY_SCAN_CMD = 0x80 (command)
|
||||
|
@ -3128,6 +3127,11 @@ struct statistics_tx {
|
|||
__le32 cts_timeout_collision;
|
||||
__le32 ack_or_ba_timeout_collision;
|
||||
struct statistics_tx_non_phy_agg agg;
|
||||
/*
|
||||
* "tx_power" are optional parameters provided by uCode,
|
||||
* 6000 series is the only device provide the information,
|
||||
* Those are reserved fields for all the other devices
|
||||
*/
|
||||
struct statistics_tx_power tx_power;
|
||||
__le32 reserved1;
|
||||
} __attribute__ ((packed));
|
||||
|
|
|
@ -68,37 +68,6 @@ static bool bt_coex_active = true;
|
|||
module_param(bt_coex_active, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
|
||||
|
||||
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
|
||||
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
|
||||
0, COEX_UNASSOC_IDLE_FLAGS},
|
||||
{COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP,
|
||||
0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
|
||||
{COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP,
|
||||
0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
|
||||
{COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP,
|
||||
0, COEX_CALIBRATION_FLAGS},
|
||||
{COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP,
|
||||
0, COEX_PERIODIC_CALIBRATION_FLAGS},
|
||||
{COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP,
|
||||
0, COEX_CONNECTION_ESTAB_FLAGS},
|
||||
{COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP,
|
||||
0, COEX_ASSOCIATED_IDLE_FLAGS},
|
||||
{COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP,
|
||||
0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
|
||||
{COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP,
|
||||
0, COEX_ASSOC_AUTO_SCAN_FLAGS},
|
||||
{COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP,
|
||||
0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
|
||||
{COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS},
|
||||
{COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS},
|
||||
{COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP,
|
||||
0, COEX_STAND_ALONE_DEBUG_FLAGS},
|
||||
{COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP,
|
||||
0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
|
||||
{COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS},
|
||||
{COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS}
|
||||
};
|
||||
|
||||
#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
|
||||
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
|
||||
IWL_RATE_SISO_##s##M_PLCP, \
|
||||
|
@ -512,7 +481,7 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
|
|||
return new_val;
|
||||
}
|
||||
|
||||
void iwl_setup_rxon_timing(struct iwl_priv *priv)
|
||||
void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
u64 tsf;
|
||||
s32 interval_tm, rem;
|
||||
|
@ -526,15 +495,14 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv)
|
|||
priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
|
||||
priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
|
||||
beacon_int = priv->beacon_int;
|
||||
priv->rxon_timing.atim_window = 0;
|
||||
} else {
|
||||
beacon_int = priv->vif->bss_conf.beacon_int;
|
||||
beacon_int = vif->bss_conf.beacon_int;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
/* TODO: we need to get atim_window from upper stack
|
||||
* for now we set to 0 */
|
||||
priv->rxon_timing.atim_window = 0;
|
||||
} else {
|
||||
priv->rxon_timing.atim_window = 0;
|
||||
}
|
||||
|
||||
beacon_int = iwl_adjust_beacon_interval(beacon_int,
|
||||
|
@ -925,8 +893,9 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_set_rxon_channel);
|
||||
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
enum ieee80211_band band)
|
||||
static void iwl_set_flags_for_band(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
if (band == IEEE80211_BAND_5GHZ) {
|
||||
priv->staging_rxon.flags &=
|
||||
|
@ -935,12 +904,12 @@ void iwl_set_flags_for_band(struct iwl_priv *priv,
|
|||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
} else {
|
||||
/* Copied from iwl_post_associate() */
|
||||
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif && vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
|
||||
if (vif && vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK;
|
||||
|
@ -952,13 +921,18 @@ void iwl_set_flags_for_band(struct iwl_priv *priv,
|
|||
/*
|
||||
* initialize rxon structure with default values from eeprom
|
||||
*/
|
||||
void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
|
||||
void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
const struct iwl_channel_info *ch_info;
|
||||
enum nl80211_iftype type = NL80211_IFTYPE_STATION;
|
||||
|
||||
if (vif)
|
||||
type = vif->type;
|
||||
|
||||
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
|
||||
|
||||
switch (mode) {
|
||||
switch (type) {
|
||||
case NL80211_IFTYPE_AP:
|
||||
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
|
||||
break;
|
||||
|
@ -976,7 +950,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
|
|||
break;
|
||||
|
||||
default:
|
||||
IWL_ERR(priv, "Unsupported interface type %d\n", mode);
|
||||
IWL_ERR(priv, "Unsupported interface type %d\n", type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -998,7 +972,7 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
|
|||
priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
|
||||
priv->band = ch_info->band;
|
||||
|
||||
iwl_set_flags_for_band(priv, priv->band);
|
||||
iwl_set_flags_for_band(priv, priv->band, vif);
|
||||
|
||||
priv->staging_rxon.ofdm_basic_rates =
|
||||
(IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
|
||||
|
@ -1099,6 +1073,9 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
|
|||
/* Cancel currently queued command. */
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
|
||||
IWL_ERR(priv, "Loaded firmware version: %s\n",
|
||||
priv->hw->wiphy->fw_version);
|
||||
|
||||
priv->cfg->ops->lib->dump_nic_error_log(priv);
|
||||
if (priv->cfg->ops->lib->dump_csr)
|
||||
priv->cfg->ops->lib->dump_csr(priv);
|
||||
|
@ -1285,41 +1262,33 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
|
|||
u64 multicast)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
__le32 *filter_flags = &priv->staging_rxon.filter_flags;
|
||||
__le32 filter_or = 0, filter_nand = 0;
|
||||
|
||||
#define CHK(test, flag) do { \
|
||||
if (*total_flags & (test)) \
|
||||
filter_or |= (flag); \
|
||||
else \
|
||||
filter_nand |= (flag); \
|
||||
} while (0)
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
|
||||
changed_flags, *total_flags);
|
||||
|
||||
if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
|
||||
if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
|
||||
*filter_flags |= RXON_FILTER_PROMISC_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_PROMISC_MSK;
|
||||
}
|
||||
if (changed_flags & FIF_ALLMULTI) {
|
||||
if (*total_flags & FIF_ALLMULTI)
|
||||
*filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
}
|
||||
if (changed_flags & FIF_CONTROL) {
|
||||
if (*total_flags & FIF_CONTROL)
|
||||
*filter_flags |= RXON_FILTER_CTL2HOST_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
|
||||
}
|
||||
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
|
||||
if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
|
||||
*filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
|
||||
else
|
||||
*filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
|
||||
}
|
||||
CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
|
||||
CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK);
|
||||
CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
|
||||
CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
|
||||
|
||||
/* We avoid iwl_commit_rxon here to commit the new filter flags
|
||||
* since mac80211 will call ieee80211_hw_config immediately.
|
||||
* (mc_list is not supported at this time). Otherwise, we need to
|
||||
* queue a background iwl_commit_rxon work.
|
||||
*/
|
||||
#undef CHK
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
priv->staging_rxon.filter_flags &= ~filter_nand;
|
||||
priv->staging_rxon.filter_flags |= filter_or;
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
|
||||
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
|
||||
|
@ -1771,10 +1740,11 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
|||
EXPORT_SYMBOL(iwl_mac_conf_tx);
|
||||
|
||||
static void iwl_ht_conf(struct iwl_priv *priv,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter:\n");
|
||||
|
||||
|
@ -1788,10 +1758,10 @@ static void iwl_ht_conf(struct iwl_priv *priv,
|
|||
|
||||
ht_conf->single_chain_sufficient = false;
|
||||
|
||||
switch (priv->iw_mode) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(priv->vif, priv->bssid);
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (sta) {
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
int maxstreams;
|
||||
|
@ -1829,7 +1799,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
|
|||
|
||||
static inline void iwl_set_no_assoc(struct iwl_priv *priv)
|
||||
{
|
||||
priv->assoc_id = 0;
|
||||
iwl_led_disassociate(priv);
|
||||
/*
|
||||
* inform the ucode that there is no longer an
|
||||
|
@ -1857,14 +1826,12 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON &&
|
||||
priv->iw_mode == NL80211_IFTYPE_AP) {
|
||||
if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
|
||||
dev_kfree_skb(priv->ibss_beacon);
|
||||
priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_INT) {
|
||||
priv->beacon_int = bss_conf->beacon_int;
|
||||
/* TODO: in AP mode, do something to make this take effect */
|
||||
}
|
||||
|
||||
|
@ -1884,8 +1851,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
/* mac80211 only sets assoc when in STATION mode */
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
|
||||
bss_conf->assoc) {
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
|
||||
memcpy(priv->staging_rxon.bssid_addr,
|
||||
bss_conf->bssid, ETH_ALEN);
|
||||
|
||||
|
@ -1903,7 +1869,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
* mac80211 decides to do both changes at once because
|
||||
* it will invoke post_associate.
|
||||
*/
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC &&
|
||||
changes & BSS_CHANGED_BEACON) {
|
||||
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
|
||||
|
||||
|
@ -1946,7 +1912,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
if (changes & BSS_CHANGED_HT) {
|
||||
iwl_ht_conf(priv, bss_conf);
|
||||
iwl_ht_conf(priv, vif);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
@ -1955,20 +1921,17 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
if (changes & BSS_CHANGED_ASSOC) {
|
||||
IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
|
||||
if (bss_conf->assoc) {
|
||||
priv->assoc_id = bss_conf->aid;
|
||||
priv->beacon_int = bss_conf->beacon_int;
|
||||
priv->timestamp = bss_conf->timestamp;
|
||||
priv->assoc_capability = bss_conf->assoc_capability;
|
||||
|
||||
iwl_led_associate(priv);
|
||||
|
||||
if (!iwl_is_rfkill(priv))
|
||||
priv->cfg->ops->lib->post_associate(priv);
|
||||
priv->cfg->ops->lib->post_associate(priv, vif);
|
||||
} else
|
||||
iwl_set_no_assoc(priv);
|
||||
}
|
||||
|
||||
if (changes && iwl_is_associated(priv) && priv->assoc_id) {
|
||||
if (changes && iwl_is_associated(priv) && bss_conf->aid) {
|
||||
IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
|
||||
changes);
|
||||
ret = iwl_send_rxon_assoc(priv);
|
||||
|
@ -1985,11 +1948,20 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
|||
memcpy(priv->staging_rxon.bssid_addr,
|
||||
bss_conf->bssid, ETH_ALEN);
|
||||
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
iwlcore_config_ap(priv);
|
||||
iwlcore_config_ap(priv, vif);
|
||||
} else
|
||||
iwl_set_no_assoc(priv);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_IBSS) {
|
||||
ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif,
|
||||
bss_conf->ibss_joined);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed to %s IBSS station %pM\n",
|
||||
bss_conf->ibss_joined ? "add" : "remove",
|
||||
bss_conf->bssid);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
@ -2016,14 +1988,13 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
|
||||
priv->ibss_beacon = skb;
|
||||
|
||||
priv->assoc_id = 0;
|
||||
timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
|
||||
priv->timestamp = le64_to_cpu(timestamp);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
priv->cfg->ops->lib->post_associate(priv);
|
||||
priv->cfg->ops->lib->post_associate(priv, priv->vif);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2031,7 +2002,7 @@ EXPORT_SYMBOL(iwl_mac_beacon_update);
|
|||
|
||||
static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
iwl_connection_init_rx_config(priv, vif->type);
|
||||
iwl_connection_init_rx_config(priv, vif);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv);
|
||||
|
@ -2071,9 +2042,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
|||
if (err)
|
||||
goto out_err;
|
||||
|
||||
/* Add the broadcast address so we can send broadcast frames */
|
||||
priv->cfg->ops->lib->add_bcast_station(priv);
|
||||
|
||||
goto out;
|
||||
|
||||
out_err:
|
||||
|
@ -2096,8 +2064,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
|||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
iwl_clear_ucode_stations(priv, true);
|
||||
|
||||
if (iwl_is_ready_rf(priv)) {
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
@ -2203,7 +2169,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
iwl_set_rxon_channel(priv, conf->channel);
|
||||
iwl_set_rxon_ht(priv, ht_conf);
|
||||
|
||||
iwl_set_flags_for_band(priv, conf->channel->band);
|
||||
iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
if (iwl_is_associated(priv) &&
|
||||
(le16_to_cpu(priv->active_rxon.channel) != ch) &&
|
||||
|
@ -2286,8 +2252,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
|
|||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
priv->assoc_id = 0;
|
||||
priv->assoc_capability = 0;
|
||||
|
||||
/* new association get rid of ibss beacon skb */
|
||||
if (priv->ibss_beacon)
|
||||
|
@ -2295,7 +2259,6 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
|
|||
|
||||
priv->ibss_beacon = NULL;
|
||||
|
||||
priv->beacon_int = priv->vif->bss_conf.beacon_int;
|
||||
priv->timestamp = 0;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
@ -2342,34 +2305,6 @@ void iwl_free_txq_mem(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_free_txq_mem);
|
||||
|
||||
int iwl_send_wimax_coex(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_wimax_coex_cmd coex_cmd;
|
||||
|
||||
if (priv->cfg->support_wimax_coexist) {
|
||||
/* UnMask wake up src at associated sleep */
|
||||
coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
|
||||
|
||||
/* UnMask wake up src at unassociated sleep */
|
||||
coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK;
|
||||
memcpy(coex_cmd.sta_prio, cu_priorities,
|
||||
sizeof(struct iwl_wimax_coex_event_entry) *
|
||||
COEX_NUM_OF_EVENTS);
|
||||
|
||||
/* enabling the coexistence feature */
|
||||
coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK;
|
||||
|
||||
/* enabling the priorities tables */
|
||||
coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK;
|
||||
} else {
|
||||
/* coexistence is disabled */
|
||||
memset(&coex_cmd, 0, sizeof(coex_cmd));
|
||||
}
|
||||
return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
|
||||
sizeof(coex_cmd), &coex_cmd);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_wimax_coex);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
||||
#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
|
||||
|
|
|
@ -106,7 +106,7 @@ struct iwl_hcmd_utils_ops {
|
|||
__le32 *tx_flags);
|
||||
int (*calc_rssi)(struct iwl_priv *priv,
|
||||
struct iwl_rx_phy_res *rx_resp);
|
||||
void (*request_scan)(struct iwl_priv *priv);
|
||||
void (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
};
|
||||
|
||||
struct iwl_apm_ops {
|
||||
|
@ -131,17 +131,6 @@ struct iwl_temp_ops {
|
|||
void (*set_calib_version)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_ucode_ops {
|
||||
u32 (*get_header_size)(u32);
|
||||
u32 (*get_build)(const struct iwl_ucode_header *, u32);
|
||||
u32 (*get_inst_size)(const struct iwl_ucode_header *, u32);
|
||||
u32 (*get_data_size)(const struct iwl_ucode_header *, u32);
|
||||
u32 (*get_init_size)(const struct iwl_ucode_header *, u32);
|
||||
u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32);
|
||||
u32 (*get_boot_size)(const struct iwl_ucode_header *, u32);
|
||||
u8 * (*get_data)(const struct iwl_ucode_header *, u32);
|
||||
};
|
||||
|
||||
struct iwl_lib_ops {
|
||||
/* set hw dependent parameters */
|
||||
int (*set_hw_params)(struct iwl_priv *priv);
|
||||
|
@ -191,8 +180,9 @@ struct iwl_lib_ops {
|
|||
/* power */
|
||||
int (*send_tx_power) (struct iwl_priv *priv);
|
||||
void (*update_chain_flags)(struct iwl_priv *priv);
|
||||
void (*post_associate) (struct iwl_priv *priv);
|
||||
void (*config_ap) (struct iwl_priv *priv);
|
||||
void (*post_associate)(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
irqreturn_t (*isr) (int irq, void *data);
|
||||
|
||||
/* eeprom operations (as defined in iwl-eeprom.h) */
|
||||
|
@ -201,7 +191,8 @@ struct iwl_lib_ops {
|
|||
/* temperature */
|
||||
struct iwl_temp_ops temp_ops;
|
||||
/* station management */
|
||||
void (*add_bcast_station)(struct iwl_priv *priv);
|
||||
int (*manage_ibss_station)(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add);
|
||||
/* recover from tx queue stall */
|
||||
void (*recover_from_tx_stall)(unsigned long data);
|
||||
/* check for plcp health */
|
||||
|
@ -220,7 +211,6 @@ struct iwl_led_ops {
|
|||
};
|
||||
|
||||
struct iwl_ops {
|
||||
const struct iwl_ucode_ops *ucode;
|
||||
const struct iwl_lib_ops *lib;
|
||||
const struct iwl_hcmd_ops *hcmd;
|
||||
const struct iwl_hcmd_utils_ops *utils;
|
||||
|
@ -257,6 +247,18 @@ struct iwl_mod_params {
|
|||
* @support_wimax_coexist: support wimax/wifi co-exist
|
||||
* @plcp_delta_threshold: plcp error rate threshold used to trigger
|
||||
* radio tuning when there is a high receiving plcp error rate
|
||||
* @chain_noise_scale: default chain noise scale used for gain computation
|
||||
* @monitor_recover_period: default timer used to check stuck queues
|
||||
* @temperature_kelvin: temperature report by uCode in kelvin
|
||||
* @max_event_log_size: size of event log buffer size for ucode event logging
|
||||
* @tx_power_by_driver: tx power calibration performed by driver
|
||||
* instead of uCode
|
||||
* @ucode_tracing: support ucode continuous tracing
|
||||
* @sensitivity_calib_by_driver: driver has the capability to perform
|
||||
* sensitivity calibration operation
|
||||
* @chain_noise_calib_by_driver: driver has the capability to perform
|
||||
* chain noise calibration operation
|
||||
* @scan_antennas: available antenna for scan operation
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt API version. The
|
||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||
|
@ -319,6 +321,10 @@ struct iwl_cfg {
|
|||
u32 monitor_recover_period;
|
||||
bool temperature_kelvin;
|
||||
u32 max_event_log_size;
|
||||
const bool tx_power_by_driver;
|
||||
const bool ucode_tracing;
|
||||
const bool sensitivity_calib_by_driver;
|
||||
const bool chain_noise_calib_by_driver;
|
||||
u8 scan_antennas[IEEE80211_NUM_BANDS];
|
||||
};
|
||||
|
||||
|
@ -340,8 +346,8 @@ int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
|
|||
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf);
|
||||
u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
|
||||
struct ieee80211_sta_ht_cap *sta_ht_inf);
|
||||
void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band);
|
||||
void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode);
|
||||
void iwl_connection_init_rx_config(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
||||
struct ieee80211_hdr *hdr,
|
||||
u32 decrypt_res,
|
||||
|
@ -351,7 +357,7 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
|
|||
unsigned int changed_flags,
|
||||
unsigned int *total_flags, u64 multicast);
|
||||
int iwl_set_hw_params(struct iwl_priv *priv);
|
||||
void iwl_post_associate(struct iwl_priv *priv);
|
||||
void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
|
@ -363,13 +369,12 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
|||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void iwl_config_ap(struct iwl_priv *priv);
|
||||
void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
|
||||
int iwl_alloc_txq_mem(struct iwl_priv *priv);
|
||||
void iwl_free_txq_mem(struct iwl_priv *priv);
|
||||
void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
|
||||
__le32 *tx_flags);
|
||||
int iwl_send_wimax_coex(struct iwl_priv *priv);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int iwl_alloc_traffic_mem(struct iwl_priv *priv);
|
||||
void iwl_free_traffic_mem(struct iwl_priv *priv);
|
||||
|
@ -448,6 +453,8 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
|
|||
struct iwl_rx_packet *pkt);
|
||||
bool iwl_good_ack_health(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt);
|
||||
void iwl_recover_from_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt);
|
||||
void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_reply_statistics(struct iwl_priv *priv,
|
||||
|
@ -515,6 +522,7 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
|||
int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct cfg80211_scan_request *req);
|
||||
void iwl_bg_start_internal_scan(struct work_struct *work);
|
||||
void iwl_internal_short_hw_scan(struct iwl_priv *priv);
|
||||
int iwl_force_reset(struct iwl_priv *priv, int mode);
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
|
@ -524,7 +532,8 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
|
|||
enum ieee80211_band band,
|
||||
u8 n_probes);
|
||||
u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band);
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_bg_scan_check(struct work_struct *data);
|
||||
void iwl_bg_abort_scan(struct work_struct *work);
|
||||
void iwl_bg_scan_completed(struct work_struct *work);
|
||||
|
@ -688,7 +697,7 @@ extern int iwl_send_lq_cmd(struct iwl_priv *priv,
|
|||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
int iwl_apm_init(struct iwl_priv *priv);
|
||||
|
||||
void iwl_setup_rxon_timing(struct iwl_priv *priv);
|
||||
void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
|
||||
{
|
||||
return priv->cfg->ops->hcmd->rxon_assoc(priv);
|
||||
|
@ -697,9 +706,10 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv)
|
|||
{
|
||||
return priv->cfg->ops->hcmd->commit_rxon(priv);
|
||||
}
|
||||
static inline void iwlcore_config_ap(struct iwl_priv *priv)
|
||||
static inline void iwlcore_config_ap(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
priv->cfg->ops->lib->config_ap(priv);
|
||||
priv->cfg->ops->lib->config_ap(priv, vif);
|
||||
}
|
||||
static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
|
||||
struct iwl_priv *priv, enum ieee80211_band band)
|
||||
|
|
|
@ -1220,46 +1220,6 @@ static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
char buf[128];
|
||||
int pos = 0;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
struct statistics_tx *tx;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
|
||||
else {
|
||||
tx = &priv->statistics.tx;
|
||||
if (tx->tx_power.ant_a ||
|
||||
tx->tx_power.ant_b ||
|
||||
tx->tx_power.ant_c) {
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"tx power: (1/2 dB step)\n");
|
||||
if ((priv->cfg->valid_tx_ant & ANT_A) &&
|
||||
tx->tx_power.ant_a)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna A: 0x%X\n",
|
||||
tx->tx_power.ant_a);
|
||||
if ((priv->cfg->valid_tx_ant & ANT_B) &&
|
||||
tx->tx_power.ant_b)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna B: 0x%X\n",
|
||||
tx->tx_power.ant_b);
|
||||
if ((priv->cfg->valid_tx_ant & ANT_C) &&
|
||||
tx->tx_power.ant_c)
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tantenna C: 0x%X\n",
|
||||
tx->tx_power.ant_c);
|
||||
} else
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "N/A\n");
|
||||
}
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
|
@ -1571,7 +1531,6 @@ DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
|
|||
DEBUGFS_READ_FILE_OPS(ucode_general_stats);
|
||||
DEBUGFS_READ_FILE_OPS(sensitivity);
|
||||
DEBUGFS_READ_FILE_OPS(chain_noise);
|
||||
DEBUGFS_READ_FILE_OPS(tx_power);
|
||||
DEBUGFS_READ_FILE_OPS(power_save_status);
|
||||
DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
|
||||
DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
|
||||
|
@ -1618,8 +1577,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||
DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(sleep_level_override, dir_data, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
|
||||
if (!priv->cfg->broken_powersave) {
|
||||
DEBUGFS_ADD_FILE(sleep_level_override, dir_data,
|
||||
S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(current_sleep_command, dir_data, S_IRUSR);
|
||||
}
|
||||
DEBUGFS_ADD_FILE(thermal_throttling, dir_data, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
|
||||
|
@ -1627,7 +1589,6 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||
DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(tx_power, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
|
||||
|
@ -1640,18 +1601,21 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
|
||||
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
||||
if (priv->cfg->sensitivity_calib_by_driver)
|
||||
DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
|
||||
if (priv->cfg->chain_noise_calib_by_driver)
|
||||
DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
|
||||
if (priv->cfg->ucode_tracing)
|
||||
DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
|
||||
}
|
||||
DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf, &priv->disable_sens_cal);
|
||||
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
|
||||
&priv->disable_chain_noise_cal);
|
||||
if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
|
||||
((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945))
|
||||
if (priv->cfg->sensitivity_calib_by_driver)
|
||||
DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
|
||||
&priv->disable_sens_cal);
|
||||
if (priv->cfg->chain_noise_calib_by_driver)
|
||||
DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
|
||||
&priv->disable_chain_noise_cal);
|
||||
if (priv->cfg->tx_power_by_driver)
|
||||
DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
|
||||
&priv->disable_tx_power_cal);
|
||||
return 0;
|
||||
|
|
|
@ -57,8 +57,8 @@ extern struct iwl_cfg iwl5100_bgn_cfg;
|
|||
extern struct iwl_cfg iwl5100_abg_cfg;
|
||||
extern struct iwl_cfg iwl5150_agn_cfg;
|
||||
extern struct iwl_cfg iwl5150_abg_cfg;
|
||||
extern struct iwl_cfg iwl6000g2a_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000g2_2agn_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2abg_cfg;
|
||||
extern struct iwl_cfg iwl6000i_2bg_cfg;
|
||||
extern struct iwl_cfg iwl6000_3agn_cfg;
|
||||
|
@ -497,20 +497,38 @@ struct iwl_station_entry {
|
|||
struct iwl_link_quality_cmd *lq;
|
||||
};
|
||||
|
||||
struct iwl_station_priv_common {
|
||||
u8 sta_id;
|
||||
};
|
||||
|
||||
/*
|
||||
* iwl_station_priv: Driver's private station information
|
||||
*
|
||||
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
|
||||
* in the structure for use by driver. This structure is places in that
|
||||
* space.
|
||||
*
|
||||
* The common struct MUST be first because it is shared between
|
||||
* 3945 and agn!
|
||||
*/
|
||||
struct iwl_station_priv {
|
||||
struct iwl_station_priv_common common;
|
||||
struct iwl_lq_sta lq_sta;
|
||||
atomic_t pending_frames;
|
||||
bool client;
|
||||
bool asleep;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_vif_priv - driver's private per-interface information
|
||||
*
|
||||
* When mac80211 allocates a virtual interface, it can allocate
|
||||
* space for us to put data into.
|
||||
*/
|
||||
struct iwl_vif_priv {
|
||||
u8 ibss_bssid_sta_id;
|
||||
};
|
||||
|
||||
/* one for each uCode image (inst/data, boot/init/runtime) */
|
||||
struct fw_desc {
|
||||
void *v_addr; /* access by driver */
|
||||
|
@ -518,7 +536,7 @@ struct fw_desc {
|
|||
u32 len; /* bytes */
|
||||
};
|
||||
|
||||
/* uCode file layout */
|
||||
/* v1/v2 uCode file layout */
|
||||
struct iwl_ucode_header {
|
||||
__le32 ver; /* major/minor/API/serial */
|
||||
union {
|
||||
|
@ -541,7 +559,62 @@ struct iwl_ucode_header {
|
|||
} v2;
|
||||
} u;
|
||||
};
|
||||
#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28)
|
||||
|
||||
/*
|
||||
* new TLV uCode file layout
|
||||
*
|
||||
* The new TLV file format contains TLVs, that each specify
|
||||
* some piece of data. To facilitate "groups", for example
|
||||
* different instruction image with different capabilities,
|
||||
* bundled with the same init image, an alternative mechanism
|
||||
* is provided:
|
||||
* When the alternative field is 0, that means that the item
|
||||
* is always valid. When it is non-zero, then it is only
|
||||
* valid in conjunction with items of the same alternative,
|
||||
* in which case the driver (user) selects one alternative
|
||||
* to use.
|
||||
*/
|
||||
|
||||
enum iwl_ucode_tlv_type {
|
||||
IWL_UCODE_TLV_INVALID = 0, /* unused */
|
||||
IWL_UCODE_TLV_INST = 1,
|
||||
IWL_UCODE_TLV_DATA = 2,
|
||||
IWL_UCODE_TLV_INIT = 3,
|
||||
IWL_UCODE_TLV_INIT_DATA = 4,
|
||||
IWL_UCODE_TLV_BOOT = 5,
|
||||
IWL_UCODE_TLV_PROBE_MAX_LEN = 6, /* a u32 value */
|
||||
};
|
||||
|
||||
struct iwl_ucode_tlv {
|
||||
__le16 type; /* see above */
|
||||
__le16 alternative; /* see comment */
|
||||
__le32 length; /* not including type/length fields */
|
||||
u8 data[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define IWL_TLV_UCODE_MAGIC 0x0a4c5749
|
||||
|
||||
struct iwl_tlv_ucode_header {
|
||||
/*
|
||||
* The TLV style ucode header is distinguished from
|
||||
* the v1/v2 style header by first four bytes being
|
||||
* zero, as such is an invalid combination of
|
||||
* major/minor/API/serial versions.
|
||||
*/
|
||||
__le32 zero;
|
||||
__le32 magic;
|
||||
u8 human_readable[64];
|
||||
__le32 ver; /* major/minor/API/serial */
|
||||
__le32 build;
|
||||
__le64 alternatives; /* bitmask of valid alternatives */
|
||||
/*
|
||||
* The data contained herein has a TLV layout,
|
||||
* see above for the TLV header and types.
|
||||
* Note that each TLV is padded to a length
|
||||
* that is a multiple of 4 for alignment.
|
||||
*/
|
||||
u8 data[0];
|
||||
};
|
||||
|
||||
struct iwl4965_ibss_seq {
|
||||
u8 mac[ETH_ALEN];
|
||||
|
@ -1155,8 +1228,7 @@ struct iwl_priv {
|
|||
#endif
|
||||
|
||||
/* context information */
|
||||
u8 bssid[ETH_ALEN];
|
||||
u16 rts_threshold;
|
||||
u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
|
||||
/*station table variables */
|
||||
|
@ -1189,7 +1261,6 @@ struct iwl_priv {
|
|||
|
||||
/* Last Rx'd beacon timestamp */
|
||||
u64 timestamp;
|
||||
u16 beacon_int;
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
union {
|
||||
|
@ -1242,6 +1313,8 @@ struct iwl_priv {
|
|||
|
||||
struct iwl_rx_phy_res last_phy_res;
|
||||
bool last_phy_res_valid;
|
||||
|
||||
struct completion firmware_loading_complete;
|
||||
} _agn;
|
||||
#endif
|
||||
};
|
||||
|
@ -1249,10 +1322,6 @@ struct iwl_priv {
|
|||
struct iwl_hw_params hw_params;
|
||||
|
||||
u32 inta_mask;
|
||||
/* Current association information needed to configure the
|
||||
* hardware */
|
||||
u16 assoc_id;
|
||||
u16 assoc_capability;
|
||||
|
||||
struct iwl_qos_info qos_data;
|
||||
|
||||
|
|
|
@ -590,9 +590,16 @@ int iwl_eeprom_init(struct iwl_priv *priv)
|
|||
e[addr / 2] = cpu_to_le16(r >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n",
|
||||
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
|
||||
? "OTP" : "EEPROM",
|
||||
iwl_eeprom_query16(priv, EEPROM_VERSION));
|
||||
|
||||
ret = 0;
|
||||
done:
|
||||
priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
|
||||
|
||||
err:
|
||||
if (ret)
|
||||
iwl_eeprom_free(priv);
|
||||
|
|
|
@ -318,10 +318,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
|
|||
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
|
||||
priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
|
||||
|
||||
if (priv->vif)
|
||||
dtimper = priv->hw->conf.ps_dtim_period;
|
||||
else
|
||||
dtimper = 1;
|
||||
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
|
||||
|
||||
if (priv->cfg->broken_powersave)
|
||||
iwl_power_sleep_cam_cmd(priv, &cmd);
|
||||
|
|
|
@ -398,7 +398,7 @@ bool iwl_good_plcp_health(struct iwl_priv *priv,
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_good_plcp_health);
|
||||
|
||||
static void iwl_recover_from_statistics(struct iwl_priv *priv,
|
||||
void iwl_recover_from_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
|
@ -413,9 +413,11 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv,
|
|||
*/
|
||||
IWL_ERR(priv, "low ack count detected, "
|
||||
"restart firmware\n");
|
||||
iwl_force_reset(priv, IWL_FW_RESET);
|
||||
if (!iwl_force_reset(priv, IWL_FW_RESET))
|
||||
return;
|
||||
}
|
||||
} else if (priv->cfg->ops->lib->check_plcp_health) {
|
||||
}
|
||||
if (priv->cfg->ops->lib->check_plcp_health) {
|
||||
if (!priv->cfg->ops->lib->check_plcp_health(
|
||||
priv, pkt)) {
|
||||
/*
|
||||
|
@ -427,6 +429,7 @@ static void iwl_recover_from_statistics(struct iwl_priv *priv,
|
|||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_recover_from_statistics);
|
||||
|
||||
void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
|
|
|
@ -265,7 +265,8 @@ inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
|
|||
EXPORT_SYMBOL(iwl_get_active_dwell_time);
|
||||
|
||||
u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
||||
enum ieee80211_band band)
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
u16 passive = (band == IEEE80211_BAND_2GHZ) ?
|
||||
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
|
||||
|
@ -275,7 +276,7 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
|
|||
/* If we're associated, we clamp the maximum passive
|
||||
* dwell time to be 98% of the beacon interval (minus
|
||||
* 2 * channel tune time) */
|
||||
passive = priv->beacon_int;
|
||||
passive = vif ? vif->bss_conf.beacon_int : 0;
|
||||
if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive)
|
||||
passive = IWL_PASSIVE_DWELL_BASE;
|
||||
passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
|
||||
|
@ -295,7 +296,7 @@ void iwl_init_scan_params(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_init_scan_params);
|
||||
|
||||
static int iwl_scan_initiate(struct iwl_priv *priv)
|
||||
static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
WARN_ON(!mutex_is_locked(&priv->mutex));
|
||||
|
||||
|
@ -307,7 +308,7 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
|
|||
if (WARN_ON(!priv->cfg->ops->utils->request_scan))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
priv->cfg->ops->utils->request_scan(priv);
|
||||
priv->cfg->ops->utils->request_scan(priv, vif);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -348,7 +349,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
|||
priv->scan_band = req->channels[0]->band;
|
||||
priv->scan_request = req;
|
||||
|
||||
ret = iwl_scan_initiate(priv);
|
||||
ret = iwl_scan_initiate(priv, vif);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
|
||||
|
@ -368,7 +369,7 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv)
|
|||
queue_work(priv->workqueue, &priv->start_internal_scan);
|
||||
}
|
||||
|
||||
static void iwl_bg_start_internal_scan(struct work_struct *work)
|
||||
void iwl_bg_start_internal_scan(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv =
|
||||
container_of(work, struct iwl_priv, start_internal_scan);
|
||||
|
@ -399,10 +400,11 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
|
|||
if (WARN_ON(!priv->cfg->ops->utils->request_scan))
|
||||
goto unlock;
|
||||
|
||||
priv->cfg->ops->utils->request_scan(priv);
|
||||
priv->cfg->ops->utils->request_scan(priv, NULL);
|
||||
unlock:
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_bg_start_internal_scan);
|
||||
|
||||
void iwl_bg_scan_check(struct work_struct *data)
|
||||
{
|
||||
|
|
|
@ -35,62 +35,6 @@
|
|||
#include "iwl-core.h"
|
||||
#include "iwl-sta.h"
|
||||
|
||||
u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
|
||||
{
|
||||
int i;
|
||||
int start = 0;
|
||||
int ret = IWL_INVALID_STATION;
|
||||
unsigned long flags;
|
||||
|
||||
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
|
||||
(priv->iw_mode == NL80211_IFTYPE_AP))
|
||||
start = IWL_STA_ID;
|
||||
|
||||
if (is_broadcast_ether_addr(addr))
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
for (i = start; i < priv->hw_params.max_stations; i++)
|
||||
if (priv->stations[i].used &&
|
||||
(!compare_ether_addr(priv->stations[i].sta.sta.addr,
|
||||
addr))) {
|
||||
ret = i;
|
||||
goto out;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
|
||||
addr, priv->num_stations);
|
||||
|
||||
out:
|
||||
/*
|
||||
* It may be possible that more commands interacting with stations
|
||||
* arrive before we completed processing the adding of
|
||||
* station
|
||||
*/
|
||||
if (ret != IWL_INVALID_STATION &&
|
||||
(!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
|
||||
((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
|
||||
(priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
|
||||
IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
|
||||
ret);
|
||||
ret = IWL_INVALID_STATION;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_find_station);
|
||||
|
||||
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
|
||||
{
|
||||
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
|
||||
return IWL_AP_ID;
|
||||
} else {
|
||||
u8 *da = ieee80211_get_DA(hdr);
|
||||
return iwl_find_station(priv, da);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_get_ra_sta_id);
|
||||
|
||||
/* priv->sta_lock must be held */
|
||||
static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
|
||||
{
|
||||
|
@ -340,10 +284,12 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr,
|
|||
station->sta.sta.sta_id = sta_id;
|
||||
station->sta.station_flags = 0;
|
||||
|
||||
/* BCAST station and IBSS stations do not work in HT mode */
|
||||
if (sta_id != priv->hw_params.bcast_sta_id &&
|
||||
priv->iw_mode != NL80211_IFTYPE_ADHOC)
|
||||
iwl_set_ht_add_station(priv, sta_id, ht_info);
|
||||
/*
|
||||
* OK to call unconditionally, since local stations (IBSS BSSID
|
||||
* STA and broadcast STA) pass in a NULL ht_info, and mac80211
|
||||
* doesn't allow HT IBSS.
|
||||
*/
|
||||
iwl_set_ht_add_station(priv, sta_id, ht_info);
|
||||
|
||||
/* 3945 only */
|
||||
rate = (priv->band == IEEE80211_BAND_5GHZ) ?
|
||||
|
@ -418,20 +364,21 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_add_station_common);
|
||||
|
||||
static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)
|
||||
static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv,
|
||||
u8 sta_id)
|
||||
{
|
||||
int i, r;
|
||||
struct iwl_link_quality_cmd link_cmd = {
|
||||
.reserved1 = 0,
|
||||
};
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
u32 rate_flags;
|
||||
int ret = 0;
|
||||
|
||||
link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
|
||||
return NULL;
|
||||
}
|
||||
/* Set up the rate scaling to start at selected rate, fall back
|
||||
* all the way down to 1M in IEEE order, and then spin on 1M */
|
||||
if (is_ap)
|
||||
r = IWL_RATE_54M_INDEX;
|
||||
else if (priv->band == IEEE80211_BAND_5GHZ)
|
||||
if (priv->band == IEEE80211_BAND_5GHZ)
|
||||
r = IWL_RATE_6M_INDEX;
|
||||
else
|
||||
r = IWL_RATE_1M_INDEX;
|
||||
|
@ -444,49 +391,48 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)
|
|||
rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
|
||||
RATE_MCS_ANT_POS;
|
||||
|
||||
link_cmd.rs_table[i].rate_n_flags =
|
||||
link_cmd->rs_table[i].rate_n_flags =
|
||||
iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
|
||||
r = iwl_get_prev_ieee_rate(r);
|
||||
}
|
||||
|
||||
link_cmd.general_params.single_stream_ant_msk =
|
||||
link_cmd->general_params.single_stream_ant_msk =
|
||||
first_antenna(priv->hw_params.valid_tx_ant);
|
||||
|
||||
link_cmd.general_params.dual_stream_ant_msk =
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant &
|
||||
~first_antenna(priv->hw_params.valid_tx_ant);
|
||||
if (!link_cmd.general_params.dual_stream_ant_msk) {
|
||||
link_cmd.general_params.dual_stream_ant_msk = ANT_AB;
|
||||
if (!link_cmd->general_params.dual_stream_ant_msk) {
|
||||
link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
|
||||
} else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
|
||||
link_cmd.general_params.dual_stream_ant_msk =
|
||||
link_cmd->general_params.dual_stream_ant_msk =
|
||||
priv->hw_params.valid_tx_ant;
|
||||
}
|
||||
|
||||
link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
|
||||
link_cmd.agg_params.agg_time_limit =
|
||||
link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
|
||||
link_cmd->agg_params.agg_time_limit =
|
||||
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
|
||||
|
||||
/* Update the rate scaling for control frame Tx to AP */
|
||||
link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
|
||||
link_cmd->sta_id = sta_id;
|
||||
|
||||
ret = iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD,
|
||||
sizeof(link_cmd), &link_cmd);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "REPLY_TX_LINK_QUALITY_CMD failed (%d)\n", ret);
|
||||
return link_cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_add_local_stations - Add stations not requested by mac80211
|
||||
*
|
||||
* This will be either the broadcast station or the bssid station needed by
|
||||
* ad-hoc.
|
||||
* iwl_add_bssid_station - Add the special IBSS BSSID station
|
||||
*
|
||||
* Function sleeps.
|
||||
*/
|
||||
int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs)
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
|
||||
u8 *sta_id_r)
|
||||
{
|
||||
int ret;
|
||||
u8 sta_id;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
|
||||
if (*sta_id_r)
|
||||
*sta_id_r = IWL_INVALID_STATION;
|
||||
|
||||
ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
|
||||
if (ret) {
|
||||
|
@ -494,12 +440,34 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (init_rs)
|
||||
if (sta_id_r)
|
||||
*sta_id_r = sta_id;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].used |= IWL_STA_LOCAL;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
if (init_rs) {
|
||||
/* Set up default rate scaling table in device's station table */
|
||||
iwl_sta_init_lq(priv, addr, false);
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
|
||||
addr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_add_local_station);
|
||||
EXPORT_SYMBOL(iwl_add_bssid_station);
|
||||
|
||||
/**
|
||||
* iwl_sta_ucode_deactivate - deactivate ucode status for a station
|
||||
|
@ -509,7 +477,8 @@ EXPORT_SYMBOL(iwl_add_local_station);
|
|||
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
|
||||
{
|
||||
/* Ucode must be active and driver must be non active */
|
||||
if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE)
|
||||
if ((priv->stations[sta_id].used &
|
||||
(IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != IWL_STA_UCODE_ACTIVE)
|
||||
IWL_ERR(priv, "removed non active STA %u\n", sta_id);
|
||||
|
||||
priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||
|
@ -574,18 +543,16 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
|
|||
/**
|
||||
* iwl_remove_station - Remove driver's knowledge of station.
|
||||
*/
|
||||
static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta)
|
||||
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr)
|
||||
{
|
||||
int sta_id = IWL_INVALID_STATION;
|
||||
int i, ret = -EINVAL;
|
||||
unsigned long flags;
|
||||
bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION;
|
||||
struct iwl_station_entry *station;
|
||||
unsigned long flags;
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Unable to remove station %pM, device not ready.\n",
|
||||
sta->addr);
|
||||
addr);
|
||||
/*
|
||||
* It is typical for stations to be removed when we are
|
||||
* going down. Return success since device will be down
|
||||
|
@ -594,37 +561,30 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta)
|
|||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
if (is_ap)
|
||||
sta_id = IWL_AP_ID;
|
||||
else
|
||||
for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++)
|
||||
if (priv->stations[i].used &&
|
||||
!compare_ether_addr(priv->stations[i].sta.sta.addr,
|
||||
sta->addr)) {
|
||||
sta_id = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(sta_id == IWL_INVALID_STATION))
|
||||
goto out;
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n",
|
||||
sta_id, sta->addr);
|
||||
sta_id, addr);
|
||||
|
||||
if (WARN_ON(sta_id == IWL_INVALID_STATION))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
|
||||
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
|
||||
IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
|
||||
sta->addr);
|
||||
goto out;
|
||||
addr);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
|
||||
IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
|
||||
sta->addr);
|
||||
goto out;
|
||||
addr);
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
|
||||
kfree(priv->stations[sta_id].lq);
|
||||
priv->stations[sta_id].lq = NULL;
|
||||
}
|
||||
|
||||
priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
|
||||
|
||||
|
@ -635,56 +595,35 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta)
|
|||
station = &priv->stations[sta_id];
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
ret = iwl_send_remove_station(priv, station);
|
||||
return ret;
|
||||
out:
|
||||
return iwl_send_remove_station(priv, station);
|
||||
out_err:
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
return ret;
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_remove_station);
|
||||
|
||||
/**
|
||||
* iwl_clear_ucode_stations() - clear entire station table driver and/or ucode
|
||||
* @priv:
|
||||
* @force: If set then the uCode station table needs to be cleared here. If
|
||||
* not set then the uCode station table has already been cleared,
|
||||
* for example after sending it a RXON command without ASSOC bit
|
||||
* set, and we just need to change driver state here.
|
||||
* iwl_clear_ucode_stations - clear ucode station table bits
|
||||
*
|
||||
* This function clears all the bits in the driver indicating
|
||||
* which stations are active in the ucode. Call when something
|
||||
* other than explicit station management would cause this in
|
||||
* the ucode, e.g. unassociated RXON.
|
||||
*/
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force)
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags_spin;
|
||||
bool cleared = false;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver%s\n",
|
||||
force ? " and ucode" : "");
|
||||
|
||||
if (force) {
|
||||
if (!iwl_is_ready(priv)) {
|
||||
/*
|
||||
* If device is not ready at this point the station
|
||||
* table is likely already empty (uCode not ready
|
||||
* to receive station requests) or will soon be
|
||||
* due to interface going down.
|
||||
*/
|
||||
IWL_DEBUG_INFO(priv, "Unable to remove stations from device - device not ready\n");
|
||||
} else {
|
||||
iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL);
|
||||
}
|
||||
}
|
||||
IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags_spin);
|
||||
if (force) {
|
||||
IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n");
|
||||
priv->num_stations = 0;
|
||||
memset(priv->stations, 0, sizeof(priv->stations));
|
||||
} else {
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
|
||||
IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i);
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||
cleared = true;
|
||||
}
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
|
||||
IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i);
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||
cleared = true;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
|
@ -1027,18 +966,23 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
|
|||
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
const u8 *addr, u32 iv32, u16 *phase1key)
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
|
||||
{
|
||||
u8 sta_id = IWL_INVALID_STATION;
|
||||
u8 sta_id;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
|
||||
addr);
|
||||
return;
|
||||
}
|
||||
if (sta) {
|
||||
sta_id = iwl_sta_id(sta);
|
||||
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n",
|
||||
sta->addr);
|
||||
return;
|
||||
}
|
||||
} else
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
|
||||
|
||||
if (iwl_scan_cancel(priv)) {
|
||||
/* cancel scan failed, just live w/ bad key and rely
|
||||
|
@ -1177,6 +1121,39 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv,
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* is_lq_table_valid() - Test one aspect of LQ cmd for validity
|
||||
*
|
||||
* It sometimes happens when a HT rate has been in use and we
|
||||
* loose connectivity with AP then mac80211 will first tell us that the
|
||||
* current channel is not HT anymore before removing the station. In such a
|
||||
* scenario the RXON flags will be updated to indicate we are not
|
||||
* communicating HT anymore, but the LQ command may still contain HT rates.
|
||||
* Test for this to prevent driver from sending LQ command between the time
|
||||
* RXON flags are updated and when LQ command is updated.
|
||||
*/
|
||||
static bool is_lq_table_valid(struct iwl_priv *priv,
|
||||
struct iwl_link_quality_cmd *lq)
|
||||
{
|
||||
int i;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
|
||||
if (ht_conf->is_ht)
|
||||
return true;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
|
||||
priv->active_rxon.channel);
|
||||
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
|
||||
if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"index %d of LQ expects HT channel\n",
|
||||
i);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_send_lq_cmd() - Send link quality command
|
||||
* @init: This command is sent as part of station initialization right
|
||||
|
@ -1206,8 +1183,12 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
|
|||
iwl_dump_lq_cmd(priv, lq);
|
||||
BUG_ON(init && (cmd.flags & CMD_ASYNC));
|
||||
|
||||
ret = iwl_send_cmd(priv, &cmd);
|
||||
if (ret || (cmd.flags & CMD_ASYNC))
|
||||
if (is_lq_table_valid(priv, lq))
|
||||
ret = iwl_send_cmd(priv, &cmd);
|
||||
else
|
||||
ret = -EINVAL;
|
||||
|
||||
if (cmd.flags & CMD_ASYNC)
|
||||
return ret;
|
||||
|
||||
if (init) {
|
||||
|
@ -1217,92 +1198,72 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
|
|||
priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_lq_cmd);
|
||||
|
||||
/**
|
||||
* iwl_add_bcast_station - add broadcast station into station table.
|
||||
*/
|
||||
void iwl_add_bcast_station(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
|
||||
iwl_add_local_station(priv, iwl_bcast_addr, true);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_add_bcast_station);
|
||||
|
||||
/**
|
||||
* iwl3945_add_bcast_station - add broadcast station into station table.
|
||||
*/
|
||||
void iwl3945_add_bcast_station(struct iwl_priv *priv)
|
||||
{
|
||||
IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
|
||||
iwl_add_local_station(priv, iwl_bcast_addr, false);
|
||||
/*
|
||||
* It is assumed that when station is added more initialization
|
||||
* needs to be done, but for 3945 it is not the case and we can
|
||||
* just release station table access right here.
|
||||
*/
|
||||
priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iwl3945_add_bcast_station);
|
||||
|
||||
/**
|
||||
* iwl_get_sta_id - Find station's index within station table
|
||||
* iwl_alloc_bcast_station - add broadcast station into driver's station table.
|
||||
*
|
||||
* If new IBSS station, create new entry in station table
|
||||
* This adds the broadcast station into the driver's station table
|
||||
* and marks it driver active, so that it will be restored to the
|
||||
* device at the next best time.
|
||||
*/
|
||||
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
|
||||
{
|
||||
int sta_id;
|
||||
__le16 fc = hdr->frame_control;
|
||||
struct iwl_link_quality_cmd *link_cmd;
|
||||
unsigned long flags;
|
||||
u8 sta_id;
|
||||
|
||||
/* If this frame is broadcast or management, use broadcast station id */
|
||||
if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Unable to prepare broadcast station\n");
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
switch (priv->iw_mode) {
|
||||
|
||||
/* If we are a client station in a BSS network, use the special
|
||||
* AP station entry (that's the only station we communicate with) */
|
||||
case NL80211_IFTYPE_STATION:
|
||||
/*
|
||||
* If addition of station not complete yet, which means
|
||||
* that rate scaling has not been initialized, then return
|
||||
* the broadcast station.
|
||||
*/
|
||||
if (!(priv->stations[IWL_AP_ID].used & IWL_STA_UCODE_ACTIVE))
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
return IWL_AP_ID;
|
||||
|
||||
/* If we are an AP, then find the station, or use BCAST */
|
||||
case NL80211_IFTYPE_AP:
|
||||
sta_id = iwl_find_station(priv, hdr->addr1);
|
||||
if (sta_id != IWL_INVALID_STATION)
|
||||
return sta_id;
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
|
||||
/* If this frame is going out to an IBSS network, find the station,
|
||||
* or create a new station table entry */
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
sta_id = iwl_find_station(priv, hdr->addr1);
|
||||
if (sta_id != IWL_INVALID_STATION)
|
||||
return sta_id;
|
||||
|
||||
IWL_DEBUG_DROP(priv, "Station %pM not in station map. "
|
||||
"Defaulting to broadcast...\n",
|
||||
hdr->addr1);
|
||||
iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
|
||||
default:
|
||||
IWL_WARN(priv, "Unknown mode of operation: %d\n",
|
||||
priv->iw_mode);
|
||||
return priv->hw_params.bcast_sta_id;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
|
||||
priv->stations[sta_id].used |= IWL_STA_BCAST;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
if (init_lq) {
|
||||
link_cmd = iwl_sta_alloc_lq(priv, sta_id);
|
||||
if (!link_cmd) {
|
||||
IWL_ERR(priv,
|
||||
"Unable to initialize rate scaling for bcast station.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
priv->stations[sta_id].lq = link_cmd;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_get_sta_id);
|
||||
EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
|
||||
|
||||
void iwl_dealloc_bcast_station(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
for (i = 0; i < priv->hw_params.max_stations; i++) {
|
||||
if (!(priv->stations[i].used & IWL_STA_BCAST))
|
||||
continue;
|
||||
|
||||
priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
|
||||
priv->num_stations--;
|
||||
BUG_ON(priv->num_stations < 0);
|
||||
kfree(priv->stations[i].lq);
|
||||
priv->stations[i].lq = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
|
||||
|
||||
/**
|
||||
* iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
|
||||
|
@ -1322,13 +1283,13 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
|
||||
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv,
|
||||
const u8 *addr, int tid, u16 ssn)
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION)
|
||||
return -ENXIO;
|
||||
|
||||
|
@ -1341,16 +1302,17 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv,
|
|||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
|
||||
CMD_ASYNC);
|
||||
CMD_ASYNC);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_sta_rx_agg_start);
|
||||
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid)
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid)
|
||||
{
|
||||
unsigned long flags;
|
||||
int sta_id;
|
||||
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
|
||||
return -ENXIO;
|
||||
|
@ -1402,14 +1364,16 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
|
|||
EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
|
||||
|
||||
int iwl_mac_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
|
||||
int ret;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
|
||||
sta->addr);
|
||||
ret = iwl_remove_station(priv, sta);
|
||||
ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error removing station %pM\n",
|
||||
sta->addr);
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#ifndef __iwl_sta_h__
|
||||
#define __iwl_sta_h__
|
||||
|
||||
#include "iwl-dev.h"
|
||||
|
||||
#define HW_KEY_DYNAMIC 0
|
||||
#define HW_KEY_DEFAULT 1
|
||||
|
||||
|
@ -36,14 +38,11 @@
|
|||
#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
|
||||
#define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of
|
||||
being activated */
|
||||
#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211;
|
||||
(this is for the IBSS BSSID stations) */
|
||||
#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
|
||||
|
||||
|
||||
/**
|
||||
* iwl_find_station - Find station id for a given BSSID
|
||||
* @bssid: MAC address of station ID to find
|
||||
*/
|
||||
u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid);
|
||||
|
||||
int iwl_remove_default_wep_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *key);
|
||||
int iwl_set_default_wep_key(struct iwl_priv *priv,
|
||||
|
@ -55,28 +54,57 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
|
|||
struct ieee80211_key_conf *key, u8 sta_id);
|
||||
void iwl_update_tkip_key(struct iwl_priv *priv,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
const u8 *addr, u32 iv32, u16 *phase1key);
|
||||
struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
|
||||
|
||||
void iwl_add_bcast_station(struct iwl_priv *priv);
|
||||
void iwl3945_add_bcast_station(struct iwl_priv *priv);
|
||||
void iwl_restore_stations(struct iwl_priv *priv);
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force);
|
||||
void iwl_clear_ucode_stations(struct iwl_priv *priv);
|
||||
int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
|
||||
void iwl_dealloc_bcast_station(struct iwl_priv *priv);
|
||||
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
|
||||
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
|
||||
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
|
||||
int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *sta, u8 flags);
|
||||
int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs);
|
||||
int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
|
||||
u8 *sta_id_r);
|
||||
int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
|
||||
bool is_ap,
|
||||
struct ieee80211_sta_ht_cap *ht_info,
|
||||
u8 *sta_id_r);
|
||||
int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
|
||||
const u8 *addr);
|
||||
int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv,
|
||||
const u8 *addr, int tid, u16 ssn);
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid);
|
||||
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn);
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid);
|
||||
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
|
||||
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
|
||||
|
||||
/**
|
||||
* iwl_clear_driver_stations - clear knowledge of all stations from driver
|
||||
* @priv: iwl priv struct
|
||||
*
|
||||
* This is called during iwl_down() to make sure that in the case
|
||||
* we're coming there from a hardware restart mac80211 will be
|
||||
* able to reconfigure stations -- if we're getting there in the
|
||||
* normal down flow then the stations will already be cleared.
|
||||
*/
|
||||
static inline void iwl_clear_driver_stations(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->sta_lock, flags);
|
||||
memset(priv->stations, 0, sizeof(priv->stations));
|
||||
priv->num_stations = 0;
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
}
|
||||
|
||||
static inline int iwl_sta_id(struct ieee80211_sta *sta)
|
||||
{
|
||||
if (WARN_ON(!sta))
|
||||
return IWL_INVALID_STATION;
|
||||
|
||||
return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
|
||||
}
|
||||
#endif /* __iwl_sta_h__ */
|
||||
|
|
|
@ -509,11 +509,11 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
hdr_len = ieee80211_hdrlen(fc);
|
||||
|
||||
/* Find (or create) index into station table for destination station */
|
||||
if (info->flags & IEEE80211_TX_CTL_INJECTED)
|
||||
/* Find index into station table for destination station */
|
||||
if (!info->control.sta)
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
else
|
||||
sta_id = iwl_get_sta_id(priv, hdr);
|
||||
sta_id = iwl_sta_id(info->control.sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
|
||||
hdr->addr1);
|
||||
|
@ -1847,7 +1847,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
|
|||
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
|
||||
enum ieee80211_band band,
|
||||
u8 is_active, u8 n_probes,
|
||||
struct iwl3945_scan_channel *scan_ch)
|
||||
struct iwl3945_scan_channel *scan_ch,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_channel *chan;
|
||||
const struct ieee80211_supported_band *sband;
|
||||
|
@ -1861,7 +1862,7 @@ static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
|
|||
return 0;
|
||||
|
||||
active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band);
|
||||
passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
|
||||
|
||||
if (passive_dwell <= active_dwell)
|
||||
passive_dwell = active_dwell + 1;
|
||||
|
@ -2109,6 +2110,28 @@ static void iwl3945_nic_start(struct iwl_priv *priv)
|
|||
iwl_write32(priv, CSR_RESET, 0);
|
||||
}
|
||||
|
||||
#define IWL3945_UCODE_GET(item) \
|
||||
static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
|
||||
{ \
|
||||
return le32_to_cpu(ucode->u.v1.item); \
|
||||
}
|
||||
|
||||
static u32 iwl3945_ucode_get_header_size(u32 api_ver)
|
||||
{
|
||||
return 24;
|
||||
}
|
||||
|
||||
static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
|
||||
{
|
||||
return (u8 *) ucode->u.v1.data;
|
||||
}
|
||||
|
||||
IWL3945_UCODE_GET(inst_size);
|
||||
IWL3945_UCODE_GET(data_size);
|
||||
IWL3945_UCODE_GET(init_size);
|
||||
IWL3945_UCODE_GET(init_data_size);
|
||||
IWL3945_UCODE_GET(boot_size);
|
||||
|
||||
/**
|
||||
* iwl3945_read_ucode - Read uCode images from disk file.
|
||||
*
|
||||
|
@ -2157,7 +2180,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
|
|||
goto error;
|
||||
|
||||
/* Make sure that we got at least our header! */
|
||||
if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) {
|
||||
if (ucode_raw->size < iwl3945_ucode_get_header_size(1)) {
|
||||
IWL_ERR(priv, "File size way too small!\n");
|
||||
ret = -EINVAL;
|
||||
goto err_release;
|
||||
|
@ -2168,13 +2191,12 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
|
|||
|
||||
priv->ucode_ver = le32_to_cpu(ucode->ver);
|
||||
api_ver = IWL_UCODE_API(priv->ucode_ver);
|
||||
inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver);
|
||||
data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver);
|
||||
init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver);
|
||||
init_data_size =
|
||||
priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver);
|
||||
boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver);
|
||||
src = priv->cfg->ops->ucode->get_data(ucode, api_ver);
|
||||
inst_size = iwl3945_ucode_get_inst_size(ucode);
|
||||
data_size = iwl3945_ucode_get_data_size(ucode);
|
||||
init_size = iwl3945_ucode_get_init_size(ucode);
|
||||
init_data_size = iwl3945_ucode_get_init_data_size(ucode);
|
||||
boot_size = iwl3945_ucode_get_boot_size(ucode);
|
||||
src = iwl3945_ucode_get_data(ucode);
|
||||
|
||||
/* api_ver should match the api version forming part of the
|
||||
* firmware filename ... but we don't check for that and only rely
|
||||
|
@ -2223,7 +2245,7 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
|
|||
|
||||
|
||||
/* Verify size of file vs. image size info in file's header */
|
||||
if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) +
|
||||
if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) +
|
||||
inst_size + data_size + init_size +
|
||||
init_data_size + boot_size) {
|
||||
|
||||
|
@ -2522,7 +2544,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
|
|||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
} else {
|
||||
/* Initialize our rx_config data */
|
||||
iwl_connection_init_rx_config(priv, priv->iw_mode);
|
||||
iwl_connection_init_rx_config(priv, NULL);
|
||||
}
|
||||
|
||||
/* Configure Bluetooth device coexistence support */
|
||||
|
@ -2561,7 +2583,9 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
|||
set_bit(STATUS_EXIT_PENDING, &priv->status);
|
||||
|
||||
/* Station information will now be cleared in device */
|
||||
iwl_clear_ucode_stations(priv, true);
|
||||
iwl_clear_ucode_stations(priv);
|
||||
iwl_dealloc_bcast_station(priv);
|
||||
iwl_clear_driver_stations(priv);
|
||||
|
||||
/* Unblock any waiting calls */
|
||||
wake_up_interruptible_all(&priv->wait_command_queue);
|
||||
|
@ -2642,6 +2666,10 @@ static int __iwl3945_up(struct iwl_priv *priv)
|
|||
{
|
||||
int rc, i;
|
||||
|
||||
rc = iwl_alloc_bcast_station(priv, false);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
|
||||
IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
|
||||
return -EIO;
|
||||
|
@ -2790,7 +2818,7 @@ static void iwl3945_rfkill_poll(struct work_struct *data)
|
|||
|
||||
}
|
||||
|
||||
void iwl3945_request_scan(struct iwl_priv *priv)
|
||||
void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_SCAN_CMD,
|
||||
|
@ -2871,7 +2899,7 @@ void iwl3945_request_scan(struct iwl_priv *priv)
|
|||
IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
interval = priv->beacon_int;
|
||||
interval = vif ? vif->bss_conf.beacon_int : 0;
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
scan->suspend_time = 0;
|
||||
|
@ -2966,7 +2994,7 @@ void iwl3945_request_scan(struct iwl_priv *priv)
|
|||
|
||||
scan->channel_count =
|
||||
iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
|
||||
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
|
||||
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
|
||||
|
||||
if (scan->channel_count == 0) {
|
||||
IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
|
||||
|
@ -3039,26 +3067,25 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
|
|||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
void iwl3945_post_associate(struct iwl_priv *priv)
|
||||
void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
int rc = 0;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_AP) {
|
||||
if (!vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
|
||||
priv->assoc_id, priv->active_rxon.bssid_addr);
|
||||
vif->bss_conf.aid, priv->active_rxon.bssid_addr);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (!priv->vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
@ -3067,7 +3094,7 @@ void iwl3945_post_associate(struct iwl_priv *priv)
|
|||
iwlcore_commit_rxon(priv);
|
||||
|
||||
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
|
||||
iwl_setup_rxon_timing(priv);
|
||||
iwl_setup_rxon_timing(priv, vif);
|
||||
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
|
||||
sizeof(priv->rxon_timing), &priv->rxon_timing);
|
||||
if (rc)
|
||||
|
@ -3076,51 +3103,38 @@ void iwl3945_post_associate(struct iwl_priv *priv)
|
|||
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
priv->assoc_id, priv->beacon_int);
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv);
|
||||
|
||||
switch (priv->iw_mode) {
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
|
||||
break;
|
||||
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
|
||||
priv->assoc_id = 1;
|
||||
iwl_add_local_station(priv, priv->bssid, false);
|
||||
iwl3945_sync_sta(priv, IWL_STA_ID,
|
||||
(priv->band == IEEE80211_BAND_5GHZ) ?
|
||||
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
|
||||
CMD_ASYNC);
|
||||
iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
|
||||
|
||||
iwl3945_send_beacon_cmd(priv);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
IWL_ERR(priv, "%s Should not be called in %d mode\n",
|
||||
__func__, priv->iw_mode);
|
||||
IWL_ERR(priv, "%s Should not be called in %d mode\n",
|
||||
__func__, vif->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -3244,7 +3258,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
void iwl3945_config_ap(struct iwl_priv *priv)
|
||||
void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
|
@ -3260,7 +3274,7 @@ void iwl3945_config_ap(struct iwl_priv *priv)
|
|||
|
||||
/* RXON Timing */
|
||||
memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
|
||||
iwl_setup_rxon_timing(priv);
|
||||
iwl_setup_rxon_timing(priv, vif);
|
||||
rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
|
||||
sizeof(priv->rxon_timing),
|
||||
&priv->rxon_timing);
|
||||
|
@ -3268,9 +3282,10 @@ void iwl3945_config_ap(struct iwl_priv *priv)
|
|||
IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
/* FIXME: what should be the assoc_id for AP? */
|
||||
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
|
||||
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
priv->staging_rxon.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_PREAMBLE)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
|
@ -3278,22 +3293,21 @@ void iwl3945_config_ap(struct iwl_priv *priv)
|
|||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (priv->assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
if (vif->bss_conf.assoc_capability &
|
||||
WLAN_CAPABILITY_SHORT_SLOT_TIME)
|
||||
priv->staging_rxon.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
if (priv->iw_mode == NL80211_IFTYPE_ADHOC)
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
priv->staging_rxon.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* restore RXON assoc */
|
||||
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv);
|
||||
iwl_add_local_station(priv, iwl_bcast_addr, false);
|
||||
}
|
||||
iwl3945_send_beacon_cmd(priv);
|
||||
|
||||
|
@ -3308,7 +3322,6 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
const u8 *addr;
|
||||
int ret = 0;
|
||||
u8 sta_id = IWL_INVALID_STATION;
|
||||
u8 static_key;
|
||||
|
@ -3320,15 +3333,19 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
addr = sta ? sta->addr : iwl_bcast_addr;
|
||||
static_key = !iwl_is_associated(priv);
|
||||
|
||||
if (!static_key) {
|
||||
sta_id = iwl_find_station(priv, addr);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n",
|
||||
addr);
|
||||
return -EINVAL;
|
||||
if (!sta) {
|
||||
sta_id = priv->hw_params.bcast_sta_id;
|
||||
} else {
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id == IWL_INVALID_STATION) {
|
||||
IWL_DEBUG_MAC80211(priv,
|
||||
"leave - %pM not in station map.\n",
|
||||
sta->addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3365,10 +3382,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
|
|||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
|
||||
int ret;
|
||||
bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION;
|
||||
bool is_ap = vif->type == NL80211_IFTYPE_STATION;
|
||||
u8 sta_id;
|
||||
|
||||
sta_priv->common.sta_id = IWL_INVALID_STATION;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
|
||||
sta->addr);
|
||||
|
||||
|
@ -3381,16 +3401,14 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
|
|||
return ret;
|
||||
}
|
||||
|
||||
sta_priv->common.sta_id = sta_id;
|
||||
|
||||
/* Initialize rate scaling */
|
||||
IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
|
||||
sta->addr);
|
||||
iwl3945_rs_rate_init(priv, sta, sta_id);
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
/*****************************************************************************
|
||||
*
|
||||
|
@ -3739,6 +3757,7 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
|
|||
INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
|
||||
INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
|
||||
INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
|
||||
INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
|
||||
INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
|
||||
|
||||
iwl3945_hw_setup_deferred_work(priv);
|
||||
|
@ -3761,6 +3780,7 @@ static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
|
|||
cancel_delayed_work_sync(&priv->init_alive_start);
|
||||
cancel_delayed_work(&priv->scan_check);
|
||||
cancel_delayed_work(&priv->alive_start);
|
||||
cancel_work_sync(&priv->start_internal_scan);
|
||||
cancel_work_sync(&priv->beacon_update);
|
||||
if (priv->cfg->ops->lib->recover_from_tx_stall)
|
||||
del_timer_sync(&priv->monitor_recover);
|
||||
|
@ -3863,6 +3883,8 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define IWL3945_MAX_PROBE_REQUEST 200
|
||||
|
||||
static int iwl3945_setup_mac(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
|
@ -3870,6 +3892,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
|
|||
|
||||
hw->rate_control_algorithm = "iwl-3945-rs";
|
||||
hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
|
||||
hw->vif_data_size = sizeof(struct iwl_vif_priv);
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
|
@ -3888,7 +3911,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
|
|||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
|
||||
/* we create the 802.11 header and a zero-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
|
||||
hw->wiphy->max_scan_ie_len = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
|
||||
|
||||
/* Default value; 4 EDCA QOS priorities */
|
||||
hw->queues = 4;
|
||||
|
|
|
@ -1007,15 +1007,15 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
|
||||
__le32 *txd = skbdesc->desc;
|
||||
__le32 *txd = entry_priv->desc;
|
||||
u32 word;
|
||||
|
||||
/*
|
||||
* Start writing the descriptor words.
|
||||
*/
|
||||
rt2x00_desc_read(entry_priv->desc, 1, &word);
|
||||
rt2x00_desc_read(txd, 1, &word);
|
||||
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
|
||||
rt2x00_desc_write(entry_priv->desc, 1, word);
|
||||
rt2x00_desc_write(txd, 1, word);
|
||||
|
||||
rt2x00_desc_read(txd, 2, &word);
|
||||
rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
|
||||
|
@ -1040,6 +1040,11 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
|
||||
rt2x00_desc_write(txd, 4, word);
|
||||
|
||||
/*
|
||||
* Writing TXD word 0 must the last to prevent a race condition with
|
||||
* the device, whereby the device may take hold of the TXD before we
|
||||
* finished updating it.
|
||||
*/
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
|
||||
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
|
||||
|
@ -1055,6 +1060,12 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
|
||||
test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
|
||||
/*
|
||||
* Register descriptor details in skb frame descriptor.
|
||||
*/
|
||||
skbdesc->desc = txd;
|
||||
skbdesc->desc_len = TXD_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1077,15 +1088,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
|
|||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
|
||||
/*
|
||||
* Replace rt2x00lib allocated descriptor with the
|
||||
* pointer to the _real_ hardware descriptor.
|
||||
* After that, map the beacon to DMA and update the
|
||||
* descriptor.
|
||||
*/
|
||||
memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len);
|
||||
skbdesc->desc = entry_priv->desc;
|
||||
|
||||
rt2x00queue_map_txskb(rt2x00dev, entry->skb);
|
||||
|
||||
rt2x00_desc_read(entry_priv->desc, 1, &word);
|
||||
|
|
|
@ -1165,15 +1165,15 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
|
||||
__le32 *txd = skbdesc->desc;
|
||||
__le32 *txd = entry_priv->desc;
|
||||
u32 word;
|
||||
|
||||
/*
|
||||
* Start writing the descriptor words.
|
||||
*/
|
||||
rt2x00_desc_read(entry_priv->desc, 1, &word);
|
||||
rt2x00_desc_read(txd, 1, &word);
|
||||
rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
|
||||
rt2x00_desc_write(entry_priv->desc, 1, word);
|
||||
rt2x00_desc_write(txd, 1, word);
|
||||
|
||||
rt2x00_desc_read(txd, 2, &word);
|
||||
rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
|
||||
|
@ -1194,6 +1194,11 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
|
||||
rt2x00_desc_write(txd, 10, word);
|
||||
|
||||
/*
|
||||
* Writing TXD word 0 must the last to prevent a race condition with
|
||||
* the device, whereby the device may take hold of the TXD before we
|
||||
* finished updating it.
|
||||
*/
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
|
||||
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
|
||||
|
@ -1212,6 +1217,12 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
|
||||
/*
|
||||
* Register descriptor details in skb frame descriptor.
|
||||
*/
|
||||
skbdesc->desc = txd;
|
||||
skbdesc->desc_len = TXD_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1234,15 +1245,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
|
|||
rt2x00_set_field32(®, CSR14_BEACON_GEN, 0);
|
||||
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
|
||||
|
||||
/*
|
||||
* Replace rt2x00lib allocated descriptor with the
|
||||
* pointer to the _real_ hardware descriptor.
|
||||
* After that, map the beacon to DMA and update the
|
||||
* descriptor.
|
||||
*/
|
||||
memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len);
|
||||
skbdesc->desc = entry_priv->desc;
|
||||
|
||||
rt2x00queue_map_txskb(rt2x00dev, entry->skb);
|
||||
|
||||
rt2x00_desc_read(entry_priv->desc, 1, &word);
|
||||
|
|
|
@ -1034,12 +1034,30 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
__le32 *txd = skbdesc->desc;
|
||||
__le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE);
|
||||
u32 word;
|
||||
|
||||
/*
|
||||
* Start writing the descriptor words.
|
||||
*/
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
|
||||
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
|
||||
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_ACK,
|
||||
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
|
||||
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_OFDM,
|
||||
(txdesc->rate_mode == RATE_MODE_OFDM));
|
||||
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
|
||||
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
|
||||
rt2x00_desc_read(txd, 1, &word);
|
||||
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
|
||||
rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
|
||||
|
@ -1059,23 +1077,11 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
_rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
|
||||
}
|
||||
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
|
||||
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
|
||||
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_ACK,
|
||||
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
|
||||
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_OFDM,
|
||||
(txdesc->rate_mode == RATE_MODE_OFDM));
|
||||
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
|
||||
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
/*
|
||||
* Register descriptor details in skb frame descriptor.
|
||||
*/
|
||||
skbdesc->desc = txd;
|
||||
skbdesc->desc_len = TXD_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1089,18 +1095,10 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
|
|||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
|
||||
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
|
||||
int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint);
|
||||
int length;
|
||||
u16 reg, reg0;
|
||||
|
||||
/*
|
||||
* Add the descriptor in front of the skb.
|
||||
*/
|
||||
skb_push(entry->skb, entry->queue->desc_size);
|
||||
memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
|
||||
skbdesc->desc = entry->skb->data;
|
||||
|
||||
/*
|
||||
* Disable beaconing while we are reloading the beacon data,
|
||||
* otherwise we might be sending out invalid data.
|
||||
|
@ -1109,6 +1107,11 @@ static void rt2500usb_write_beacon(struct queue_entry *entry,
|
|||
rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0);
|
||||
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
|
||||
|
||||
/*
|
||||
* Take the descriptor in front of the skb into account.
|
||||
*/
|
||||
skb_push(entry->skb, TXD_DESC_SIZE);
|
||||
|
||||
/*
|
||||
* USB devices cannot blindly pass the skb->len as the
|
||||
* length of the data to usb_fill_bulk_urb. Pass the skb
|
||||
|
|
|
@ -633,7 +633,8 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
__le32 *txd = skbdesc->desc;
|
||||
struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
|
||||
__le32 *txd = entry_priv->desc;
|
||||
u32 word;
|
||||
|
||||
/*
|
||||
|
@ -657,15 +658,14 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
!test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W1_BURST,
|
||||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W1_SD_LEN0,
|
||||
rt2x00dev->ops->extra_tx_headroom);
|
||||
rt2x00_set_field32(&word, TXD_W1_SD_LEN0, TXWI_DESC_SIZE);
|
||||
rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
|
||||
rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
|
||||
rt2x00_desc_write(txd, 1, word);
|
||||
|
||||
rt2x00_desc_read(txd, 2, &word);
|
||||
rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
|
||||
skbdesc->skb_dma + rt2x00dev->ops->extra_tx_headroom);
|
||||
skbdesc->skb_dma + TXWI_DESC_SIZE);
|
||||
rt2x00_desc_write(txd, 2, word);
|
||||
|
||||
rt2x00_desc_read(txd, 3, &word);
|
||||
|
@ -673,6 +673,12 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W3_QSEL, 2);
|
||||
rt2x00_desc_write(txd, 3, word);
|
||||
|
||||
/*
|
||||
* Register descriptor details in skb frame descriptor.
|
||||
*/
|
||||
skbdesc->desc = txd;
|
||||
skbdesc->desc_len = TXD_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -400,7 +400,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
__le32 *txi = skbdesc->desc;
|
||||
__le32 *txi = (__le32 *)(skb->data - TXWI_DESC_SIZE - TXINFO_DESC_SIZE);
|
||||
u32 word;
|
||||
|
||||
/*
|
||||
|
@ -422,6 +422,12 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST,
|
||||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_desc_write(txi, 0, word);
|
||||
|
||||
/*
|
||||
* Register descriptor details in skb frame descriptor.
|
||||
*/
|
||||
skbdesc->desc = txi;
|
||||
skbdesc->desc_len = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -156,10 +156,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
|||
enum rt2x00_dump_type type, struct sk_buff *skb)
|
||||
{
|
||||
struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
|
||||
struct skb_frame_desc *desc = get_skb_frame_desc(skb);
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
struct sk_buff *skbcopy;
|
||||
struct rt2x00dump_hdr *dump_hdr;
|
||||
struct timeval timestamp;
|
||||
u32 data_len;
|
||||
|
||||
do_gettimeofday(×tamp);
|
||||
|
||||
|
@ -171,7 +172,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
|||
return;
|
||||
}
|
||||
|
||||
skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + skb->len,
|
||||
data_len = skb->len;
|
||||
if (skbdesc->flags & SKBDESC_DESC_IN_SKB)
|
||||
data_len -= skbdesc->desc_len;
|
||||
|
||||
skbcopy = alloc_skb(sizeof(*dump_hdr) + skbdesc->desc_len + data_len,
|
||||
GFP_ATOMIC);
|
||||
if (!skbcopy) {
|
||||
DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
|
||||
|
@ -181,18 +186,20 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
|||
dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
|
||||
dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
|
||||
dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
|
||||
dump_hdr->desc_length = cpu_to_le32(desc->desc_len);
|
||||
dump_hdr->data_length = cpu_to_le32(skb->len);
|
||||
dump_hdr->desc_length = cpu_to_le32(skbdesc->desc_len);
|
||||
dump_hdr->data_length = cpu_to_le32(data_len);
|
||||
dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
|
||||
dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
|
||||
dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
|
||||
dump_hdr->type = cpu_to_le16(type);
|
||||
dump_hdr->queue_index = desc->entry->queue->qid;
|
||||
dump_hdr->entry_index = desc->entry->entry_idx;
|
||||
dump_hdr->queue_index = skbdesc->entry->queue->qid;
|
||||
dump_hdr->entry_index = skbdesc->entry->entry_idx;
|
||||
dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
|
||||
dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
|
||||
|
||||
memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len);
|
||||
if (!(skbdesc->flags & SKBDESC_DESC_IN_SKB))
|
||||
memcpy(skb_put(skbcopy, skbdesc->desc_len), skbdesc->desc,
|
||||
skbdesc->desc_len);
|
||||
memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len);
|
||||
|
||||
skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
|
||||
|
|
|
@ -62,11 +62,14 @@
|
|||
* the tx event which has either succeeded or failed. A frame
|
||||
* with this type should also have been reported with as a
|
||||
* %DUMP_FRAME_TX frame.
|
||||
* @DUMP_FRAME_BEACON: This beacon frame is queued for transmission to the
|
||||
* hardware.
|
||||
*/
|
||||
enum rt2x00_dump_type {
|
||||
DUMP_FRAME_RXDONE = 1,
|
||||
DUMP_FRAME_TX = 2,
|
||||
DUMP_FRAME_TXDONE = 3,
|
||||
DUMP_FRAME_BEACON = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,8 +67,6 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
|
||||
/*
|
||||
* This should not happen, we already checked the entry
|
||||
|
@ -83,13 +81,6 @@ int rt2x00pci_write_tx_data(struct queue_entry *entry,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in skb descriptor
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(entry->skb);
|
||||
skbdesc->desc = entry_priv->desc;
|
||||
skbdesc->desc_len = entry->queue->desc_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
|
||||
|
|
|
@ -421,6 +421,7 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
|
|||
{
|
||||
struct data_queue *queue = entry->queue;
|
||||
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
|
||||
enum rt2x00_dump_type dump_type;
|
||||
|
||||
rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc);
|
||||
|
||||
|
@ -428,7 +429,9 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
|
|||
* All processing on the frame has been completed, this means
|
||||
* it is now ready to be dumped to userspace through debugfs.
|
||||
*/
|
||||
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb);
|
||||
dump_type = (txdesc->queue == QID_BEACON) ?
|
||||
DUMP_FRAME_BEACON : DUMP_FRAME_TX;
|
||||
rt2x00debug_dump_frame(rt2x00dev, dump_type, entry->skb);
|
||||
}
|
||||
|
||||
static void rt2x00queue_kick_tx_queue(struct queue_entry *entry,
|
||||
|
@ -553,7 +556,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
|
|||
struct rt2x00_intf *intf = vif_to_intf(vif);
|
||||
struct skb_frame_desc *skbdesc;
|
||||
struct txentry_desc txdesc;
|
||||
__le32 desc[16];
|
||||
|
||||
if (unlikely(!intf->beacon))
|
||||
return -ENOBUFS;
|
||||
|
@ -585,20 +587,11 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
|
|||
*/
|
||||
rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
|
||||
|
||||
/*
|
||||
* For the descriptor we use a local array from where the
|
||||
* driver can move it to the correct location required for
|
||||
* the hardware.
|
||||
*/
|
||||
memset(desc, 0, sizeof(desc));
|
||||
|
||||
/*
|
||||
* Fill in skb descriptor
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(intf->beacon->skb);
|
||||
memset(skbdesc, 0, sizeof(*skbdesc));
|
||||
skbdesc->desc = desc;
|
||||
skbdesc->desc_len = intf->beacon->queue->desc_size;
|
||||
skbdesc->entry = intf->beacon;
|
||||
|
||||
/*
|
||||
|
|
|
@ -94,12 +94,15 @@ enum data_queue_qid {
|
|||
* mac80211 but was stripped for processing by the driver.
|
||||
* @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211,
|
||||
* don't try to pass it back.
|
||||
* @SKBDESC_DESC_IN_SKB: The descriptor is at the start of the
|
||||
* skb, instead of in the desc field.
|
||||
*/
|
||||
enum skb_frame_desc_flags {
|
||||
SKBDESC_DMA_MAPPED_RX = 1 << 0,
|
||||
SKBDESC_DMA_MAPPED_TX = 1 << 1,
|
||||
SKBDESC_IV_STRIPPED = 1 << 2,
|
||||
SKBDESC_NOT_MAC80211 = 1 << 3,
|
||||
SKBDESC_DESC_IN_SKB = 1 << 4,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -222,7 +222,6 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry,
|
|||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
|
||||
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
|
||||
struct skb_frame_desc *skbdesc;
|
||||
u32 length;
|
||||
|
||||
/*
|
||||
|
@ -231,13 +230,6 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry,
|
|||
skb_push(entry->skb, entry->queue->desc_size);
|
||||
memset(entry->skb->data, 0, entry->queue->desc_size);
|
||||
|
||||
/*
|
||||
* Fill in skb descriptor
|
||||
*/
|
||||
skbdesc = get_skb_frame_desc(entry->skb);
|
||||
skbdesc->desc = entry->skb->data;
|
||||
skbdesc->desc_len = entry->queue->desc_size;
|
||||
|
||||
/*
|
||||
* USB devices cannot blindly pass the skb->len as the
|
||||
* length of the data to usb_fill_bulk_urb. Pass the skb
|
||||
|
|
|
@ -1764,7 +1764,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
__le32 *txd = skbdesc->desc;
|
||||
struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data;
|
||||
__le32 *txd = entry_priv->desc;
|
||||
u32 word;
|
||||
|
||||
/*
|
||||
|
@ -1802,18 +1803,23 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
|
||||
rt2x00_desc_write(txd, 5, word);
|
||||
|
||||
rt2x00_desc_read(txd, 6, &word);
|
||||
rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
|
||||
skbdesc->skb_dma);
|
||||
rt2x00_desc_write(txd, 6, word);
|
||||
if (txdesc->queue != QID_BEACON) {
|
||||
rt2x00_desc_read(txd, 6, &word);
|
||||
rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
|
||||
skbdesc->skb_dma);
|
||||
rt2x00_desc_write(txd, 6, word);
|
||||
|
||||
if (skbdesc->desc_len > TXINFO_SIZE) {
|
||||
rt2x00_desc_read(txd, 11, &word);
|
||||
rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0,
|
||||
txdesc->length);
|
||||
rt2x00_desc_write(txd, 11, word);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writing TXD word 0 must the last to prevent a race condition with
|
||||
* the device, whereby the device may take hold of the TXD before we
|
||||
* finished updating it.
|
||||
*/
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1);
|
||||
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
|
||||
|
@ -1838,6 +1844,13 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
|
||||
/*
|
||||
* Register descriptor details in skb frame descriptor.
|
||||
*/
|
||||
skbdesc->desc = txd;
|
||||
skbdesc->desc_len =
|
||||
(txdesc->queue == QID_BEACON) ? TXINFO_SIZE : TXD_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1847,7 +1860,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
|
||||
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
|
||||
unsigned int beacon_base;
|
||||
u32 reg;
|
||||
|
||||
|
@ -1863,11 +1876,9 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
|
|||
* Write entire beacon with descriptor to register.
|
||||
*/
|
||||
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
|
||||
rt2x00pci_register_multiwrite(rt2x00dev,
|
||||
beacon_base,
|
||||
skbdesc->desc, skbdesc->desc_len);
|
||||
rt2x00pci_register_multiwrite(rt2x00dev,
|
||||
beacon_base + skbdesc->desc_len,
|
||||
rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
|
||||
entry_priv->desc, TXINFO_SIZE);
|
||||
rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
|
||||
entry->skb->data, entry->skb->len);
|
||||
|
||||
/*
|
||||
|
|
|
@ -1441,12 +1441,38 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
|
||||
__le32 *txd = skbdesc->desc;
|
||||
__le32 *txd = (__le32 *)(skb->data - TXD_DESC_SIZE);
|
||||
u32 word;
|
||||
|
||||
/*
|
||||
* Start writing the descriptor words.
|
||||
*/
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
rt2x00_set_field32(&word, TXD_W0_BURST,
|
||||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
|
||||
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
|
||||
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_ACK,
|
||||
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
|
||||
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_OFDM,
|
||||
(txdesc->rate_mode == RATE_MODE_OFDM));
|
||||
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_TKIP_MIC,
|
||||
test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
|
||||
test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W0_BURST2,
|
||||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
|
||||
rt2x00_desc_read(txd, 1, &word);
|
||||
rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue);
|
||||
rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs);
|
||||
|
@ -1475,31 +1501,11 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
|
|||
rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1);
|
||||
rt2x00_desc_write(txd, 5, word);
|
||||
|
||||
rt2x00_desc_read(txd, 0, &word);
|
||||
rt2x00_set_field32(&word, TXD_W0_BURST,
|
||||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_VALID, 1);
|
||||
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
|
||||
test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_ACK,
|
||||
test_bit(ENTRY_TXD_ACK, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
|
||||
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_OFDM,
|
||||
(txdesc->rate_mode == RATE_MODE_OFDM));
|
||||
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_TKIP_MIC,
|
||||
test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_TABLE,
|
||||
test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx);
|
||||
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
|
||||
rt2x00_set_field32(&word, TXD_W0_BURST2,
|
||||
test_bit(ENTRY_TXD_BURST, &txdesc->flags));
|
||||
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher);
|
||||
rt2x00_desc_write(txd, 0, word);
|
||||
/*
|
||||
* Register descriptor details in skb frame descriptor.
|
||||
*/
|
||||
skbdesc->desc = txd;
|
||||
skbdesc->desc_len = TXD_DESC_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1509,17 +1515,9 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
|
|||
struct txentry_desc *txdesc)
|
||||
{
|
||||
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
|
||||
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
|
||||
unsigned int beacon_base;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* Add the descriptor in front of the skb.
|
||||
*/
|
||||
skb_push(entry->skb, entry->queue->desc_size);
|
||||
memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
|
||||
skbdesc->desc = entry->skb->data;
|
||||
|
||||
/*
|
||||
* Disable beaconing while we are reloading the beacon data,
|
||||
* otherwise we might be sending out invalid data.
|
||||
|
@ -1528,6 +1526,11 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
|
|||
rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0);
|
||||
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
|
||||
|
||||
/*
|
||||
* Take the descriptor in front of the skb into account.
|
||||
*/
|
||||
skb_push(entry->skb, TXD_DESC_SIZE);
|
||||
|
||||
/*
|
||||
* Write entire beacon with descriptor to register.
|
||||
*/
|
||||
|
|
|
@ -467,6 +467,7 @@ static void wl1271_irq_work(struct work_struct *work)
|
|||
intr = le32_to_cpu(wl->fw_status->intr);
|
||||
if (!intr) {
|
||||
wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
|
||||
spin_lock_irqsave(&wl->wl_lock, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -852,7 +853,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
|
|||
if (wl == wl_temp)
|
||||
break;
|
||||
}
|
||||
if (wl == NULL)
|
||||
if (wl != wl_temp)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
/* Get the interface IP address for the device. "ifa" will become
|
||||
|
@ -1558,8 +1559,6 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
|||
default:
|
||||
wl1271_error("Unsupported key cmd 0x%x", cmd);
|
||||
ret = -EOPNOTSUPP;
|
||||
goto out_sleep;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -711,6 +711,28 @@ struct ieee80211_conf {
|
|||
enum ieee80211_smps_mode smps_mode;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_channel_switch - holds the channel switch data
|
||||
*
|
||||
* The information provided in this structure is required for channel switch
|
||||
* operation.
|
||||
*
|
||||
* @timestamp: value in microseconds of the 64-bit Time Synchronization
|
||||
* Function (TSF) timer when the frame containing the channel switch
|
||||
* announcement was received. This is simply the rx.mactime parameter
|
||||
* the driver passed into mac80211.
|
||||
* @block_tx: Indicates whether transmission must be blocked before the
|
||||
* scheduled channel switch, as indicated by the AP.
|
||||
* @channel: the new channel to switch to
|
||||
* @count: the number of TBTT's until the channel switch event
|
||||
*/
|
||||
struct ieee80211_channel_switch {
|
||||
u64 timestamp;
|
||||
bool block_tx;
|
||||
struct ieee80211_channel *channel;
|
||||
u8 count;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ieee80211_vif - per-interface data
|
||||
*
|
||||
|
@ -1631,6 +1653,11 @@ enum ieee80211_ampdu_mlme_action {
|
|||
* @flush: Flush all pending frames from the hardware queue, making sure
|
||||
* that the hardware queues are empty. If the parameter @drop is set
|
||||
* to %true, pending frames may be dropped. The callback can sleep.
|
||||
*
|
||||
* @channel_switch: Drivers that need (or want) to offload the channel
|
||||
* switch operation for CSAs received from the AP may implement this
|
||||
* callback. They must then call ieee80211_chswitch_done() to indicate
|
||||
* completion of the channel switch.
|
||||
*/
|
||||
struct ieee80211_ops {
|
||||
int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
|
@ -1694,6 +1721,8 @@ struct ieee80211_ops {
|
|||
int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
|
||||
#endif
|
||||
void (*flush)(struct ieee80211_hw *hw, bool drop);
|
||||
void (*channel_switch)(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2444,6 +2473,16 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
|
|||
enum nl80211_cqm_rssi_threshold_event rssi_event,
|
||||
gfp_t gfp);
|
||||
|
||||
/**
|
||||
* ieee80211_chswitch_done - Complete channel switch process
|
||||
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
||||
* @success: make the channel switch successful or not
|
||||
*
|
||||
* Complete the channel switch post-process: set the new operational channel
|
||||
* and wake up the suspended queues.
|
||||
*/
|
||||
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success);
|
||||
|
||||
/* Rate control API */
|
||||
|
||||
/**
|
||||
|
|
|
@ -371,4 +371,15 @@ static inline void drv_flush(struct ieee80211_local *local, bool drop)
|
|||
if (local->ops->flush)
|
||||
local->ops->flush(&local->hw, drop);
|
||||
}
|
||||
|
||||
static inline void drv_channel_switch(struct ieee80211_local *local,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
local->ops->channel_switch(&local->hw, ch_switch);
|
||||
|
||||
trace_drv_channel_switch(local, ch_switch);
|
||||
}
|
||||
|
||||
#endif /* __MAC80211_DRIVER_OPS */
|
||||
|
|
|
@ -774,6 +774,34 @@ TRACE_EVENT(drv_flush,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(drv_channel_switch,
|
||||
TP_PROTO(struct ieee80211_local *local,
|
||||
struct ieee80211_channel_switch *ch_switch),
|
||||
|
||||
TP_ARGS(local, ch_switch),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
LOCAL_ENTRY
|
||||
__field(u64, timestamp)
|
||||
__field(bool, block_tx)
|
||||
__field(u16, freq)
|
||||
__field(u8, count)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
LOCAL_ASSIGN;
|
||||
__entry->timestamp = ch_switch->timestamp;
|
||||
__entry->block_tx = ch_switch->block_tx;
|
||||
__entry->freq = ch_switch->channel->center_freq;
|
||||
__entry->count = ch_switch->count;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
LOCAL_PR_FMT " new freq:%u count:%d",
|
||||
LOCAL_PR_ARG, __entry->freq, __entry->count
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
* Tracing for API calls that drivers call.
|
||||
*/
|
||||
|
@ -992,6 +1020,27 @@ TRACE_EVENT(api_sta_block_awake,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(api_chswitch_done,
|
||||
TP_PROTO(struct ieee80211_sub_if_data *sdata, bool success),
|
||||
|
||||
TP_ARGS(sdata, success),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
VIF_ENTRY
|
||||
__field(bool, success)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
VIF_ASSIGN;
|
||||
__entry->success = success;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
VIF_PR_FMT " success=%d",
|
||||
VIF_PR_ARG, __entry->success
|
||||
)
|
||||
);
|
||||
|
||||
/*
|
||||
* Tracing for internal functions
|
||||
* (which may also be called in response to driver calls)
|
||||
|
|
|
@ -998,7 +998,8 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
|
|||
unsigned long data, void *dummy);
|
||||
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_channel_sw_ie *sw_elem,
|
||||
struct ieee80211_bss *bss);
|
||||
struct ieee80211_bss *bss,
|
||||
u64 timestamp);
|
||||
void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
|
|
|
@ -342,7 +342,11 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
|||
goto out;
|
||||
|
||||
sdata->local->oper_channel = sdata->local->csa_channel;
|
||||
ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
if (!sdata->local->ops->channel_switch) {
|
||||
/* call "hw_config" only if doing sw channel switch */
|
||||
ieee80211_hw_config(sdata->local,
|
||||
IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
}
|
||||
|
||||
/* XXX: shouldn't really modify cfg80211-owned data! */
|
||||
ifmgd->associated->channel = sdata->local->oper_channel;
|
||||
|
@ -354,6 +358,29 @@ static void ieee80211_chswitch_work(struct work_struct *work)
|
|||
mutex_unlock(&ifmgd->mtx);
|
||||
}
|
||||
|
||||
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
struct ieee80211_if_managed *ifmgd;
|
||||
|
||||
sdata = vif_to_sdata(vif);
|
||||
ifmgd = &sdata->u.mgd;
|
||||
|
||||
trace_api_chswitch_done(sdata, success);
|
||||
if (!success) {
|
||||
/*
|
||||
* If the channel switch was not successful, stay
|
||||
* around on the old channel. We currently lack
|
||||
* good handling of this situation, possibly we
|
||||
* should just drop the association.
|
||||
*/
|
||||
sdata->local->csa_channel = sdata->local->oper_channel;
|
||||
}
|
||||
|
||||
ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_chswitch_done);
|
||||
|
||||
static void ieee80211_chswitch_timer(unsigned long data)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata =
|
||||
|
@ -370,7 +397,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
|
|||
|
||||
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_channel_sw_ie *sw_elem,
|
||||
struct ieee80211_bss *bss)
|
||||
struct ieee80211_bss *bss,
|
||||
u64 timestamp)
|
||||
{
|
||||
struct cfg80211_bss *cbss =
|
||||
container_of((void *)bss, struct cfg80211_bss, priv);
|
||||
|
@ -398,10 +426,29 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
sdata->local->csa_channel = new_ch;
|
||||
|
||||
if (sdata->local->ops->channel_switch) {
|
||||
/* use driver's channel switch callback */
|
||||
struct ieee80211_channel_switch ch_switch;
|
||||
memset(&ch_switch, 0, sizeof(ch_switch));
|
||||
ch_switch.timestamp = timestamp;
|
||||
if (sw_elem->mode) {
|
||||
ch_switch.block_tx = true;
|
||||
ieee80211_stop_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
}
|
||||
ch_switch.channel = new_ch;
|
||||
ch_switch.count = sw_elem->count;
|
||||
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
|
||||
drv_channel_switch(sdata->local, &ch_switch);
|
||||
return;
|
||||
}
|
||||
|
||||
/* channel switch handled in software */
|
||||
if (sw_elem->count <= 1) {
|
||||
ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work);
|
||||
} else {
|
||||
ieee80211_stop_queues_by_reason(&sdata->local->hw,
|
||||
if (sw_elem->mode)
|
||||
ieee80211_stop_queues_by_reason(&sdata->local->hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||
ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
|
||||
mod_timer(&ifmgd->chswitch_timer,
|
||||
|
@ -1317,7 +1364,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|||
ETH_ALEN) == 0)) {
|
||||
struct ieee80211_channel_sw_ie *sw_elem =
|
||||
(struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
|
||||
ieee80211_sta_process_chanswitch(sdata, sw_elem, bss);
|
||||
ieee80211_sta_process_chanswitch(sdata, sw_elem,
|
||||
bss, rx_status->mactime);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1649,7 +1697,8 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|||
|
||||
ieee80211_sta_process_chanswitch(sdata,
|
||||
&mgmt->u.action.u.chan_switch.sw_elem,
|
||||
(void *)ifmgd->associated->priv);
|
||||
(void *)ifmgd->associated->priv,
|
||||
rx_status->mactime);
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&ifmgd->mtx);
|
||||
|
|
|
@ -1253,6 +1253,12 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
|
|||
if (skb_linearize(rx->skb))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
/*
|
||||
* skb_linearize() might change the skb->data and
|
||||
* previously cached variables (in this case, hdr) need to
|
||||
* be refreshed with the new data.
|
||||
*/
|
||||
hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
|
||||
|
||||
if (frag == 0) {
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define IEEE80211_MAX_PROBE_TRIES 5
|
||||
|
||||
enum work_action {
|
||||
WORK_ACT_MISMATCH,
|
||||
WORK_ACT_NONE,
|
||||
WORK_ACT_TIMEOUT,
|
||||
WORK_ACT_DONE,
|
||||
|
@ -585,7 +586,7 @@ ieee80211_rx_mgmt_auth(struct ieee80211_work *wk,
|
|||
u16 auth_alg, auth_transaction, status_code;
|
||||
|
||||
if (wk->type != IEEE80211_WORK_AUTH)
|
||||
return WORK_ACT_NONE;
|
||||
return WORK_ACT_MISMATCH;
|
||||
|
||||
if (len < 24 + 6)
|
||||
return WORK_ACT_NONE;
|
||||
|
@ -636,6 +637,9 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk,
|
|||
struct ieee802_11_elems elems;
|
||||
u8 *pos;
|
||||
|
||||
if (wk->type != IEEE80211_WORK_ASSOC)
|
||||
return WORK_ACT_MISMATCH;
|
||||
|
||||
/*
|
||||
* AssocResp and ReassocResp have identical structure, so process both
|
||||
* of them in this function.
|
||||
|
@ -691,6 +695,12 @@ ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk,
|
|||
|
||||
ASSERT_WORK_MTX(local);
|
||||
|
||||
if (wk->type != IEEE80211_WORK_DIRECT_PROBE)
|
||||
return WORK_ACT_MISMATCH;
|
||||
|
||||
if (len < 24 + 12)
|
||||
return WORK_ACT_NONE;
|
||||
|
||||
baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
|
||||
if (baselen > len)
|
||||
return WORK_ACT_NONE;
|
||||
|
@ -705,7 +715,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
|||
struct ieee80211_rx_status *rx_status;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct ieee80211_work *wk;
|
||||
enum work_action rma = WORK_ACT_NONE;
|
||||
enum work_action rma;
|
||||
u16 fc;
|
||||
|
||||
rx_status = (struct ieee80211_rx_status *) skb->cb;
|
||||
|
@ -752,7 +762,17 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
|||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
rma = WORK_ACT_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've either received an unexpected frame, or we have
|
||||
* multiple work items and need to match the frame to the
|
||||
* right one.
|
||||
*/
|
||||
if (rma == WORK_ACT_MISMATCH)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We've processed this frame for that work, so it can't
|
||||
* belong to another work struct.
|
||||
|
@ -762,6 +782,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
|
|||
}
|
||||
|
||||
switch (rma) {
|
||||
case WORK_ACT_MISMATCH:
|
||||
/* ignore this unmatched frame */
|
||||
break;
|
||||
case WORK_ACT_NONE:
|
||||
break;
|
||||
case WORK_ACT_DONE:
|
||||
|
|
Loading…
Reference in a new issue