From 0bacdf303f72a3ed34252934114bc04e79222687 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Wed, 30 Jul 2008 13:18:59 +0300 Subject: [PATCH 01/78] ath5k: Update register list * Update list of registers * Use updated register macros inside hw.c, initvals.c and debug.c Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/debug.c | 2 +- drivers/net/wireless/ath5k/hw.c | 43 +- drivers/net/wireless/ath5k/initvals.c | 4 +- drivers/net/wireless/ath5k/reg.h | 936 +++++++++++++++++++------- 4 files changed, 721 insertions(+), 264 deletions(-) diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 41d5fa34b544..6fa6c8e04ff0 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -129,7 +129,7 @@ static struct reg regs[] = { REG_STRUCT_INIT(AR5K_CPC1), REG_STRUCT_INIT(AR5K_CPC2), REG_STRUCT_INIT(AR5K_CPC3), - REG_STRUCT_INIT(AR5K_CPCORN), + REG_STRUCT_INIT(AR5K_CPCOVF), REG_STRUCT_INIT(AR5K_RESET_CTL), REG_STRUCT_INIT(AR5K_SLEEP_CTL), REG_STRUCT_INIT(AR5K_INTPEND), diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 7ca87a557312..42ef41ed5d18 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -843,27 +843,26 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, * Write some more initial register settings */ if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11)); + ath5k_hw_reg_write(ah, 0x0002a002, 0x982c); if (channel->hw_value == CHANNEL_G) if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413) ath5k_hw_reg_write(ah, 0x00f80d80, - AR5K_PHY(83)); + 0x994c); else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424) ath5k_hw_reg_write(ah, 0x00380140, - AR5K_PHY(83)); + 0x994c); else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425) ath5k_hw_reg_write(ah, 0x00fc0ec0, - AR5K_PHY(83)); + 0x994c); else /* 2425 */ ath5k_hw_reg_write(ah, 0x00fc0fc0, - AR5K_PHY(83)); + 0x994c); else - ath5k_hw_reg_write(ah, 0x00000000, - AR5K_PHY(83)); + ath5k_hw_reg_write(ah, 0x00000000, 0x994c); ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); - ath5k_hw_reg_write(ah, 0x0000000f, 0x8060); + ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); ath5k_hw_reg_write(ah, 0x00000000, 0xa254); ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL); } @@ -935,7 +934,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, return ret; /* Set antenna mode */ - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x44), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_ANT_CTL, ah->ah_antenna[ee_mode][0], 0xfffffc06); /* @@ -965,15 +964,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), - AR5K_PHY(0x5a)); + AR5K_PHY_NFTHRES); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x11), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_SETTLING, (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80, 0xffffc07f); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x12), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN, (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000, 0xfffc0fff); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x14), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE, (ee->ee_adc_desired_size[ee_mode] & 0x00ff) | ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00), 0xffff0000); @@ -982,13 +981,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | - (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY(0x0d)); + (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x0a), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_RF_CTL3, ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x19), + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_NF, (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff); - AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x49), 4, 0xffffff01); + AR5K_REG_MASKED_BITS(ah, AR5K_PHY_OFDM_SELFCORR, 4, 0xffffff01); AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | @@ -3363,11 +3362,13 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) ath5k_hw_reg_write(ah, ah->ah_turbo ? AR5K_INIT_PROTO_TIME_CNTRL_TURBO : AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); - /* Set PHY register 0x9844 (??) */ + /* Set AR5K_PHY_SETTLING */ ath5k_hw_reg_write(ah, ah->ah_turbo ? - (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 : - (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C, - AR5K_PHY(17)); + (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) + | 0x38 : + (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) + | 0x1C, + AR5K_PHY_SETTLING); /* Set Frame Control Register */ ath5k_hw_reg_write(ah, ah->ah_turbo ? (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index 04c84e9da89d..2806b21bf90b 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -489,7 +489,7 @@ static const struct ath5k_ini ar5212_ini[] = { { AR5K_QUEUE_TXDP(9), 0x00000000 }, { AR5K_DCU_FP, 0x00000000 }, { AR5K_DCU_TXP, 0x00000000 }, - { AR5K_DCU_TX_FILTER, 0x00000000 }, + { AR5K_DCU_TX_FILTER_0_BASE, 0x00000000 }, /* Unknown table */ { 0x1078, 0x00000000 }, { 0x10b8, 0x00000000 }, @@ -679,7 +679,7 @@ static const struct ath5k_ini ar5212_ini[] = { { AR5K_PHY(645), 0x00106c10 }, { AR5K_PHY(646), 0x009c4060 }, { AR5K_PHY(647), 0x1483800a }, - /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */ + /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413/2425 */ { AR5K_PHY(648), 0x01831061 }, { AR5K_PHY(649), 0x00000400 }, /*{ AR5K_PHY(650), 0x000001b5 },*/ diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 30629b3e37c2..7562bf173d3e 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -53,7 +53,7 @@ #define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */ #define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */ #define AR5K_CR_RXD 0x00000020 /* RX Disable */ -#define AR5K_CR_SWI 0x00000040 +#define AR5K_CR_SWI 0x00000040 /* Software Interrupt */ /* * RX Descriptor Pointer register @@ -65,19 +65,19 @@ */ #define AR5K_CFG 0x0014 /* Register Address */ #define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */ -#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer (?) */ +#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer */ #define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */ -#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer (?) */ -#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register values (?) */ -#define AR5K_CFG_ADHOC 0x00000020 /* [5211+] */ +#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */ +#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */ +#define AR5K_CFG_ADHOC 0x00000020 /* AP/Adhoc indication [5211+] */ #define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */ #define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */ -#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (?) */ +#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */ #define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */ #define AR5K_CFG_TXCNT_S 11 #define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */ #define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */ -#define AR5K_CFG_PCI_THRES 0x00060000 /* [5211+] */ +#define AR5K_CFG_PCI_THRES 0x00060000 /* PCI Master req q threshold [5211+] */ #define AR5K_CFG_PCI_THRES_S 17 /* @@ -162,35 +162,40 @@ /* * Transmit configuration register */ -#define AR5K_TXCFG 0x0030 /* Register Address */ -#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size */ -#define AR5K_TXCFG_SDMAMR_S 0 -#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */ -#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */ -#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */ -#define AR5K_TXCFG_TXFULL_S 4 -#define AR5K_TXCFG_TXFULL_0B 0x00000000 -#define AR5K_TXCFG_TXFULL_64B 0x00000010 -#define AR5K_TXCFG_TXFULL_128B 0x00000020 -#define AR5K_TXCFG_TXFULL_192B 0x00000030 -#define AR5K_TXCFG_TXFULL_256B 0x00000040 -#define AR5K_TXCFG_TXCONT_EN 0x00000080 -#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */ -#define AR5K_TXCFG_JUMBO_TXE 0x00000400 /* Enable jumbo frames transmition (?) [5211+] */ -#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */ -#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */ -#define AR5K_TXCFG_RDY_DIS 0x00004000 /* [5211+] */ +#define AR5K_TXCFG 0x0030 /* Register Address */ +#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size (read) */ +#define AR5K_TXCFG_SDMAMR_S 0 +#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */ +#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */ +#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */ +#define AR5K_TXCFG_TXFULL_S 4 +#define AR5K_TXCFG_TXFULL_0B 0x00000000 +#define AR5K_TXCFG_TXFULL_64B 0x00000010 +#define AR5K_TXCFG_TXFULL_128B 0x00000020 +#define AR5K_TXCFG_TXFULL_192B 0x00000030 +#define AR5K_TXCFG_TXFULL_256B 0x00000040 +#define AR5K_TXCFG_TXCONT_EN 0x00000080 +#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */ +#define AR5K_TXCFG_JUMBO_DESC_EN 0x00000400 /* Enable jumbo tx descriptors [5211+] */ +#define AR5K_TXCFG_ADHOC_BCN_ATIM 0x00000800 /* Adhoc Beacon ATIM Policy */ +#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS 0x00001000 /* Disable ATIM window defer [5211+] */ +#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */ +#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */ +#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */ +#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */ +#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */ /* * Receive configuration register */ #define AR5K_RXCFG 0x0034 /* Register Address */ -#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size */ +#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size (write) */ #define AR5K_RXCFG_SDMAMW_S 0 -#define AR5K_RXCFG_DEF_ANTENNA 0x00000008 /* Default antenna */ -#define AR5K_RXCFG_ZLFDMA 0x00000010 /* Zero-length DMA */ -#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo frames reception (?) [5211+] */ -#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames (?) [5211+] */ +#define AR5K_RXCFG_ZLFDMA 0x00000008 /* Enable Zero-length frame DMA */ +#define AR5K_RXCFG_DEF_ANTENNA 0x00000010 /* Default antenna (?) */ +#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo rx descriptors [5211+] */ +#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames [5211+] */ +#define AR5K_RXCFG_SLE_ENTRY 0x00000080 /* Sleep entry policy */ /* * Receive jumbo descriptor last address register @@ -202,35 +207,35 @@ * MIB control register */ #define AR5K_MIBC 0x0040 /* Register Address */ -#define AR5K_MIBC_COW 0x00000001 -#define AR5K_MIBC_FMC 0x00000002 /* Freeze Mib Counters (?) */ -#define AR5K_MIBC_CMC 0x00000004 /* Clean Mib Counters (?) */ -#define AR5K_MIBC_MCS 0x00000008 +#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ +#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ +#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ +#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ /* * Timeout prescale register */ #define AR5K_TOPS 0x0044 -#define AR5K_TOPS_M 0x0000ffff /* [5211+] (?) */ +#define AR5K_TOPS_M 0x0000ffff /* * Receive timeout register (no frame received) */ #define AR5K_RXNOFRM 0x0048 -#define AR5K_RXNOFRM_M 0x000003ff /* [5211+] (?) */ +#define AR5K_RXNOFRM_M 0x000003ff /* * Transmit timeout register (no frame sent) */ #define AR5K_TXNOFRM 0x004c -#define AR5K_TXNOFRM_M 0x000003ff /* [5211+] (?) */ -#define AR5K_TXNOFRM_QCU 0x000ffc00 /* [5211+] (?) */ +#define AR5K_TXNOFRM_M 0x000003ff +#define AR5K_TXNOFRM_QCU 0x000ffc00 /* * Receive frame gap timeout register */ #define AR5K_RPGTO 0x0050 -#define AR5K_RPGTO_M 0x000003ff /* [5211+] (?) */ +#define AR5K_RPGTO_M 0x000003ff /* * Receive frame count limit register @@ -241,6 +246,7 @@ /* * Misc settings register + * (reserved0-3) */ #define AR5K_MISC 0x0058 /* Register Address */ #define AR5K_MISC_DMA_OBS_M 0x000001e0 @@ -256,6 +262,7 @@ /* * QCU/DCU clock gating register (5311) + * (reserved4-5) */ #define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */ #define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */ @@ -284,18 +291,18 @@ #define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ #define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ #define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ -#define AR5K_ISR_SWI 0x00002000 /* Software interrupt (?) */ +#define AR5K_ISR_SWI 0x00002000 /* Software interrupt */ #define AR5K_ISR_RXPHY 0x00004000 /* PHY error */ -#define AR5K_ISR_RXKCM 0x00008000 +#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */ #define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ #define AR5K_ISR_BRSSI 0x00020000 #define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ #define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ #define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ -#define AR5K_ISR_MCABT 0x00100000 /* [5210] */ -#define AR5K_ISR_RXCHIRP 0x00200000 /* [5212+] */ -#define AR5K_ISR_SSERR 0x00200000 /* [5210] */ -#define AR5K_ISR_DPERR 0x00400000 /* [5210] */ +#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ +#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ +#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ +#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */ #define AR5K_ISR_TIM 0x00800000 /* [5210] */ #define AR5K_ISR_BCNMISC 0x00800000 /* [5212+] */ #define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill)*/ @@ -320,14 +327,14 @@ #define AR5K_SISR2 0x008c /* Register Address [5211+] */ #define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ -#define AR5K_SISR2_MCABT 0x00100000 -#define AR5K_SISR2_SSERR 0x00200000 -#define AR5K_SISR2_DPERR 0x00400000 +#define AR5K_SISR2_MCABT 0x00100000 /* Master Cycle Abort */ +#define AR5K_SISR2_SSERR 0x00200000 /* Signaled System Error */ +#define AR5K_SISR2_DPERR 0x00400000 /* Det par Error (?) */ #define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ -#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* [5212+] */ -#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* [5212+] */ -#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* [5212+] */ +#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ +#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ +#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ #define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ #define AR5K_SISR3 0x0090 /* Register Address [5211+] */ @@ -368,18 +375,18 @@ #define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/ #define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/ #define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/ -#define AR5K_IMR_SWI 0x00002000 +#define AR5K_IMR_SWI 0x00002000 /* Software interrupt */ #define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/ -#define AR5K_IMR_RXKCM 0x00008000 +#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */ #define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/ #define AR5K_IMR_BRSSI 0x00020000 #define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/ #define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ #define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */ -#define AR5K_IMR_MCABT 0x00100000 /* [5210] */ -#define AR5K_IMR_RXCHIRP 0x00200000 /* [5212+]*/ -#define AR5K_IMR_SSERR 0x00200000 /* [5210] */ -#define AR5K_IMR_DPERR 0x00400000 /* [5210] */ +#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ +#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/ +#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */ +#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */ #define AR5K_IMR_TIM 0x00800000 /* [5211+] */ #define AR5K_IMR_BCNMISC 0x00800000 /* [5212+] */ #define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/ @@ -405,14 +412,14 @@ #define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ #define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ #define AR5K_SIMR2_QCU_TXURN_S 0 -#define AR5K_SIMR2_MCABT 0x00100000 -#define AR5K_SIMR2_SSERR 0x00200000 -#define AR5K_SIMR2_DPERR 0x00400000 +#define AR5K_SIMR2_MCABT 0x00100000 /* Master Cycle Abort */ +#define AR5K_SIMR2_SSERR 0x00200000 /* Signaled System Error */ +#define AR5K_SIMR2_DPERR 0x00400000 /* Det par Error (?) */ #define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ #define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ -#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* [5212+] */ -#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* [5212+] */ -#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* [5212+] */ +#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ +#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ +#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ #define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */ #define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */ @@ -425,23 +432,69 @@ #define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */ #define AR5K_SIMR4_QTRIG_S 0 +/* + * DMA Debug registers 0-7 + * 0xe0 - 0xfc + */ /* * Decompression mask registers [5212+] */ -#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (?)*/ -#define AR5K_DCM_DATA 0x0404 /*Decompression mask data (?)*/ +#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (index) */ +#define AR5K_DCM_DATA 0x0404 /*Decompression mask data */ + +/* + * Wake On Wireless pattern control register [5212+] + */ +#define AR5K_WOW_PCFG 0x0410 /* Register Address */ +#define AR5K_WOW_PCFG_PAT_MATCH_EN 0x00000001 /* Pattern match enable */ +#define AR5K_WOW_PCFG_LONG_FRAME_POL 0x00000002 /* Long frame policy */ +#define AR5K_WOW_PCFG_WOBMISS 0x00000004 /* Wake on bea(con) miss (?) */ +#define AR5K_WOW_PCFG_PAT_0_EN 0x00000100 /* Enable pattern 0 */ +#define AR5K_WOW_PCFG_PAT_1_EN 0x00000200 /* Enable pattern 1 */ +#define AR5K_WOW_PCFG_PAT_2_EN 0x00000400 /* Enable pattern 2 */ +#define AR5K_WOW_PCFG_PAT_3_EN 0x00000800 /* Enable pattern 3 */ +#define AR5K_WOW_PCFG_PAT_4_EN 0x00001000 /* Enable pattern 4 */ +#define AR5K_WOW_PCFG_PAT_5_EN 0x00002000 /* Enable pattern 5 */ + +/* + * Wake On Wireless pattern index register (?) [5212+] + */ +#define AR5K_WOW_PAT_IDX 0x0414 + +/* + * Wake On Wireless pattern data register [5212+] + */ +#define AR5K_WOW_PAT_DATA 0x0418 /* Register Address */ +#define AR5K_WOW_PAT_DATA_0_3_V 0x00000001 /* Pattern 0, 3 value */ +#define AR5K_WOW_PAT_DATA_1_4_V 0x00000100 /* Pattern 1, 4 value */ +#define AR5K_WOW_PAT_DATA_2_5_V 0x00010000 /* Pattern 2, 5 value */ +#define AR5K_WOW_PAT_DATA_0_3_M 0x01000000 /* Pattern 0, 3 mask */ +#define AR5K_WOW_PAT_DATA_1_4_M 0x04000000 /* Pattern 1, 4 mask */ +#define AR5K_WOW_PAT_DATA_2_5_M 0x10000000 /* Pattern 2, 5 mask */ /* * Decompression configuration registers [5212+] */ -#define AR5K_DCCFG 0x0420 +#define AR5K_DCCFG 0x0420 /* Register Address */ +#define AR5K_DCCFG_GLOBAL_EN 0x00000001 /* Enable decompression on all queues */ +#define AR5K_DCCFG_BYPASS_EN 0x00000002 /* Bypass decompression */ +#define AR5K_DCCFG_BCAST_EN 0x00000004 /* Enable decompression for bcast frames */ +#define AR5K_DCCFG_MCAST_EN 0x00000008 /* Enable decompression for mcast frames */ /* * Compression configuration registers [5212+] */ -#define AR5K_CCFG 0x0600 -#define AR5K_CCFG_CUP 0x0604 +#define AR5K_CCFG 0x0600 /* Register Address */ +#define AR5K_CCFG_WINDOW_SIZE 0x00000007 /* Compression window size */ +#define AR5K_CCFG_CPC_EN 0x00000008 /* Enable performance counters */ + +#define AR5K_CCFG_CCU 0x0604 /* Register Address */ +#define AR5K_CCFG_CCU_CUP_EN 0x00000001 /* CCU Catchup enable */ +#define AR5K_CCFG_CCU_CREDIT 0x00000002 /* CCU Credit (field) */ +#define AR5K_CCFG_CCU_CD_THRES 0x00000080 /* CCU Cyc(lic?) debt threshold (field) */ +#define AR5K_CCFG_CCU_CUP_LCNT 0x00010000 /* CCU Catchup lit(?) count */ +#define AR5K_CCFG_CCU_INIT 0x00100200 /* Initial value during reset */ /* * Compression performance counter registers [5212+] @@ -450,7 +503,7 @@ #define AR5K_CPC1 0x0614 /* Compression performance counter 1*/ #define AR5K_CPC2 0x0618 /* Compression performance counter 2 */ #define AR5K_CPC3 0x061c /* Compression performance counter 3 */ -#define AR5K_CPCORN 0x0620 /* Compression performance overrun (?) */ +#define AR5K_CPCOVF 0x0620 /* Compression performance overflow */ /* @@ -466,8 +519,6 @@ * set/clear, which contain status for all queues (we shift by 1 for each * queue). To access these registers easily we define some macros here * that are used inside HAL. For more infos check out *_tx_queue functs. - * - * TODO: Boundary checking on macros (here?) */ /* @@ -513,7 +564,6 @@ #define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */ #define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */ #define AR5K_QCU_RDYTIMECFG_INTVAL_S 0 -#define AR5K_QCU_RDYTIMECFG_DURATION 0x00ffffff /* Ready time duration mask */ #define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */ #define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q) @@ -534,19 +584,20 @@ */ #define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */ #define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */ -#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */ -#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */ -#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated (?) */ -#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* Time gated (?) */ +#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */ +#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */ +#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated (?) */ +#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* Time gated (?) */ #define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated (?) */ #define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */ #define AR5K_QCU_MISC_CBREXP 0x00000020 /* CBR expired (normal queue) */ #define AR5K_QCU_MISC_CBREXP_BCN 0x00000040 /* CBR expired (beacon queue) */ -#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Beacons enabled */ -#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR threshold enabled (?) */ -#define AR5K_QCU_MISC_TXE 0x00000200 /* TXE reset when RDYTIME enalbed (?) */ -#define AR5K_QCU_MISC_CBR 0x00000400 /* CBR threshold reset (?) */ -#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU reset (?) */ +#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */ +#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR threshold enabled */ +#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME enalbed */ +#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */ +#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */ +#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */ #define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q) @@ -555,7 +606,7 @@ */ #define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */ #define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */ -#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter (?) */ +#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter */ #define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q) /* @@ -569,9 +620,11 @@ */ #define AR5K_QCU_CBB_SELECT 0x0b00 #define AR5K_QCU_CBB_ADDR 0x0b04 +#define AR5K_QCU_CBB_ADDR_S 9 /* * QCU compression buffer configuration register [5212+] + * (buffer size) */ #define AR5K_QCU_CBCFG 0x0b08 @@ -652,80 +705,100 @@ * No lockout means there is no special handling. */ #define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */ -#define AR5K_DCU_MISC_BACKOFF 0x000007ff /* Mask for backoff setting (?) */ +#define AR5K_DCU_MISC_BACKOFF 0x000007ff /* Mask for backoff threshold */ #define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */ -#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll (?) */ -#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff (?) */ -#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch (?) */ +#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */ +#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */ +#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */ #define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */ -#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 -#define AR5K_DCU_MISC_VIRTCOL_MODIFIED 1 -#define AR5K_DCU_MISC_VIRTCOL_IGNORE 2 -#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Beacon enable (?) */ +#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 +#define AR5K_DCU_MISC_VIRTCOL_MODIFIED 1 +#define AR5K_DCU_MISC_VIRTCOL_IGNORE 2 +#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */ #define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */ #define AR5K_DCU_MISC_ARBLOCK_CTL_S 17 -#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */ +#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */ #define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */ #define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */ -#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 -#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment (?) */ -#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff (?) */ -#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision policy (?) */ -#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 +#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 /* Ignore Arbiter lockout */ +#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment */ +#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff */ +#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision cw policy */ +#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS policy (?) */ #define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */ #define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q) /* * DCU frame sequence number registers */ -#define AR5K_DCU_SEQNUM_BASE 0x1140 -#define AR5K_DCU_SEQNUM_M 0x00000fff +#define AR5K_DCU_SEQNUM_BASE 0x1140 +#define AR5K_DCU_SEQNUM_M 0x00000fff #define AR5K_QUEUE_DFS_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q) /* - * DCU global IFS SIFS registers + * DCU global IFS SIFS register */ #define AR5K_DCU_GBL_IFS_SIFS 0x1030 #define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff /* - * DCU global IFS slot interval registers + * DCU global IFS slot interval register */ #define AR5K_DCU_GBL_IFS_SLOT 0x1070 #define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff /* - * DCU global IFS EIFS registers + * DCU global IFS EIFS register */ #define AR5K_DCU_GBL_IFS_EIFS 0x10b0 #define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff /* - * DCU global IFS misc registers + * DCU global IFS misc register + * + * LFSR stands for Linear Feedback Shift Register + * and it's used for generating pseudo-random + * number sequences. + * + * (If i understand corectly, random numbers are + * used for idle sensing -multiplied with cwmin/max etc-) */ #define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */ -#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 -#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode (?) */ -#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask (?) */ -#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 -#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 +#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ +#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ +#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ +#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ +#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ +#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFC cnt reset policy (?) */ +#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */ +#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */ /* * DCU frame prefetch control register */ -#define AR5K_DCU_FP 0x1230 +#define AR5K_DCU_FP 0x1230 /* Register Address */ +#define AR5K_DCU_FP_NOBURST_DCU_EN 0x00000001 /* Enable non-burst prefetch on DCU (?) */ +#define AR5K_DCU_FP_NOBURST_EN 0x00000010 /* Enable non-burst prefetch (?) */ +#define AR5K_DCU_FP_BURST_DCU_EN 0x00000020 /* Enable burst prefetch on DCU (?) */ /* * DCU transmit pause control/status register */ #define AR5K_DCU_TXP 0x1270 /* Register Address */ -#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask (?) */ -#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status (?) */ +#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask */ +#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status */ /* - * DCU transmit filter register + * DCU transmit filter table 0 (32 entries) */ -#define AR5K_DCU_TX_FILTER 0x1038 +#define AR5K_DCU_TX_FILTER_0_BASE 0x1038 +#define AR5K_DCU_TX_FILTER_0(_n) (AR5K_DCU_TX_FILTER_0_BASE + (_n * 64)) + +/* + * DCU transmit filter table 1 (16 entries) + */ +#define AR5K_DCU_TX_FILTER_1_BASE 0x103c +#define AR5K_DCU_TX_FILTER_1(_n) (AR5K_DCU_TX_FILTER_1_BASE + ((_n - 32) * 64)) /* * DCU clear transmit filter register @@ -739,9 +812,6 @@ /* * Reset control register - * - * 4 and 8 are not used in 5211/5212 and - * 2 means "baseband reset" on 5211/5212. */ #define AR5K_RESET_CTL 0x4000 /* Register Address */ #define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */ @@ -765,6 +835,7 @@ #define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */ #define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 #define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */ +/* more bits */ /* * Interrupt pending register @@ -776,13 +847,14 @@ * Sleep force register */ #define AR5K_SFR 0x400c -#define AR5K_SFR_M 0x00000001 +#define AR5K_SFR_EN 0x00000001 /* * PCI configuration register */ #define AR5K_PCICFG 0x4010 /* Register Address */ #define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */ +#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock (?) */ #define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */ #define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */ #define AR5K_PCICFG_EESIZE_S 3 @@ -798,19 +870,21 @@ #define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix (?) */ #define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep (?) */ #define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ -#define AR5K_PCICFG_SL_INPEN 0x00002800 /* Sleep even whith pending interrupts (?) */ +#define AR5K_PCICFG_UNK 0x00001000 /* Passed on some parts durring attach (?) */ +#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts (?) */ #define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ #define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ #define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ #define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */ #define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */ #define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */ -#define AR5K_PCICFG_LEDBLINK 0x00700000 +#define AR5K_PCICFG_LEDBLINK 0x00700000 /* Led blink rate */ #define AR5K_PCICFG_LEDBLINK_S 20 -#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slow led blink rate (?) [5211+] */ +#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slowest led blink rate [5211+] */ #define AR5K_PCICFG_LEDSTATE \ (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \ AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW) +#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate (field) */ /* * "General Purpose Input/Output" (GPIO) control register @@ -947,7 +1021,7 @@ #define AR5K_EEPROM_VERSION_4_4 0x4004 #define AR5K_EEPROM_VERSION_4_5 0x4005 #define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ -#define AR5K_EEPROM_VERSION_4_7 0x3007 +#define AR5K_EEPROM_VERSION_4_7 0x4007 #define AR5K_EEPROM_MODE_11A 0 #define AR5K_EEPROM_MODE_11B 1 @@ -1023,10 +1097,14 @@ #define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */ /* - * EEPROM config register (?) + * EEPROM config register */ -#define AR5K_EEPROM_CFG 0x6010 - +#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */ +#define AR5K_EEPROM_CFG_SIZE_OVR 0x00000001 +#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */ +#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */ +#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protectio key */ +#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */ /* @@ -1050,7 +1128,7 @@ #define AR5K_STA_ID1 0x8004 /* Register Address */ #define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ #define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ -#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting (?) */ +#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ #define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */ #define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */ #define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */ @@ -1059,9 +1137,13 @@ AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211) #define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ #define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ -#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS (?) */ -#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS (?) */ +#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ +#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */ #define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate (for ACK/CTS ?) [5211+] */ +#define AR5K_STA_ID1_SELF_GEN_SECTORE 0x04000000 /* Self generate sectore (?) */ +#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ +#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Keysearch mode (?) */ +#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */ /* * First BSSID register (MAC address, lower 32bits) @@ -1117,7 +1199,7 @@ * * Retry limit register for 5210 (no QCU/DCU so it's done in PCU) */ -#define AR5K_NODCU_RETRY_LMT 0x801c /*Register Address */ +#define AR5K_NODCU_RETRY_LMT 0x801c /* Register Address */ #define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ #define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0 #define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */ @@ -1136,9 +1218,9 @@ #define AR5K_USEC_5211 0x801c /* Register Address [5211+] */ #define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \ AR5K_USEC_5210 : AR5K_USEC_5211) -#define AR5K_USEC_1 0x0000007f +#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */ #define AR5K_USEC_1_S 0 -#define AR5K_USEC_32 0x00003f80 +#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */ #define AR5K_USEC_32_S 7 #define AR5K_USEC_TX_LATENCY_5211 0x007fc000 #define AR5K_USEC_TX_LATENCY_5211_S 14 @@ -1152,16 +1234,16 @@ /* * PCU beacon control register */ -#define AR5K_BEACON_5210 0x8024 -#define AR5K_BEACON_5211 0x8020 +#define AR5K_BEACON_5210 0x8024 /*Register Address [5210] */ +#define AR5K_BEACON_5211 0x8020 /*Register Address [5211+] */ #define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \ AR5K_BEACON_5210 : AR5K_BEACON_5211) -#define AR5K_BEACON_PERIOD 0x0000ffff +#define AR5K_BEACON_PERIOD 0x0000ffff /* Mask for beacon period */ #define AR5K_BEACON_PERIOD_S 0 -#define AR5K_BEACON_TIM 0x007f0000 +#define AR5K_BEACON_TIM 0x007f0000 /* Mask for TIM offset */ #define AR5K_BEACON_TIM_S 16 -#define AR5K_BEACON_ENABLE 0x00800000 -#define AR5K_BEACON_RESET_TSF 0x01000000 +#define AR5K_BEACON_ENABLE 0x00800000 /* Enable beacons */ +#define AR5K_BEACON_RESET_TSF 0x01000000 /* Force TSF reset */ /* * CFP period register @@ -1234,7 +1316,6 @@ /* * Receive filter register - * TODO: Get these out of ar5xxx.h on ath5k */ #define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */ #define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */ @@ -1307,11 +1388,11 @@ #define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ #define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211) -#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 -#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs (?) */ -#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs (?) */ -#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption (?) */ -#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption (?) */ +#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */ +#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ +#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ +#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */ +#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */ #define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ #define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ #define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 @@ -1329,13 +1410,13 @@ #define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 #define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) -#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 /* Scrambler seed (?) */ +#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 /* Enable scrambler seed */ #define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 #define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211) #define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */ #define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ -#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask (?) */ +#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ #define AR5K_DIAG_SW_SCRAM_SEED_S 10 #define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ #define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 @@ -1344,6 +1425,7 @@ AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) #define AR5K_DIAG_SW_OBSPT_M 0x000c0000 #define AR5K_DIAG_SW_OBSPT_S 18 +/* more bits */ /* * TSF (clock) register (lower 32 bits) @@ -1369,15 +1451,34 @@ /* * ADDAC test register [5211+] */ -#define AR5K_ADDAC_TEST 0x8054 -#define AR5K_ADDAC_TEST_TXCONT 0x00000001 +#define AR5K_ADDAC_TEST 0x8054 /* Register Address */ +#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */ +#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */ +#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */ +#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */ +#define AR5K_ADDAC_TEST_USE_U8 0x00004000 /* Use upper 8 bits */ +#define AR5K_ADDAC_TEST_MSB 0x00008000 /* State of MSB */ +#define AR5K_ADDAC_TEST_TRIG_SEL 0x00010000 /* Trigger select */ +#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */ +#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */ +#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */ +#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* Test ARM (Adaptive Radio Mode ?) */ /* * Default antenna register [5211+] */ #define AR5K_DEFAULT_ANTENNA 0x8058 +/* + * Frame control QoS mask register (?) [5211+] + * (FC_QOS_MASK) + */ +#define AR5K_FRAME_CTL_QOSM 0x805c +/* + * Seq mask register (?) [5211+] + */ +#define AR5K_SEQ_MASK 0x8060 /* * Retry count register [5210] @@ -1449,124 +1550,242 @@ /* * XR (eXtended Range) mode register */ -#define AR5K_XRMODE 0x80c0 -#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f +#define AR5K_XRMODE 0x80c0 /* Register Address */ +#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f /* Mask for Poll type (?) */ #define AR5K_XRMODE_POLL_TYPE_S 0 -#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c +#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c /* Mask for Poll subtype (?) */ #define AR5K_XRMODE_POLL_SUBTYPE_S 2 -#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 -#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 -#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 +#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 /* Wait for poll */ +#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 /* Mask for SIFS delay */ +#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 /* Mask for frame hold (?) */ #define AR5K_XRMODE_FRAME_HOLD_S 20 /* * XR delay register */ -#define AR5K_XRDELAY 0x80c4 -#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff +#define AR5K_XRDELAY 0x80c4 /* Register Address */ +#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff /* Mask for slot delay */ #define AR5K_XRDELAY_SLOT_DELAY_S 0 -#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 +#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 /* Mask for CHIRP data delay */ #define AR5K_XRDELAY_CHIRP_DELAY_S 16 /* * XR timeout register */ -#define AR5K_XRTIMEOUT 0x80c8 -#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff +#define AR5K_XRTIMEOUT 0x80c8 /* Register Address */ +#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff /* Mask for CHIRP timeout */ #define AR5K_XRTIMEOUT_CHIRP_S 0 -#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 +#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 /* Mask for Poll timeout */ #define AR5K_XRTIMEOUT_POLL_S 16 /* * XR chirp register */ -#define AR5K_XRCHIRP 0x80cc -#define AR5K_XRCHIRP_SEND 0x00000001 -#define AR5K_XRCHIRP_GAP 0xffff0000 +#define AR5K_XRCHIRP 0x80cc /* Register Address */ +#define AR5K_XRCHIRP_SEND 0x00000001 /* Send CHIRP */ +#define AR5K_XRCHIRP_GAP 0xffff0000 /* Mask for CHIRP gap (?) */ /* * XR stomp register */ -#define AR5K_XRSTOMP 0x80d0 -#define AR5K_XRSTOMP_TX 0x00000001 -#define AR5K_XRSTOMP_RX_ABORT 0x00000002 -#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 +#define AR5K_XRSTOMP 0x80d0 /* Register Address */ +#define AR5K_XRSTOMP_TX 0x00000001 /* Stomp Tx (?) */ +#define AR5K_XRSTOMP_RX 0x00000002 /* Stomp Rx (?) */ +#define AR5K_XRSTOMP_TX_RSSI 0x00000004 /* Stomp Tx RSSI (?) */ +#define AR5K_XRSTOMP_TX_BSSID 0x00000008 /* Stomp Tx BSSID (?) */ +#define AR5K_XRSTOMP_DATA 0x00000010 /* Stomp data (?)*/ +#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 /* Mask for XR RSSI threshold */ /* * First enhanced sleep register */ -#define AR5K_SLEEP0 0x80d4 -#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff +#define AR5K_SLEEP0 0x80d4 /* Register Address */ +#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */ #define AR5K_SLEEP0_NEXT_DTIM_S 0 -#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 -#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 -#define AR5K_SLEEP0_CABTO 0xff000000 +#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */ +#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */ +#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */ #define AR5K_SLEEP0_CABTO_S 24 /* * Second enhanced sleep register */ -#define AR5K_SLEEP1 0x80d8 -#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff +#define AR5K_SLEEP1 0x80d8 /* Register Address */ +#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff /* Mask for next TIM (?) */ #define AR5K_SLEEP1_NEXT_TIM_S 0 -#define AR5K_SLEEP1_BEACON_TO 0xff000000 +#define AR5K_SLEEP1_BEACON_TO 0xff000000 /* Mask for Beacon Time Out */ #define AR5K_SLEEP1_BEACON_TO_S 24 /* * Third enhanced sleep register */ -#define AR5K_SLEEP2 0x80dc -#define AR5K_SLEEP2_TIM_PER 0x0000ffff +#define AR5K_SLEEP2 0x80dc /* Register Address */ +#define AR5K_SLEEP2_TIM_PER 0x0000ffff /* Mask for TIM period (?) */ #define AR5K_SLEEP2_TIM_PER_S 0 -#define AR5K_SLEEP2_DTIM_PER 0xffff0000 +#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */ #define AR5K_SLEEP2_DTIM_PER_S 16 /* * BSSID mask registers */ -#define AR5K_BSS_IDM0 0x80e0 -#define AR5K_BSS_IDM1 0x80e4 +#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */ +#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */ /* * TX power control (TPC) register + * + * XXX: PCDAC steps (0.5dbm) or DBM ? + * + * XXX: Mask changes for newer chips to 7f + * like tx power table ? */ -#define AR5K_TXPC 0x80e8 -#define AR5K_TXPC_ACK_M 0x0000003f +#define AR5K_TXPC 0x80e8 /* Register Address */ +#define AR5K_TXPC_ACK_M 0x0000003f /* Mask for ACK tx power */ #define AR5K_TXPC_ACK_S 0 -#define AR5K_TXPC_CTS_M 0x00003f00 +#define AR5K_TXPC_CTS_M 0x00003f00 /* Mask for CTS tx power */ #define AR5K_TXPC_CTS_S 8 -#define AR5K_TXPC_CHIRP_M 0x003f0000 +#define AR5K_TXPC_CHIRP_M 0x003f0000 /* Mask for CHIRP tx power */ #define AR5K_TXPC_CHIRP_S 22 /* * Profile count registers */ -#define AR5K_PROFCNT_TX 0x80ec -#define AR5K_PROFCNT_RX 0x80f0 -#define AR5K_PROFCNT_RXCLR 0x80f4 -#define AR5K_PROFCNT_CYCLE 0x80f8 +#define AR5K_PROFCNT_TX 0x80ec /* Tx count */ +#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ +#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ +#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ + +/* + * Quiet (period) control registers (?) + */ +#define AR5K_QUIET_CTL1 0x80fc /* Register Address */ +#define AR5K_QUIET_CTL1_NEXT_QT 0x0000ffff /* Mask for next quiet (period?) (?) */ +#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet (period?) */ +#define AR5K_QUIET_CTL2 0x8100 /* Register Address */ +#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period (?) */ +#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet duration (?) */ /* * TSF parameter register */ -#define AR5K_TSF_PARM 0x8104 -#define AR5K_TSF_PARM_INC_M 0x000000ff +#define AR5K_TSF_PARM 0x8104 /* Register Address */ +#define AR5K_TSF_PARM_INC_M 0x000000ff /* Mask for TSF increment */ #define AR5K_TSF_PARM_INC_S 0 +/* + * QoS register (?) + */ +#define AR5K_QOS 0x8108 /* Register Address */ +#define AR5K_QOS_NOACK_2BIT_VALUES 0x00000000 /* (field) */ +#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000020 /* (field) */ +#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000080 /* (field) */ + /* * PHY error filter register */ #define AR5K_PHY_ERR_FIL 0x810c -#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 -#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 -#define AR5K_PHY_ERR_FIL_CCK 0x02000000 +#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 /* Radar signal */ +#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 /* OFDM false detect (ANI) */ +#define AR5K_PHY_ERR_FIL_CCK 0x02000000 /* CCK false detect (ANI) */ /* - * Rate duration register + * XR latency register + */ +#define AR5K_XRLAT_TX 0x8110 + +/* + * ACK SIFS register + */ +#define AR5K_ACKSIFS 0x8114 /* Register Address */ +#define AR5K_ACKSIFS_INC 0x00000000 /* ACK SIFS Increment (field) */ + +/* + * MIC QoS control register (?) + */ +#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */ +#define AR5K_MIC_QOS_CTL_0 0x00000001 /* MIC QoS control 0 (?) */ +#define AR5K_MIC_QOS_CTL_1 0x00000004 /* MIC QoS control 1 (?) */ +#define AR5K_MIC_QOS_CTL_2 0x00000010 /* MIC QoS control 2 (?) */ +#define AR5K_MIC_QOS_CTL_3 0x00000040 /* MIC QoS control 3 (?) */ +#define AR5K_MIC_QOS_CTL_4 0x00000100 /* MIC QoS control 4 (?) */ +#define AR5K_MIC_QOS_CTL_5 0x00000400 /* MIC QoS control 5 (?) */ +#define AR5K_MIC_QOS_CTL_6 0x00001000 /* MIC QoS control 6 (?) */ +#define AR5K_MIC_QOS_CTL_7 0x00004000 /* MIC QoS control 7 (?) */ +#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */ + +/* + * MIC QoS select register (?) + */ +#define AR5K_MIC_QOS_SEL 0x811c +#define AR5K_MIC_QOS_SEL_0 0x00000001 +#define AR5K_MIC_QOS_SEL_1 0x00000010 +#define AR5K_MIC_QOS_SEL_2 0x00000100 +#define AR5K_MIC_QOS_SEL_3 0x00001000 +#define AR5K_MIC_QOS_SEL_4 0x00010000 +#define AR5K_MIC_QOS_SEL_5 0x00100000 +#define AR5K_MIC_QOS_SEL_6 0x01000000 +#define AR5K_MIC_QOS_SEL_7 0x10000000 + +/* + * Misc mode control register (?) + */ +#define AR5K_MISC_MODE 0x8120 /* Register Address */ +#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */ +#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */ +/* more bits */ + +/* + * OFDM Filter counter + */ +#define AR5K_OFDM_FIL_CNT 0x8124 + +/* + * CCK Filter counter + */ +#define AR5K_CCK_FIL_CNT 0x8128 + +/* + * PHY Error Counters (?) + */ +#define AR5K_PHYERR_CNT1 0x812c +#define AR5K_PHYERR_CNT1_MASK 0x8130 + +#define AR5K_PHYERR_CNT2 0x8134 +#define AR5K_PHYERR_CNT2_MASK 0x8138 + +/* + * TSF Threshold register (?) + */ +#define AR5K_TSF_THRES 0x813c + +/* + * Rate -> ACK SIFS mapping table (32 entries) + */ +#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */ +#define AR5K_RATE_ACKSIFS(_n) (AR5K_RATE_ACKSIFS_BSE + ((_n) << 2)) +#define AR5K_RATE_ACKSIFS_NORMAL 0x00000001 /* Normal SIFS (field) */ +#define AR5K_RATE_ACKSIFS_TURBO 0x00000400 /* Turbo SIFS (field) */ + +/* + * Rate -> duration mapping table (32 entries) */ #define AR5K_RATE_DUR_BASE 0x8700 #define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2)) +/* + * Rate -> db mapping table + * (8 entries, each one has 4 8bit fields) + */ +#define AR5K_RATE2DB_BASE 0x87c0 +#define AR5K_RATE2DB(_n) (AR5K_RATE2DB_BASE + ((_n) << 2)) + +/* + * db -> Rate mapping table + * (8 entries, each one has 4 8bit fields) + */ +#define AR5K_DB2RATE_BASE 0x87e0 +#define AR5K_DB2RATE(_n) (AR5K_DB2RATE_BASE + ((_n) << 2)) + /*===5212 end===*/ /* @@ -1613,12 +1832,34 @@ /*===PHY REGISTERS===*/ /* - * PHY register + * PHY registers start */ #define AR5K_PHY_BASE 0x9800 #define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2)) -#define AR5K_PHY_SHIFT_2GHZ 0x00004007 -#define AR5K_PHY_SHIFT_5GHZ 0x00000007 + +/* + * TST_2 (Misc config parameters) + */ +#define AR5K_PHY_TST2 0x9800 /* Register Address */ +#define AR5K_PHY_TST2_TRIG_SEL 0x00000001 /* Trigger select (?) (field ?) */ +#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) (field ?) */ +#define AR5K_PHY_TST2_CBUS_MODE 0x00000100 /* Cardbus mode (?) */ +/* bit reserved */ +#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */ +#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */ +#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */ +#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */ +#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch) */ +#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */ +#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */ +#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */ +#define AR5K_PHY_TST2_AGC_OBS_SEL_3 0x00040000 /* AGC OBS Select 3 (?) */ +#define AR5K_PHY_TST2_BBB_OBS_SEL 0x00080000 /* BB OBS Select (field ?) */ +#define AR5K_PHY_TST2_ADC_OBS_SEL 0x00800000 /* ADC OBS Select (field ?) */ +#define AR5K_PHY_TST2_RX_CLR_SEL 0x08000000 /* RX Clear Select (?) */ +#define AR5K_PHY_TST2_FORCE_AGC_CLR 0x10000000 /* Force AGC clear (?) */ +#define AR5K_PHY_SHIFT_2GHZ 0x00004007 /* Used to access 2GHz radios */ +#define AR5K_PHY_SHIFT_5GHZ 0x00000007 /* Used to access 5GHz radios (default) */ /* * PHY frame control register [5110] /turbo mode register [5111+] @@ -1630,18 +1871,21 @@ * a "turbo mode register" for 5110. We treat this one as * a frame control register for 5110 below. */ -#define AR5K_PHY_TURBO 0x9804 -#define AR5K_PHY_TURBO_MODE 0x00000001 -#define AR5K_PHY_TURBO_SHORT 0x00000002 +#define AR5K_PHY_TURBO 0x9804 /* Register Address */ +#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ +#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Short mode (20Mhz channels) (?) */ /* * PHY agility command register + * (aka TST_1) */ -#define AR5K_PHY_AGC 0x9808 -#define AR5K_PHY_AGC_DISABLE 0x08000000 +#define AR5K_PHY_AGC 0x9808 /* Register Address */ +#define AR5K_PHY_TST1 0x9808 +#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/ +#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */ /* - * PHY timing register [5112+] + * PHY timing register 3 [5112+] */ #define AR5K_PHY_TIMING_3 0x9814 #define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000 @@ -1657,26 +1901,81 @@ /* * PHY activation register */ -#define AR5K_PHY_ACT 0x981c -#define AR5K_PHY_ACT_ENABLE 0x00000001 -#define AR5K_PHY_ACT_DISABLE 0x00000002 +#define AR5K_PHY_ACT 0x981c /* Register Address */ +#define AR5K_PHY_ACT_ENABLE 0x00000001 /* Activate PHY */ +#define AR5K_PHY_ACT_DISABLE 0x00000002 /* Deactivate PHY */ + +/* + * PHY RF control registers + * (i think these are delay times, + * these calibration values exist + * in EEPROM) + */ +#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */ +#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* Mask for TX frame to TX d(esc?) start */ + +#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */ +#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000000f /* Mask for TX end to XLNA on */ + +#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */ +#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */ +#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON 0x00000100 /* TX frame to XPA B on (field) */ +#define AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF 0x00010000 /* TX end to XPA A off (field) */ +#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF 0x01000000 /* TX end to XPA B off (field) */ + +/* + * Pre-Amplifier control register + * (XPA -> external pre-amplifier) + */ +#define AR5K_PHY_PA_CTL 0x9838 /* Register Address */ +#define AR5K_PHY_PA_CTL_XPA_A_HI 0x00000001 /* XPA A high (?) */ +#define AR5K_PHY_PA_CTL_XPA_B_HI 0x00000002 /* XPA B high (?) */ +#define AR5K_PHY_PA_CTL_XPA_A_EN 0x00000004 /* Enable XPA A */ +#define AR5K_PHY_PA_CTL_XPA_B_EN 0x00000008 /* Enable XPA B */ + +/* + * PHY settling register + */ +#define AR5K_PHY_SETTLING 0x9844 /* Register Address */ +#define AR5K_PHY_SETTLING_AGC 0x0000007f /* Mask for AGC settling time */ +#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Mask for Switch settlig time */ + +/* + * PHY Gain registers + */ +#define AR5K_PHY_GAIN 0x9848 /* Register Address */ +#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* Mask for TX-RX Attenuation */ + +#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */ +#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */ + +/* + * Desired size register + * (for more infos read ANI patent) + */ +#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */ +#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* Mask for ADC desired size */ +#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* Mask for PGA desired size */ +#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Mask for Total desired size (?) */ /* * PHY signal register + * (for more infos read ANI patent) */ -#define AR5K_PHY_SIG 0x9858 -#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 +#define AR5K_PHY_SIG 0x9858 /* Register Address */ +#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* Mask for FIRSTEP */ #define AR5K_PHY_SIG_FIRSTEP_S 12 -#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 +#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* Mask for FIPWR */ #define AR5K_PHY_SIG_FIRPWR_S 18 /* * PHY coarse agility control register + * (for more infos read ANI patent) */ -#define AR5K_PHY_AGCCOARSE 0x985c -#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 +#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */ +#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* Mask for AGC Coarse low */ #define AR5K_PHY_AGCCOARSE_LO_S 7 -#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 +#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* Mask for AGC Coarse high */ #define AR5K_PHY_AGCCOARSE_HI_S 15 /* @@ -1689,12 +1988,13 @@ /* * PHY noise floor status register */ -#define AR5K_PHY_NF 0x9864 -#define AR5K_PHY_NF_M 0x000001ff -#define AR5K_PHY_NF_ACTIVE 0x00000100 +#define AR5K_PHY_NF 0x9864 /* Register address */ +#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */ +#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */ #define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) #define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) #define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) +#define AR5K_PHY_NF_THRESH62 0x00001000 /* Thresh62 -check ANI patent- (field) */ /* * PHY ADC saturation register [5110] @@ -1705,6 +2005,30 @@ #define AR5K_PHY_ADCSAT_THR 0x000007e0 #define AR5K_PHY_ADCSAT_THR_S 5 +/* + * PHY Weak ofdm signal detection threshold registers (ANI) [5212+] + */ + +/* High thresholds */ +#define AR5K_PHY_WEAK_OFDM_HIGH_THR 0x9868 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT 0x0000001f +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S 0 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1 0x00fe0000 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S 17 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2 0x7f000000 +#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24 + +/* Low thresholds */ +#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c +#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1 0x001fc000 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S 14 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2 0x0fe00000 +#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S 21 + + /* * PHY sleep registers [5112+] */ @@ -1730,6 +2054,8 @@ AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212) #define AR5K_PHY_PLL_RF5111 0x00000000 #define AR5K_PHY_PLL_RF5112 0x00000040 +#define AR5K_PHY_PLL_HALF_RATE 0x00000100 +#define AR5K_PHY_PLL_QUARTER_RATE 0x00000200 /* * RF Buffer register @@ -1792,23 +2118,74 @@ #define AR5K_PHY_RFSTG_DISABLE 0x00000021 /* - * PHY receiver delay register [5111+] + * PHY Antenna control register */ -#define AR5K_PHY_RX_DELAY 0x9914 -#define AR5K_PHY_RX_DELAY_M 0x00003fff +#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */ +#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */ +#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */ +#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */ +#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x00000010 /* Switch table idle (?) */ /* - * PHY timing I(nphase) Q(adrature) control register [5111+] + * PHY receiver delay register [5111+] */ -#define AR5K_PHY_IQ 0x9920 /* Register address */ +#define AR5K_PHY_RX_DELAY 0x9914 /* Register Address */ +#define AR5K_PHY_RX_DELAY_M 0x00003fff /* Mask for RX activate to receive delay (/100ns) */ + +/* + * PHY max rx length register (?) [5111] + */ +#define AR5K_PHY_MAX_RX_LEN 0x991c + +/* + * PHY timing register 4 + * I(nphase)/Q(adrature) calibration register [5111+] + */ +#define AR5K_PHY_IQ 0x9920 /* Register Address */ #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ #define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 #define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ -#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 +#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 /* Mask for max number of samples in log scale */ #define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12 #define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */ +#define AR5K_PHY_IQ_USE_PT_DF 0x00020000 /* Use pilot track df (?) */ +#define AR5K_PHY_IQ_EARLY_TRIG_THR 0x00200000 /* Early trigger threshold (?) (field) */ +#define AR5K_PHY_IQ_PILOT_MASK_EN 0x10000000 /* Enable pilot mask (?) */ +#define AR5K_PHY_IQ_CHAN_MASK_EN 0x20000000 /* Enable channel mask (?) */ +#define AR5K_PHY_IQ_SPUR_FILT_EN 0x40000000 /* Enable spur filter */ +#define AR5K_PHY_IQ_SPUR_RSSI_EN 0x80000000 /* Enable spur rssi */ +/* + * PHY timing register 5 + * OFDM Self-correlator Cyclic RSSI threshold params + * (Check out bb_cycpwr_thr1 on ANI patent) + */ +#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */ +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */ +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */ +#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */ +#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */ +#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */ +#define AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI 0x00800000 /* Long sc threshold hi rssi (?) */ + +/* + * PHY-only warm reset register + */ +#define AR5K_PHY_WARM_RESET 0x9928 + +/* + * PHY-only control register + */ +#define AR5K_PHY_CTL 0x992c /* Register Address */ +#define AR5K_PHY_CTL_RX_DRAIN_RATE 0x00000001 /* RX drain rate (?) */ +#define AR5K_PHY_CTL_LATE_TX_SIG_SYM 0x00000002 /* Late tx signal symbol (?) */ +#define AR5K_PHY_CTL_GEN_SCRAMBLER 0x00000004 /* Generate scrambler */ +#define AR5K_PHY_CTL_TX_ANT_SEL 0x00000008 /* TX antenna select */ +#define AR5K_PHY_CTL_TX_ANT_STATIC 0x00000010 /* Static TX antenna */ +#define AR5K_PHY_CTL_RX_ANT_SEL 0x00000020 /* RX antenna select */ +#define AR5K_PHY_CTL_RX_ANT_STATIC 0x00000040 /* Static RX antenna */ +#define AR5K_PHY_CTL_LOW_FREQ_SLE_EN 0x00000080 /* Enable low freq sleep */ /* * PHY PAPD probe register [5111+ (?)] @@ -1816,9 +2193,13 @@ * Because it's always 0 in 5211 initialization code */ #define AR5K_PHY_PAPD_PROBE 0x9930 +#define AR5K_PHY_PAPD_PROBE_SH_HI_PAR 0x00000001 +#define AR5K_PHY_PAPD_PROBE_PCDAC_BIAS 0x00000002 +#define AR5K_PHY_PAPD_PROBE_COMP_GAIN 0x00000040 #define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00 #define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9 #define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000 +#define AR5K_PHY_PAPD_PROBE_PREDIST_EN 0x00010000 #define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */ #define AR5K_PHY_PAPD_PROBE_TYPE_S 23 #define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0 @@ -1848,15 +2229,16 @@ #define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) /*---[5111+]---*/ -#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 +#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ #define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 +#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ /*---[5110/5111]---*/ -#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 -#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 -#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* illegal rate */ -#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* illegal length */ +#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */ +#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */ +#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* Illegal rate */ +#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */ #define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000 -#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* tx underrun */ +#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */ #define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \ AR5K_PHY_FRAME_CTL_TXURN_ERR | \ AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \ @@ -1914,6 +2296,11 @@ after DFS is enabled */ #define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960 #define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964 +/* + * PHY Noise floor threshold + */ +#define AR5K_PHY_NFTHRES 0x9968 + /* * PHY clock sleep registers [5112+] */ @@ -1922,56 +2309,116 @@ after DFS is enabled */ #define AR5K_PHY_SDELAY 0x99f4 #define AR5K_PHY_SDELAY_32MHZ 0x000000ff #define AR5K_PHY_SPENDING 0x99f8 +#define AR5K_PHY_SPENDING_14 0x00000014 +#define AR5K_PHY_SPENDING_18 0x00000018 #define AR5K_PHY_SPENDING_RF5111 0x00000018 -#define AR5K_PHY_SPENDING_RF5112 0x00000014 /* <- i 've only seen this on 2425 dumps ! */ -#define AR5K_PHY_SPENDING_RF5112A 0x0000000e /* but since i only have 5112A-based chips */ -#define AR5K_PHY_SPENDING_RF5424 0x00000012 /* to test it might be also for old 5112. */ +#define AR5K_PHY_SPENDING_RF5112 0x00000014 +/* #define AR5K_PHY_SPENDING_RF5112A 0x0000000e */ +/* #define AR5K_PHY_SPENDING_RF5424 0x00000012 */ +#define AR5K_PHY_SPENDING_RF5413 0x00000014 +#define AR5K_PHY_SPENDING_RF2413 0x00000014 +#define AR5K_PHY_SPENDING_RF2425 0x00000018 /* * Misc PHY/radio registers [5110 - 5111] */ -#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */ +#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */ #define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2)) -#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */ +#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */ #define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2)) /* * PHY timing IQ calibration result register [5111+] */ -#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */ -#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */ +#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */ +#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */ #define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */ /* * PHY current RSSI register [5111+] */ -#define AR5K_PHY_CURRENT_RSSI 0x9c1c +#define AR5K_PHY_CURRENT_RSSI 0x9c1c + +/* + * PHY RF Bus grant register (?) + */ +#define AR5K_PHY_RFBUS_GRANT 0x9c20 + +/* + * PHY ADC test register + */ +#define AR5K_PHY_ADC_TEST 0x9c24 +#define AR5K_PHY_ADC_TEST_I 0x00000001 +#define AR5K_PHY_ADC_TEST_Q 0x00000200 + +/* + * PHY DAC test register + */ +#define AR5K_PHY_DAC_TEST 0x9c28 +#define AR5K_PHY_DAC_TEST_I 0x00000001 +#define AR5K_PHY_DAC_TEST_Q 0x00000200 + +/* + * PHY PTAT register (?) + */ +#define AR5K_PHY_PTAT 0x9c2c + +/* + * PHY Illegal TX rate register [5112+] + */ +#define AR5K_PHY_BAD_TX_RATE 0x9c30 + +/* + * PHY SPUR Power register [5112+] + */ +#define AR5K_PHY_SPUR_PWR 0x9c34 /* Register Address */ +#define AR5K_PHY_SPUR_PWR_I 0x00000001 /* SPUR Power estimate for I (field) */ +#define AR5K_PHY_SPUR_PWR_Q 0x00000100 /* SPUR Power estimate for Q (field) */ +#define AR5K_PHY_SPUR_PWR_FILT 0x00010000 /* Power with SPUR removed (field) */ + +/* + * PHY Channel status register [5112+] (?) + */ +#define AR5K_PHY_CHAN_STATUS 0x9c38 +#define AR5K_PHY_CHAN_STATUS_BT_ACT 0x00000001 +#define AR5K_PHY_CHAN_STATUS_RX_CLR_RAW 0x00000002 +#define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004 +#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008 + +/* + * PHY PAPD I (power?) table (?) + * (92! entries) + */ +#define AR5K_PHY_PAPD_I_BASE 0xa000 +#define AR5K_PHY_PAPD_I(_n) (AR5K_PHY_PAPD_I_BASE + ((_n) << 2)) /* * PHY PCDAC TX power table */ #define AR5K_PHY_PCDAC_TXPOWER_BASE_5211 0xa180 -#define AR5K_PHY_PCDAC_TXPOWER_BASE_5413 0xa280 -#define AR5K_PHY_PCDAC_TXPOWER_BASE (ah->ah_radio >= AR5K_RF5413 ? \ - AR5K_PHY_PCDAC_TXPOWER_BASE_5413 :\ +#define AR5K_PHY_PCDAC_TXPOWER_BASE_2413 0xa280 +#define AR5K_PHY_PCDAC_TXPOWER_BASE (ah->ah_radio >= AR5K_RF2413 ? \ + AR5K_PHY_PCDAC_TXPOWER_BASE_2413 :\ AR5K_PHY_PCDAC_TXPOWER_BASE_5211) #define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2)) /* * PHY mode register [5111+] */ -#define AR5K_PHY_MODE 0x0a200 /* Register address */ -#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation mask*/ +#define AR5K_PHY_MODE 0x0a200 /* Register Address */ +#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation bit */ #define AR5K_PHY_MODE_MOD_OFDM 0 #define AR5K_PHY_MODE_MOD_CCK 1 -#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode mask */ +#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode bit */ #define AR5K_PHY_MODE_FREQ_5GHZ 0 #define AR5K_PHY_MODE_FREQ_2GHZ 2 -#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Dynamic OFDM/CCK mode mask [5112+] */ +#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Enable Dynamic OFDM/CCK mode [5112+] */ #define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */ #define AR5K_PHY_MODE_RAD_RF5111 0 #define AR5K_PHY_MODE_RAD_RF5112 8 -#define AR5K_PHY_MODE_XR 0x00000010 /* [5112+] */ +#define AR5K_PHY_MODE_XR 0x00000010 /* Enable XR mode [5112+] */ +#define AR5K_PHY_MODE_HALF_RATE 0x00000020 /* Enable Half rate (test) */ +#define AR5K_PHY_MODE_QUARTER_RATE 0x00000040 /* Enable Quarter rat (test) */ /* * PHY CCK transmit control register [5111+ (?)] @@ -1979,6 +2426,15 @@ after DFS is enabled */ #define AR5K_PHY_CCKTXCTL 0xa204 #define AR5K_PHY_CCKTXCTL_WORLD 0x00000000 #define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010 +#define AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS 0x00000001 +#define AR5K_PHY_CCKTXCTK_DAC_SCALE 0x00000004 + +/* + * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] + */ +#define AR5K_PHY_CCK_CROSSCORR 0xa208 +#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000000f +#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 /* * PHY 2GHz gain register [5111+] From ba37746e547e14703a5ac86560c6e056620bc4cf Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:32:32 +0300 Subject: [PATCH 02/78] ath5k: Restore saved initval after POST * Restore saved initial value after POST Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 42ef41ed5d18..b3b9baa551bc 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -139,6 +139,8 @@ static int ath5k_hw_post(struct ath5k_hw *ah) for (c = 0; c < 2; c++) { cur_reg = regs[c]; + + /* Save previous value */ init_val = ath5k_hw_reg_read(ah, cur_reg); for (i = 0; i < 256; i++) { @@ -170,6 +172,10 @@ static int ath5k_hw_post(struct ath5k_hw *ah) var_pattern = 0x003b080f; ath5k_hw_reg_write(ah, var_pattern, cur_reg); } + + /* Restore previous value */ + ath5k_hw_reg_write(ah, init_val, cur_reg); + } return 0; From e5a4ad0dda8f79a984ba6391af65274b482b6703 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:34:39 +0300 Subject: [PATCH 03/78] ath5k: Misc hw_attach fixes * Correctly attach RF2425 * Update SREV values for Radio chips * Update hw_attach to use new SPENDING values * Write a bit after POST for some chips Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 8 +-- drivers/net/wireless/ath5k/hw.c | 80 +++++++++++------------------- 2 files changed, 35 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index ba35c30d203c..9102eea3c8bf 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -186,11 +186,13 @@ struct ath5k_srev_name { #define AR5K_SREV_RAD_2111 0x20 #define AR5K_SREV_RAD_5112 0x30 #define AR5K_SREV_RAD_5112A 0x35 +#define AR5K_SREV_RAD_5112B 0x36 #define AR5K_SREV_RAD_2112 0x40 #define AR5K_SREV_RAD_2112A 0x45 -#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */ -#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ -#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */ +#define AR5K_SREV_RAD_2112B 0x46 +#define AR5K_SREV_RAD_SC0 0x50 /* Found on 2413/2414 */ +#define AR5K_SREV_RAD_SC1 0x60 /* Found on 5413/5414 */ +#define AR5K_SREV_RAD_SC2 0xa0 /* Found on 2424-5/5424 */ #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ /* IEEE defs */ diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index b3b9baa551bc..8cd8659e9128 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -293,67 +293,42 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) /* Identify the radio chip*/ if (ah->ah_version == AR5K_AR5210) { ah->ah_radio = AR5K_RF5110; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { - ah->ah_radio = AR5K_RF5111; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { - - ah->ah_radio = AR5K_RF5112; - - if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; - } else { - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - } - - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { - ah->ah_radio = AR5K_RF2413; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { - ah->ah_radio = AR5K_RF5413; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { - - /* AR5424 */ - if (srev >= AR5K_SREV_VER_AR5424) { - ah->ah_radio = AR5K_RF5413; - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; - /* AR2424 */ - } else { - ah->ah_radio = AR5K_RF2413; /* For testing */ - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - } - /* - * Register returns 0x4 for radio revision + * Register returns 0x0/0x04 for radio revision * so ath5k_hw_radio_revision doesn't parse the value * correctly. For now we are based on mac's srev to * identify RF2425 radio. */ } else if (srev == AR5K_SREV_VER_AR2425) { ah->ah_radio = AR5K_RF2425; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2425; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { + ah->ah_radio = AR5K_RF5111; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { + ah->ah_radio = AR5K_RF5112; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { + ah->ah_radio = AR5K_RF2413; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { + ah->ah_radio = AR5K_RF5413; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { + /* AR5424 */ + if (srev >= AR5K_SREV_VER_AR5424) { + ah->ah_radio = AR5K_RF5413; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5413; + /* AR2424 */ + } else { + ah->ah_radio = AR5K_RF2413; /* For testing */ + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF2413; + } } - ah->ah_phy = AR5K_PHY(0); /* - * Identify AR5212-based PCI-E cards - * And write some initial settings. - * - * (doing a "strings" on ndis driver - * -ar5211.sys- reveals the following - * pci-e related functions: - * - * pcieClockReq - * pcieRxErrNotify - * pcieL1SKPEnable - * pcieAspm - * pcieDisableAspmOnRfWake - * pciePowerSaveEnable - * - * I guess these point to ClockReq but - * i'm not sure.) + * Write PCI-E power save settings */ if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); @@ -375,10 +350,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) if (ret) goto err_free; + /* Write AR5K_PCICFG_UNK on 2112B and later chips */ + if (ah->ah_radio_5ghz_revision > AR5K_SREV_RAD_2112B || + srev > AR5K_SREV_VER_AR2413) { + ath5k_hw_reg_write(ah, AR5K_PCICFG_UNK, AR5K_PCICFG); + } + /* * Get card capabilities, values, ... */ - ret = ath5k_eeprom_init(ah); if (ret) { ATH5K_ERR(sc, "unable to init EEPROM\n"); From 2203d6be7ed17af81a1dc35a0af9806086743b02 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:36:52 +0300 Subject: [PATCH 04/78] ath5k: Misc hw_reset updates * Update hw_reset to calculate some of the values we were using as static * Increase activation to rx delay Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 8cd8659e9128..dc51b844c62d 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -847,7 +847,22 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, else ath5k_hw_reg_write(ah, 0x00000000, 0x994c); - ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); + /* Some bits are disabled here, we know nothing about + * register 0xa228 yet, most of the times this ends up + * with a value 0x9b5 -haven't seen any dump with + * a different value- */ + /* Got this from decompiling binary HAL */ + data = ath5k_hw_reg_read(ah, 0xa228); + data &= 0xfffffdff; + ath5k_hw_reg_write(ah, data, 0xa228); + + data = ath5k_hw_reg_read(ah, 0xa228); + data &= 0xfffe03ff; + ath5k_hw_reg_write(ah, data, 0xa228); + data = 0; + + /* Just write 0x9b5 ? */ + /* ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); */ ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); ath5k_hw_reg_write(ah, 0x00000000, 0xa254); ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL); @@ -864,6 +879,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, else data = 0xffb80d20; ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); + data = 0; } /* @@ -883,7 +899,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /* * Write RF registers - * TODO:Does this work on 5211 (5111) ? */ ret = ath5k_hw_rfregs(ah, channel, mode); if (ret) @@ -1048,7 +1063,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); /* - * 5111/5112 Specific + * On 5211+ read activation -> rx delay + * and use it. */ if (ah->ah_version != AR5K_AR5210) { data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & @@ -1056,7 +1072,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, data = (channel->hw_value & CHANNEL_CCK) ? ((data << 2) / 22) : (data / 10); - udelay(100 + data); + udelay(100 + (2 * data)); + data = 0; } else { mdelay(1); } @@ -1139,6 +1156,12 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING); + + data = ath5k_hw_reg_read(ah, AR5K_USEC_5211) & 0xffffc07f ; + data |= (ah->ah_phy_spending == AR5K_PHY_SPENDING_18) ? + 0x00000f80 : 0x00001380 ; + ath5k_hw_reg_write(ah, data, AR5K_USEC_5211); + data = 0; } if (ah->ah_version == AR5K_AR5212) { From e2a0ccebc4ffabc1c7234cfd324299b5a936e0f2 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:38:16 +0300 Subject: [PATCH 05/78] ath5k: Do ADC test during reset * Do an ADC test during reset to match recent regdumps Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index dc51b844c62d..3937e46e4735 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -1078,6 +1078,19 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, mdelay(1); } + /* + * Perform ADC test (?) + */ + data = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); + ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); + for (i = 0; i <= 20; i++) { + if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) + break; + udelay(200); + } + ath5k_hw_reg_write(ah, data, AR5K_PHY_TST1); + data = 0; + /* * Enable calibration and wait until completion */ From df75dcddf99647d68f3b6b874effe5365c5024d9 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:41:26 +0300 Subject: [PATCH 06/78] ath5k: Reorder calibration calls during reset and update hw_set_power * Update ath5k_hw_reset and add some more documentation about PHY calibration * Fix ath5k_hw_set_power to use AR5K_SLEEP_CTL_SLE_ALLOW for Network sleep * Preserve sleep duration field while setting AR5K_SLEEP_CTL and reduce delays & checks for register's status (got this from decompiling & dumps, it works for me but it needs testing) Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 84 +++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 3937e46e4735..ad1a5b422c8c 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -1092,26 +1092,25 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, data = 0; /* - * Enable calibration and wait until completion + * Start automatic gain calibration + * + * During AGC calibration RX path is re-routed to + * a signal detector so we don't receive anything. + * + * This method is used to calibrate some static offsets + * used together with on-the fly I/Q calibration (the + * one performed via ath5k_hw_phy_calibrate), that doesn't + * interrupt rx path. + * + * If we are in a noisy environment AGC calibration may time + * out. */ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL); - if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL, 0, false)) { - ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", - channel->center_freq); - return -EAGAIN; - } - - ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - if (ret) - return ret; - + /* At the same time start I/Q calibration for QAM constellation + * -no need for CCK- */ ah->ah_calibration = false; - - /* A and G modes can use QAM modulation which requires enabling - * I and Q calibration. Don't bother in B mode. */ if (!(mode == AR5K_MODE_11B)) { ah->ah_calibration = true; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, @@ -1120,6 +1119,30 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, AR5K_PHY_IQ_RUN); } + /* Wait for gain calibration to finish (we check for I/Q calibration + * during ath5k_phy_calibrate) */ + if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, + AR5K_PHY_AGCCTL_CAL, 0, false)) { + ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", + channel->center_freq); + return -EAGAIN; + } + + /* + * Start noise floor calibration + * + * If we run NF calibration before AGC, it always times out. + * Binary HAL starts NF and AGC calibration at the same time + * and only waits for AGC to finish. I believe that's wrong because + * during NF calibration, rx path is also routed to a detector, so if + * it doesn't finish we won't have RX. + * + * XXX: Find an interval that's OK for all cards... + */ + ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); + if (ret) + return ret; + /* * Reset queues and start beacon timers at the end of the reset routine */ @@ -1247,7 +1270,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration) { unsigned int i; - u32 staid; + u32 staid, data; ATH5K_TRACE(ah->ah_sc); staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); @@ -1259,7 +1282,8 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, case AR5K_PM_NETWORK_SLEEP: if (set_chip) ath5k_hw_reg_write(ah, - AR5K_SLEEP_CTL_SLE | sleep_duration, + AR5K_SLEEP_CTL_SLE_ALLOW | + sleep_duration, AR5K_SLEEP_CTL); staid |= AR5K_STA_ID1_PWR_SV; @@ -1274,13 +1298,24 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, break; case AR5K_PM_AWAKE: + + staid &= ~AR5K_STA_ID1_PWR_SV; + if (!set_chip) goto commit; - ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); + /* Preserve sleep duration */ + data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); + if( data & 0xffc00000 ){ + data = 0; + } else { + data = data & 0xfffcffff; + } - for (i = 5000; i > 0; i--) { + ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); + udelay(15); + + for (i = 50; i > 0; i--) { /* Check if the chip did wake up */ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_SPWR_DN) == 0) @@ -1288,15 +1323,13 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, /* Wait a bit and retry */ udelay(200); - ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); + ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); } /* Fail if the chip didn't wake up */ if (i <= 0) return -EIO; - staid &= ~AR5K_STA_ID1_PWR_SV; break; default: @@ -1325,6 +1358,7 @@ void ath5k_hw_start_rx(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); + ath5k_hw_reg_read(ah, AR5K_CR); } /* @@ -1411,6 +1445,7 @@ int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue) } /* Start queue */ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); + ath5k_hw_reg_read(ah, AR5K_CR); } else { /* Return if queue is disabled */ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) @@ -1708,6 +1743,7 @@ enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask) * (they will be re-enabled afterwards). */ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); + ath5k_hw_reg_read(ah, AR5K_IER); old_mask = ah->ah_imr; @@ -3511,7 +3547,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_TXE); + AR5K_QCU_MISC_RDY_VEOL_POLICY); } if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) From 27bcdeed320c8c7dc0f502df43f6465f0d9840f1 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:42:47 +0300 Subject: [PATCH 07/78] ath5k: Add RF2425 initial rfgain values * Add initial RF gain settings for RF2425 Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/phy.c | 72 +++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index afd8689e5c03..66af70bd14e7 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -1020,6 +1020,74 @@ static const struct ath5k_ini_rfgain rfgain_2413[] = { { AR5K_RF_GAIN(63), { 0x000000f9 } }, }; +/* Initial RF Gain settings for RF2425 */ +static const struct ath5k_ini_rfgain rfgain_2425[] = { + { AR5K_RF_GAIN(0), { 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x00000181 } }, + { AR5K_RF_GAIN(4), { 0x000001c1 } }, + { AR5K_RF_GAIN(5), { 0x00000001 } }, + { AR5K_RF_GAIN(6), { 0x00000041 } }, + { AR5K_RF_GAIN(7), { 0x00000081 } }, + { AR5K_RF_GAIN(8), { 0x00000188 } }, + { AR5K_RF_GAIN(9), { 0x000001c8 } }, + { AR5K_RF_GAIN(10), { 0x00000008 } }, + { AR5K_RF_GAIN(11), { 0x00000048 } }, + { AR5K_RF_GAIN(12), { 0x00000088 } }, + { AR5K_RF_GAIN(13), { 0x00000189 } }, + { AR5K_RF_GAIN(14), { 0x000001c9 } }, + { AR5K_RF_GAIN(15), { 0x00000009 } }, + { AR5K_RF_GAIN(16), { 0x00000049 } }, + { AR5K_RF_GAIN(17), { 0x00000089 } }, + { AR5K_RF_GAIN(18), { 0x000001b0 } }, + { AR5K_RF_GAIN(19), { 0x000001f0 } }, + { AR5K_RF_GAIN(20), { 0x00000030 } }, + { AR5K_RF_GAIN(21), { 0x00000070 } }, + { AR5K_RF_GAIN(22), { 0x00000171 } }, + { AR5K_RF_GAIN(23), { 0x000001b1 } }, + { AR5K_RF_GAIN(24), { 0x000001f1 } }, + { AR5K_RF_GAIN(25), { 0x00000031 } }, + { AR5K_RF_GAIN(26), { 0x00000071 } }, + { AR5K_RF_GAIN(27), { 0x000001b8 } }, + { AR5K_RF_GAIN(28), { 0x000001f8 } }, + { AR5K_RF_GAIN(29), { 0x00000038 } }, + { AR5K_RF_GAIN(30), { 0x00000078 } }, + { AR5K_RF_GAIN(31), { 0x000000b8 } }, + { AR5K_RF_GAIN(32), { 0x000001b9 } }, + { AR5K_RF_GAIN(33), { 0x000001f9 } }, + { AR5K_RF_GAIN(34), { 0x00000039 } }, + { AR5K_RF_GAIN(35), { 0x00000079 } }, + { AR5K_RF_GAIN(36), { 0x000000b9 } }, + { AR5K_RF_GAIN(37), { 0x000000f9 } }, + { AR5K_RF_GAIN(38), { 0x000000f9 } }, + { AR5K_RF_GAIN(39), { 0x000000f9 } }, + { AR5K_RF_GAIN(40), { 0x000000f9 } }, + { AR5K_RF_GAIN(41), { 0x000000f9 } }, + { AR5K_RF_GAIN(42), { 0x000000f9 } }, + { AR5K_RF_GAIN(43), { 0x000000f9 } }, + { AR5K_RF_GAIN(44), { 0x000000f9 } }, + { AR5K_RF_GAIN(45), { 0x000000f9 } }, + { AR5K_RF_GAIN(46), { 0x000000f9 } }, + { AR5K_RF_GAIN(47), { 0x000000f9 } }, + { AR5K_RF_GAIN(48), { 0x000000f9 } }, + { AR5K_RF_GAIN(49), { 0x000000f9 } }, + { AR5K_RF_GAIN(50), { 0x000000f9 } }, + { AR5K_RF_GAIN(51), { 0x000000f9 } }, + { AR5K_RF_GAIN(52), { 0x000000f9 } }, + { AR5K_RF_GAIN(53), { 0x000000f9 } }, + { AR5K_RF_GAIN(54), { 0x000000f9 } }, + { AR5K_RF_GAIN(55), { 0x000000f9 } }, + { AR5K_RF_GAIN(56), { 0x000000f9 } }, + { AR5K_RF_GAIN(57), { 0x000000f9 } }, + { AR5K_RF_GAIN(58), { 0x000000f9 } }, + { AR5K_RF_GAIN(59), { 0x000000f9 } }, + { AR5K_RF_GAIN(60), { 0x000000f9 } }, + { AR5K_RF_GAIN(61), { 0x000000f9 } }, + { AR5K_RF_GAIN(62), { 0x000000f9 } }, + { AR5K_RF_GAIN(63), { 0x000000f9 } }, +}; + static const struct ath5k_gain_opt rfgain_opt_5112 = { 1, 8, @@ -1588,8 +1656,8 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) freq = 0; /* only 2Ghz */ break; case AR5K_RF2425: - ath5k_rfg = rfgain_2413; - size = ARRAY_SIZE(rfgain_2413); + ath5k_rfg = rfgain_2425; + size = ARRAY_SIZE(rfgain_2425); freq = 0; /* only 2Ghz */ break; default: From cc6323c7d8c231d83e592ff9f7acf2cac5e016f7 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:44:43 +0300 Subject: [PATCH 08/78] ath5k: Update channel functions * Add channel function for RF2425 (got this from decompiling binary HAL, i have no idea why there is a 5GHz section but i'm looking into it) * Update RF5112 channel function (also got this from decompiling binary HAL) * Set JAPAN setting for channel 14 on all PHY chips Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/phy.c | 59 +++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 66af70bd14e7..cbc362d20719 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -1898,9 +1898,6 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, data = data0 = data1 = data2 = 0; c = channel->center_freq; - /* - * Set the channel on the RF5112 or newer - */ if (c < 4800) { if (!((c - 2224) % 5)) { data0 = ((2 * (c - 704)) - 3040) / 10; @@ -1912,7 +1909,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, return -EINVAL; data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); - } else { + } else if ((c - (c % 5)) != 2 || c > 5435) { if (!(c % 20) && c >= 5120) { data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); data2 = ath5k_hw_bitswap(3, 2); @@ -1924,6 +1921,9 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, data2 = ath5k_hw_bitswap(1, 2); } else return -EINVAL; + } else { + data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data2 = ath5k_hw_bitswap(0, 2); } data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; @@ -1934,6 +1934,45 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, return 0; } +/* + * Set the channel on the RF2425 + */ +static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, + struct ieee80211_channel *channel) +{ + u32 data, data0, data2; + u16 c; + + data = data0 = data2 = 0; + c = channel->center_freq; + + if (c < 4800) { + data0 = ath5k_hw_bitswap((c - 2272), 8); + data2 = 0; + /* ? 5GHz ? */ + } else if ((c - (c % 5)) != 2 || c > 5435) { + if (!(c % 20) && c < 5120) + data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); + else if (!(c % 10)) + data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); + else if (!(c % 5)) + data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); + else + return -EINVAL; + data2 = ath5k_hw_bitswap(1, 2); + } else { + data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); + data2 = ath5k_hw_bitswap(0, 2); + } + + data = (data0 << 4) | data2 << 2 | 0x1001; + + ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); + ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); + + return 0; +} + /* * Set a channel on the radio chip */ @@ -1963,6 +2002,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) case AR5K_RF5111: ret = ath5k_hw_rf5111_channel(ah, channel); break; + case AR5K_RF2425: + ret = ath5k_hw_rf2425_channel(ah, channel); + break; default: ret = ath5k_hw_rf5112_channel(ah, channel); break; @@ -1971,6 +2013,15 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) if (ret) return ret; + /* Set JAPAN setting for channel 14 */ + if (channel->center_freq == 2484) { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, + AR5K_PHY_CCKTXCTL_JAPAN); + } else { + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, + AR5K_PHY_CCKTXCTL_WORLD); + } + ah->ah_current_channel.center_freq = channel->center_freq; ah->ah_current_channel.hw_value = channel->hw_value; ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; From f860ee26db51c478fd70039bd4902912a8d93993 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Sun, 20 Jul 2008 06:47:12 +0300 Subject: [PATCH 09/78] ath5k: Update phy calibration functions * Enable I/Q calibration each time we have correction results (we were only enabling calibration during reset). If we don't we commit the same results each time calibration routine is called. * Add some documentation and a TODO on nf calibration * Return -EAGAIN on noise floor timeout/failure Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/phy.c | 54 +++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index cbc362d20719..fa0d47faf574 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -2052,6 +2052,8 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 * + * XXX: Since during noise floor calibration antennas are detached according to + * the patent, we should stop tx queues here. */ int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) @@ -2061,7 +2063,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) s32 noise_floor; /* - * Enable noise floor calibration and wait until completion + * Enable noise floor calibration */ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF); @@ -2071,7 +2073,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) if (ret) { ATH5K_ERR(ah->ah_sc, "noise floor calibration timeout (%uMHz)\n", freq); - return ret; + return -EAGAIN; } /* Wait until the noise floor is calibrated and read the value */ @@ -2093,7 +2095,7 @@ ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { ATH5K_ERR(ah->ah_sc, "noise floor calibration failed (%uMHz)\n", freq); - return -EIO; + return -EAGAIN; } ah->ah_noise_floor = noise_floor; @@ -2206,38 +2208,66 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, } /* - * Perform a PHY calibration on RF5111/5112 + * Perform a PHY calibration on RF5111/5112 and newer chips */ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel) { u32 i_pwr, q_pwr; s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; + int i; ATH5K_TRACE(ah->ah_sc); if (!ah->ah_calibration || - ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) + ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) goto done; - ah->ah_calibration = false; + /* Calibration has finished, get the results and re-run */ + for (i = 0; i <= 10; i++) { + iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); + i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); + q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); + } - iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); - i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); - q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; - q_coffd = q_pwr >> 6; + q_coffd = q_pwr >> 7; + /* No correction */ if (i_coffd == 0 || q_coffd == 0) goto done; i_coff = ((-iq_corr) / i_coffd) & 0x3f; - q_coff = (((s32)i_pwr / q_coffd) - 64) & 0x1f; - /* Commit new IQ value */ + /* Boundary check */ + if (i_coff > 31) + i_coff = 31; + if (i_coff < -32) + i_coff = -32; + + q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f; + + /* Boundary check */ + if (q_coff > 15) + q_coff = 15; + if (q_coff < -16) + q_coff = -16; + + /* Commit new I/Q value */ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); + /* Re-enable calibration -if we don't we'll commit + * the same values again and again */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, + AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); + done: + + /* TODO: Separate noise floor calibration from I/Q calibration + * since noise floor calibration interrupts rx path while I/Q + * calibration doesn't. We don't need to run noise floor calibration + * as often as I/Q calibration.*/ ath5k_hw_noise_floor_calibration(ah, channel->center_freq); /* Request RF gain */ From 6e28fbef0f330d7c1cade345eeae003d4e5d6070 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 31 Jul 2008 10:53:57 -0300 Subject: [PATCH 10/78] rfkill: query EV_SW states when rfkill-input (re)?connects to a input device Every time a new input device that is capable of one of the rfkill EV_SW events (currently only SW_RFKILL_ALL) is connected to rfkill-input, we must check the states of the input EV_SW switches and take action. Otherwise, we will ignore the initial switch state. We also need to re-check the states of the EV_SW switches after a device that was under an exclusive grab is released back to us, since we got no input events from that device while it was grabbed. Signed-off-by: Henrique de Moraes Holschuh Acked-by: Ivo van Doorn Cc: Dmitry Torokhov Signed-off-by: John W. Linville --- net/rfkill/rfkill-input.c | 54 ++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/net/rfkill/rfkill-input.c b/net/rfkill/rfkill-input.c index 8aa822730145..e5b69556bb5b 100644 --- a/net/rfkill/rfkill-input.c +++ b/net/rfkill/rfkill-input.c @@ -109,6 +109,25 @@ static DEFINE_RFKILL_TASK(rfkill_uwb, RFKILL_TYPE_UWB); static DEFINE_RFKILL_TASK(rfkill_wimax, RFKILL_TYPE_WIMAX); static DEFINE_RFKILL_TASK(rfkill_wwan, RFKILL_TYPE_WWAN); +static void rfkill_schedule_evsw_rfkillall(int state) +{ + /* EVERY radio type. state != 0 means radios ON */ + /* handle EPO (emergency power off) through shortcut */ + if (state) { + rfkill_schedule_set(&rfkill_wwan, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_wimax, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_uwb, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_bt, + RFKILL_STATE_UNBLOCKED); + rfkill_schedule_set(&rfkill_wlan, + RFKILL_STATE_UNBLOCKED); + } else + rfkill_schedule_epo(); +} + static void rfkill_event(struct input_handle *handle, unsigned int type, unsigned int code, int data) { @@ -132,21 +151,7 @@ static void rfkill_event(struct input_handle *handle, unsigned int type, } else if (type == EV_SW) { switch (code) { case SW_RFKILL_ALL: - /* EVERY radio type. data != 0 means radios ON */ - /* handle EPO (emergency power off) through shortcut */ - if (data) { - rfkill_schedule_set(&rfkill_wwan, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_wimax, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_uwb, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_bt, - RFKILL_STATE_UNBLOCKED); - rfkill_schedule_set(&rfkill_wlan, - RFKILL_STATE_UNBLOCKED); - } else - rfkill_schedule_epo(); + rfkill_schedule_evsw_rfkillall(data); break; default: break; @@ -168,6 +173,7 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, handle->handler = handler; handle->name = "rfkill"; + /* causes rfkill_start() to be called */ error = input_register_handle(handle); if (error) goto err_free_handle; @@ -185,6 +191,23 @@ static int rfkill_connect(struct input_handler *handler, struct input_dev *dev, return error; } +static void rfkill_start(struct input_handle *handle) +{ + /* Take event_lock to guard against configuration changes, we + * should be able to deal with concurrency with rfkill_event() + * just fine (which event_lock will also avoid). */ + spin_lock_irq(&handle->dev->event_lock); + + if (test_bit(EV_SW, handle->dev->evbit)) { + if (test_bit(SW_RFKILL_ALL, handle->dev->swbit)) + rfkill_schedule_evsw_rfkillall(test_bit(SW_RFKILL_ALL, + handle->dev->sw)); + /* add resync for further EV_SW events here */ + } + + spin_unlock_irq(&handle->dev->event_lock); +} + static void rfkill_disconnect(struct input_handle *handle) { input_close_device(handle); @@ -225,6 +248,7 @@ static struct input_handler rfkill_handler = { .event = rfkill_event, .connect = rfkill_connect, .disconnect = rfkill_disconnect, + .start = rfkill_start, .name = "rfkill", .id_table = rfkill_ids, }; From 7c4f4578fc85d42d149f86b47f76c28626a20d92 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Jul 2008 14:17:37 +0400 Subject: [PATCH 11/78] RFKILL: allow one to specify led trigger name Allow the rfkill driver to specify led trigger name. By default it still defaults to the name of rfkill switch. Signed-off-by: Dmitry Baryshkov Acked-by: Henrique de Moraes Holschuh Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- net/rfkill/rfkill.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index c6f2f388cb72..5c24f3647189 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -589,7 +589,8 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill) #ifdef CONFIG_RFKILL_LEDS int error; - rfkill->led_trigger.name = rfkill->dev.bus_id; + if (!rfkill->led_trigger.name) + rfkill->led_trigger.name = rfkill->dev.bus_id; error = led_trigger_register(&rfkill->led_trigger); if (error) rfkill->led_trigger.name = NULL; From 96185664f10e79d038c084305d3cacff9b52204f Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 22 Jul 2008 14:21:59 +0400 Subject: [PATCH 12/78] RFKILL: set the status of the leds on activation. Provide default activate function to set the state of the led when the led becomes bound to the trigger Signed-off-by: Dmitry Baryshkov Acked-by: Ivo van Doorn Acked-by: Henrique de Moraes Holschuh Signed-off-by: John W. Linville --- net/rfkill/rfkill.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index 5c24f3647189..d2d45655cd1a 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -105,6 +105,16 @@ static void rfkill_led_trigger(struct rfkill *rfkill, #endif /* CONFIG_RFKILL_LEDS */ } +#ifdef CONFIG_RFKILL_LEDS +static void rfkill_led_trigger_activate(struct led_classdev *led) +{ + struct rfkill *rfkill = container_of(led->trigger, + struct rfkill, led_trigger); + + rfkill_led_trigger(rfkill, rfkill->state); +} +#endif /* CONFIG_RFKILL_LEDS */ + static void notify_rfkill_state_change(struct rfkill *rfkill) { blocking_notifier_call_chain(&rfkill_notifier_list, @@ -591,6 +601,8 @@ static void rfkill_led_trigger_register(struct rfkill *rfkill) if (!rfkill->led_trigger.name) rfkill->led_trigger.name = rfkill->dev.bus_id; + if (!rfkill->led_trigger.activate) + rfkill->led_trigger.activate = rfkill_led_trigger_activate; error = led_trigger_register(&rfkill->led_trigger); if (error) rfkill->led_trigger.name = NULL; From dc1968e7b7862bcd2d358c1be6119c011992bdd2 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 23 Jul 2008 13:17:34 +0200 Subject: [PATCH 13/78] Ath5k: mask out unneeded interrupts Mask out previously demanded interrupt flags because we set new ones. Don't allow mixing them after switch from sta to ibss and vice versa. Signed-off-by: Jiri Slaby Cc: Nick Kossifidis Cc: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index ff3fad794b61..ebf19bc11f5b 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2170,6 +2170,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) ath5k_hw_set_intr(ah, 0); sc->bmisscount = 0; + sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); if (sc->opmode == IEEE80211_IF_TYPE_STA) { sc->imask |= AR5K_INT_BMISS; From f8e79ddd31c3615ddca26b9a469c44a7adbd4e13 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 24 Jul 2008 18:46:44 +0300 Subject: [PATCH 14/78] mac80211: fix fragmentation kludge This patch make mac80211 transmit correctly fragmented packet after queue was stopped Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- net/mac80211/ieee80211_i.h | 1 + net/mac80211/tx.c | 17 ++++++++++++----- net/mac80211/util.c | 1 + 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a4f9a832722a..a2e200f9811e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -586,6 +586,7 @@ struct ieee80211_local { struct timer_list sta_cleanup; unsigned long queues_pending[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; + unsigned long queues_pending_run[BITS_TO_LONGS(IEEE80211_MAX_QUEUES)]; struct ieee80211_tx_stored_packet pending_packet[IEEE80211_MAX_QUEUES]; struct tasklet_struct tx_pending_tasklet; diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 69019e943873..771ec68b848d 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1060,13 +1060,14 @@ static int ieee80211_tx_prepare(struct ieee80211_tx_data *tx, static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, struct ieee80211_tx_data *tx) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct ieee80211_tx_info *info; int ret, i; - if (netif_subqueue_stopped(local->mdev, skb)) - return IEEE80211_TX_AGAIN; - if (skb) { + if (netif_subqueue_stopped(local->mdev, skb)) + return IEEE80211_TX_AGAIN; + info = IEEE80211_SKB_CB(skb); + ieee80211_dump_frame(wiphy_name(local->hw.wiphy), "TX to low-level driver", skb); ret = local->ops->tx(local_to_hw(local), skb); @@ -1215,6 +1216,7 @@ retry: if (ret == IEEE80211_TX_FRAG_AGAIN) skb = NULL; + set_bit(queue, local->queues_pending); smp_mb(); /* @@ -1708,14 +1710,19 @@ void ieee80211_tx_pending(unsigned long data) netif_tx_lock_bh(dev); for (i = 0; i < ieee80211_num_regular_queues(&local->hw); i++) { /* Check that this queue is ok */ - if (__netif_subqueue_stopped(local->mdev, i)) + if (__netif_subqueue_stopped(local->mdev, i) && + !test_bit(i, local->queues_pending_run)) continue; if (!test_bit(i, local->queues_pending)) { + clear_bit(i, local->queues_pending_run); ieee80211_wake_queue(&local->hw, i); continue; } + clear_bit(i, local->queues_pending_run); + netif_start_subqueue(local->mdev, i); + store = &local->pending_packet[i]; tx.extra_frag = store->extra_frag; tx.num_extra_frag = store->num_extra_frag; diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 19f85e1b3695..0d463c80c404 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -361,6 +361,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) struct ieee80211_local *local = hw_to_local(hw); if (test_bit(queue, local->queues_pending)) { + set_bit(queue, local->queues_pending_run); tasklet_schedule(&local->tx_pending_tasklet); } else { netif_wake_subqueue(local->mdev, queue); From 8de394f60235a825b32f30441290a44251eca45d Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 24 Jul 2008 18:22:55 +0200 Subject: [PATCH 15/78] ath5k: remove obsolete declaration of struct ieee80211_hw_mode Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/debug.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index 2cf8d18b10e3..ffc529393306 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -63,7 +63,6 @@ struct ath5k_softc; struct ath5k_hw; -struct ieee80211_hw_mode; struct sk_buff; struct ath5k_buf; From 143b09efb74efd3328f57d7a4bd6d7663c1d6497 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 24 Jul 2008 21:33:42 +0300 Subject: [PATCH 16/78] iwlwifi: don't stop queue in the middle of fragmented packet This patch avoids stopping queue in the middle of the fragmented packet. It is required that there will be ~10 (max packet/min fragment) or 16 (4 bits of frag number) free tfds all the time. Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-tx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index f72cd0bf6aa3..0182e4da8e35 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -962,16 +962,16 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) if (ret) return ret; - if ((iwl_queue_space(q) < q->high_mark) - && priv->mac80211_registered) { + if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { if (wait_write_ptr) { spin_lock_irqsave(&priv->lock, flags); txq->need_update = 1; iwl_txq_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); + } else { + ieee80211_stop_queue(priv->hw, + skb_get_queue_mapping(skb)); } - - ieee80211_stop_queue(priv->hw, skb_get_queue_mapping(skb)); } return 0; From 7c7e6af37dad30632103497a72a1273d18ec55fe Mon Sep 17 00:00:00 2001 From: Andrea Merello Date: Fri, 25 Jul 2008 19:08:11 +0200 Subject: [PATCH 17/78] Rtl8187 PATCH add usb ID for asus wireless link This patch from Davide Cavalca adds a usb ID for an rtl8187L device. Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/rtl8187_dev.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 91fc2c765d90..4c7ff61a1a9c 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -649,6 +649,7 @@ config RTL8187 Trendnet TEW-424UB ASUS P5B Deluxe Toshiba Satellite Pro series of laptops + Asus Wireless Link Thanks to Realtek for their support! diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 177988efd660..461aa26164c2 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -31,6 +31,8 @@ MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); static struct usb_device_id rtl8187_table[] __devinitdata = { + /* Asus */ + {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, /* Realtek */ {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, From d2b690714cd7d328561bfb9bf941edd6a3316a85 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 27 Jul 2008 15:06:05 +0200 Subject: [PATCH 18/78] rt2x00: Fix access permissions on debugfs files Although most rt2x00 debugfs files don't contain information which could compromise network security, it is better to set the access permissions to root only. This will be required when HW crypto is implemented, because it could be possible to read the HW key from the registers. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 300cf061035f..6bee1d611bbf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -372,9 +372,6 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \ if (*offset) \ return 0; \ \ - if (!capable(CAP_NET_ADMIN)) \ - return -EPERM; \ - \ if (intf->offset_##__name >= debug->__name.word_count) \ return -EINVAL; \ \ @@ -454,7 +451,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name, data += sprintf(data, "compiled: %s %s\n", __DATE__, __TIME__); blob->size = strlen(blob->data); - return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob); + return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); } static struct dentry *rt2x00debug_create_file_chipset(const char *name, @@ -482,7 +479,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, data += sprintf(data, "rf length: %d\n", debug->rf.word_count); blob->size = strlen(blob->data); - return debugfs_create_blob(name, S_IRUGO, intf->driver_folder, blob); + return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); } void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) @@ -517,7 +514,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) if (IS_ERR(intf->chipset_entry)) goto exit; - intf->dev_flags = debugfs_create_file("dev_flags", S_IRUGO, + intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR, intf->driver_folder, intf, &rt2x00debug_fop_dev_flags); if (IS_ERR(intf->dev_flags)) @@ -532,7 +529,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) ({ \ (__intf)->__name##_off_entry = \ debugfs_create_u32(__stringify(__name) "_offset", \ - S_IRUGO | S_IWUSR, \ + S_IRUSR | S_IWUSR, \ (__intf)->register_folder, \ &(__intf)->offset_##__name); \ if (IS_ERR((__intf)->__name##_off_entry)) \ @@ -540,7 +537,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) \ (__intf)->__name##_val_entry = \ debugfs_create_file(__stringify(__name) "_value", \ - S_IRUGO | S_IWUSR, \ + S_IRUSR | S_IWUSR, \ (__intf)->register_folder, \ (__intf), &rt2x00debug_fop_##__name);\ if (IS_ERR((__intf)->__name##_val_entry)) \ @@ -560,7 +557,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) goto exit; intf->queue_frame_dump_entry = - debugfs_create_file("dump", S_IRUGO, intf->queue_folder, + debugfs_create_file("dump", S_IRUSR, intf->queue_folder, intf, &rt2x00debug_fop_queue_dump); if (IS_ERR(intf->queue_frame_dump_entry)) goto exit; @@ -569,7 +566,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) init_waitqueue_head(&intf->frame_dump_waitqueue); intf->queue_stats_entry = - debugfs_create_file("queue", S_IRUGO, intf->queue_folder, + debugfs_create_file("queue", S_IRUSR, intf->queue_folder, intf, &rt2x00debug_fop_queue_stats); return; From ada662f3eb6231ab27f5e6366d4e5c395d25edd3 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 27 Jul 2008 15:06:21 +0200 Subject: [PATCH 19/78] rt2x00: Fix partial antenna configuration The if-statement to determine the new TX/RX antenna configuration was incomplete. It lacks the general else-clause when the antenna wasn't changed. This is a correct event, since it can occur when only one of the antenna's has been changed or when the new configuration is being forced (like when the interface has just been added). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 3f89516e8332..d134c3be539a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -254,6 +254,8 @@ config: libconf.ant.rx = default_ant->rx; else if (active_ant->rx == ANTENNA_SW_DIVERSITY) libconf.ant.rx = ANTENNA_B; + else + libconf.ant.rx = active_ant->rx; if (conf->antenna_sel_tx) libconf.ant.tx = conf->antenna_sel_tx; @@ -261,6 +263,8 @@ config: libconf.ant.tx = default_ant->tx; else if (active_ant->tx == ANTENNA_SW_DIVERSITY) libconf.ant.tx = ANTENNA_B; + else + libconf.ant.tx = active_ant->tx; } if (flags & CONFIG_UPDATE_SLOT_TIME) { From e6d3e902088ac5da77b074f513e3cb80422ff471 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 27 Jul 2008 15:06:50 +0200 Subject: [PATCH 20/78] rt2x00: rt61pci needs another millisecond after firmware upload After the hardware has indicated the firmware upload has completed and the device is ready, we should wait another millisecond to make sure the device is really ready to continue. Without this timout, bringing the interface down and up again will fail due to incorrect register initialization. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index fbe2a652e014..087e90b328cd 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1003,6 +1003,11 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data, return -EBUSY; } + /* + * Hardware needs another millisecond before it is ready. + */ + msleep(1); + /* * Reset MAC and BBP registers. */ From 8d8acd46fb7e962ac04baef5a118d431fae6b0f6 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 28 Jul 2008 10:20:12 +0200 Subject: [PATCH 21/78] rt2x00: Fix VGC lower bound initialization When the EEPROM_BBPTUNE_VGC word is valid, we should override EEPROM_BBPTUNE_VGCLOWER field with the BBP value. And we should _not_ do that when EEPROM_BBPTUNE_R17 is valid. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 3078417b326b..c6f6eb6e17a1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1376,6 +1376,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word); + } else { + rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); + rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); } rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word); @@ -1384,9 +1387,6 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word); - } else { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); } rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word); From d4764b29b6e0f1608e397930677928e5a3f62bba Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 28 Jul 2008 10:21:16 +0200 Subject: [PATCH 22/78] rt2x00: Sequence counter should be protected in irqsave The sequence counter can be accessed in IRQ context, which means the lock protecting the counter should be irqsave. To prevent making the entire intf->lock irqsave without reason, create a new lock which only protects the sequence counter. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 6 ++++++ drivers/net/wireless/rt2x00/rt2x00mac.c | 1 + drivers/net/wireless/rt2x00/rt2x00queue.c | 5 +++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index db2dc976d831..8b10ea41b204 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -368,6 +368,12 @@ struct rt2x00_intf { #define DELAYED_CONFIG_ERP 0x00000002 #define DELAYED_LED_ASSOC 0x00000004 + /* + * Software sequence counter, this is only required + * for hardware which doesn't support hardware + * sequence counting. + */ + spinlock_t seqlock; u16 seqno; }; diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index c3ee4ecba792..bd422fd6a894 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -247,6 +247,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, rt2x00dev->intf_sta_count++; spin_lock_init(&intf->lock); + spin_lock_init(&intf->seqlock); intf->beacon = entry; if (conf->type == IEEE80211_IF_TYPE_AP) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 3b27f6aa860c..898cdd7f57d9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -128,6 +128,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, unsigned int data_length; unsigned int duration; unsigned int residual; + unsigned long irqflags; memset(txdesc, 0, sizeof(*txdesc)); @@ -213,14 +214,14 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, * sequence counter given by mac80211. */ if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - spin_lock(&intf->lock); + spin_lock_irqsave(&intf->seqlock, irqflags); if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) intf->seqno += 0x10; hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); hdr->seq_ctrl |= cpu_to_le16(intf->seqno); - spin_unlock(&intf->lock); + spin_unlock_irqrestore(&intf->seqlock, irqflags); __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); } From 3b72b01d3ab623c296df49f2d71d40a38bcfb4b3 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 29 Jul 2008 13:50:39 -0400 Subject: [PATCH 23/78] libertas: only enable rtap with mesh firmware Since only mesh-enabled firmware has the CMD_802_11_MONITOR_MODE on which the rtap functionality depends, only expose the rtap functionality when mesh is also available. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/main.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 14d5d61cec4c..bd32ac0b4e07 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -297,9 +297,7 @@ static ssize_t lbs_rtap_set(struct device *dev, lbs_add_rtap(priv); } priv->monitormode = monitor_mode; - } - - else { + } else { if (!priv->monitormode) return strlen(buf); priv->monitormode = 0; @@ -1242,8 +1240,6 @@ int lbs_start_card(struct lbs_private *priv) lbs_pr_err("cannot register ethX device\n"); goto done; } - if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) - lbs_pr_err("cannot register lbs_rtap attribute\n"); lbs_update_channel(priv); @@ -1275,6 +1271,13 @@ int lbs_start_card(struct lbs_private *priv) if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) lbs_pr_err("cannot register lbs_mesh attribute\n"); + + /* While rtap isn't related to mesh, only mesh-enabled + * firmware implements the rtap functionality via + * CMD_802_11_MONITOR_MODE. + */ + if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) + lbs_pr_err("cannot register lbs_rtap attribute\n"); } } @@ -1306,9 +1309,9 @@ void lbs_stop_card(struct lbs_private *priv) netif_carrier_off(priv->dev); lbs_debugfs_remove_one(priv); - device_remove_file(&dev->dev, &dev_attr_lbs_rtap); if (priv->mesh_tlv) { device_remove_file(&dev->dev, &dev_attr_lbs_mesh); + device_remove_file(&dev->dev, &dev_attr_lbs_rtap); } /* Flush pending command nodes */ From bf4634afd8bb72936d2d56425ec792ca1bfa92a2 Mon Sep 17 00:00:00 2001 From: Peter Chubb Date: Thu, 31 Jul 2008 10:56:34 +1000 Subject: [PATCH 24/78] rt2500pci: restoring missing line In kernel version 2.6.26-rc9 my wireless LAN card worked; but in the released 2.6.26, my RaLink rt2500 card wouldn't associate. Git-bisect led me to this patch: 61486e0f68d1f8966c09b734566a187d42d65c54 rt2x00: Remove ieee80211_tx_control argument from write_tx_desc() I believe that there is a problem with that patch --- it (inadvertantly) removes an extra line of code, that used to set the DATABYTE_COUNT field. This patch reinstates that line, and with it my card works again. Signed-off-by: Peter Chubb Acked-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index aa6dfb811c71..181a146b4768 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1220,6 +1220,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } From 7dcdd073bf78bb6958bbc12a1a47754a0f3c4721 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 31 Jul 2008 19:30:48 -0500 Subject: [PATCH 25/78] rtl8187: Fix lockups due to concurrent access to config routine Some users of the RTL8187B have experienced difficulties since commit 49292d56352a6ab90d04c3448dd8b6106dfef2d6 that introduced the power management wext hooks. This difficulty has not made much sense until it was realized that it was possible for mac80211 to make a call to the config routine while that routine was already being executed. On this device, it is necessary to loopback the TX when changing channels. Unless this is properly restored, the device will lockup. A mutex now protects the device state, and the private data in several places. The problem was found by Herton Ronaldo Krzesinski , who also suggested this type of fix. Signed-off-by: Larry Finger Acked-by: Herton Ronaldo Krzesinski Acked-by: Hin-Tak Leung Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187.h | 4 ++++ drivers/net/wireless/rtl8187_dev.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index 1b0d750f6623..5a9515c99960 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h @@ -94,6 +94,10 @@ struct rtl8187_priv { const struct rtl818x_rf_ops *rf; struct ieee80211_vif *vif; int mode; + /* The mutex protects the TX loopback state. + * Any attempt to set channels concurrently locks the device. + */ + struct mutex conf_mutex; /* rtl8187 specific */ struct ieee80211_channel channels[14]; diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 461aa26164c2..57376fb993ed 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -728,6 +728,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) if (ret) return ret; + mutex_lock(&priv->conf_mutex); if (priv->is_rtl8187b) { reg = RTL818X_RX_CONF_MGMT | RTL818X_RX_CONF_DATA | @@ -749,6 +750,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) (7 << 0 /* long retry limit */) | (7 << 21 /* MAX TX DMA */)); rtl8187_init_urbs(dev); + mutex_unlock(&priv->conf_mutex); return 0; } @@ -792,6 +794,7 @@ static int rtl8187_start(struct ieee80211_hw *dev) reg |= RTL818X_CMD_TX_ENABLE; reg |= RTL818X_CMD_RX_ENABLE; rtl818x_iowrite8(priv, &priv->map->CMD, reg); + mutex_unlock(&priv->conf_mutex); return 0; } @@ -803,6 +806,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) struct sk_buff *skb; u32 reg; + mutex_lock(&priv->conf_mutex); rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); reg = rtl818x_ioread8(priv, &priv->map->CMD); @@ -822,7 +826,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev) usb_kill_urb(info->urb); kfree_skb(skb); } - return; + mutex_unlock(&priv->conf_mutex); } static int rtl8187_add_interface(struct ieee80211_hw *dev, @@ -842,6 +846,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, return -EOPNOTSUPP; } + mutex_lock(&priv->conf_mutex); priv->vif = conf->vif; rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); @@ -850,6 +855,7 @@ static int rtl8187_add_interface(struct ieee80211_hw *dev, ((u8 *)conf->mac_addr)[i]); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + mutex_unlock(&priv->conf_mutex); return 0; } @@ -857,8 +863,10 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev, struct ieee80211_if_init_conf *conf) { struct rtl8187_priv *priv = dev->priv; + mutex_lock(&priv->conf_mutex); priv->mode = IEEE80211_IF_TYPE_MNTR; priv->vif = NULL; + mutex_unlock(&priv->conf_mutex); } static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) @@ -866,6 +874,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) struct rtl8187_priv *priv = dev->priv; u32 reg; + mutex_lock(&priv->conf_mutex); reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); /* Enable TX loopback on MAC level to avoid TX during channel * changes, as this has be seen to causes problems and the @@ -898,6 +907,7 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); + mutex_unlock(&priv->conf_mutex); return 0; } @@ -909,6 +919,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, int i; u8 reg; + mutex_lock(&priv->conf_mutex); for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); @@ -922,6 +933,7 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, rtl818x_iowrite8(priv, &priv->map->MSR, reg); } + mutex_unlock(&priv->conf_mutex); return 0; } @@ -1189,6 +1201,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, printk(KERN_ERR "rtl8187: Cannot register device\n"); goto err_free_dev; } + mutex_init(&priv->conf_mutex); printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n", wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), From fb55d887c5bd9054ec069534e1ef9eb8d9a983c6 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 31 Jul 2008 19:02:06 +0200 Subject: [PATCH 26/78] ipw2200 - Fix bad ipw_write8() macro ipw_write8() can't be used alone with a loop because of a wrong definition. CC [M] drivers/net/wireless/ipw2200.o drivers/net/wireless/ipw2200.c: In function 'ipw_ethtool_set_eeprom': drivers/net/wireless/ipw2200.c:10579: warning: array subscript is above array bounds drivers/net/wireless/ipw2200.c: In function 'ipw_load': drivers/net/wireless/ipw2200.c:2663: warning: array subscript is above array bounds Add missing do {} while (0) to fix them. Signed-off-by: Takashi Iwai Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 1acfbcd3703c..9509fd2a25f8 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -305,9 +305,10 @@ static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) #define _ipw_write8(ipw, ofs, val) writeb((val), (ipw)->hw_base + (ofs)) /* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ -#define ipw_write8(ipw, ofs, val) \ +#define ipw_write8(ipw, ofs, val) do { \ IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, __LINE__, (u32)(ofs), (u32)(val)); \ - _ipw_write8(ipw, ofs, val) + _ipw_write8(ipw, ofs, val); \ + } while (0) /* 16-bit direct write (low 4K) */ #define _ipw_write16(ipw, ofs, val) writew((val), (ipw)->hw_base + (ofs)) From 3d0f823953e6b5aa36fc098de2d27e15da220974 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 31 Jul 2008 19:03:10 +0200 Subject: [PATCH 27/78] prism54 - Use offsetof() Use the standard offsetof() macro to fix a compile warning below: CC [M] drivers/net/wireless/prism54/isl_ioctl.o drivers/net/wireless/prism54/isl_ioctl.c: In function 'prism2_ioctl_set_generic_element': drivers/net/wireless/prism54/isl_ioctl.c:2658: warning: cast from pointer to integer of different size Signed-off-by: Takashi Iwai Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 97fa14e0a479..3d75a7137d3c 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -2518,7 +2518,7 @@ enum { #define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 #define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((int) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) + offsetof(struct prism2_hostapd_param, u.generic_elem.data) /* Maximum length for algorithm names (-1 for nul termination) * used in ioctl() */ From 56decd3c5758b0d776c073f65f777beb7a05ac0a Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Fri, 1 Aug 2008 12:54:27 +0300 Subject: [PATCH 28/78] iwl3945: Fix statistics in monitor mode iwl3945_rx_reply_rx was sending packets too early to mac80211, before updating signal strength/quality. This resulted in garbage power levels. Signed-off-by: Maxim Levitsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index a51e0eaa1334..56a9361a847f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -710,10 +710,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, return; } - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); - return; - } + /* Convert 3945's rssi indicator to dBm */ rx_status.signal = rx_stats->rssi - IWL_RSSI_OFFSET; @@ -775,6 +772,11 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, priv->last_rx_noise = rx_status.noise; } + if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { + iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); + return; + } + switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) { case IEEE80211_FTYPE_MGMT: switch (le16_to_cpu(header->frame_control) & From 82f97b8d3cb3982ec97e081598c671fab2c321b0 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 2 Aug 2008 01:31:09 -0700 Subject: [PATCH 29/78] rt2x00: Fix compile warning rt2x00usb_vendor_request_large_buff is write-only, so it is safe to make the argument a const. Fixes compile warning: drivers/net/wireless/rt2x00/rt73usb.c: In function 'rt73usb_load_firmware': drivers/net/wireless/rt2x00/rt73usb.c:916: warning: passing argument 5 of 'rt2x00usb_vendor_request_large_buff' discards qualifiers from pointer target typ Signed-off-by: Ivo van Doorn Signed-off-by: David S. Miller --- drivers/net/wireless/rt2x00/rt2x00usb.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00usb.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 933e6cc9359d..8d76bb2e0312 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -124,7 +124,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, - const u16 offset, void *buffer, + const u16 offset, const void *buffer, const u16 buffer_length, const int timeout) { @@ -134,7 +134,7 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, mutex_lock(&rt2x00dev->usb_cache_mutex); - tb = buffer; + tb = (char *)buffer; off = offset; len = buffer_length; while (len && !status) { diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index ee3875f894aa..3b4a67417f95 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -185,7 +185,7 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, */ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, - const u16 offset, void *buffer, + const u16 offset, const void *buffer, const u16 buffer_length, const int timeout); From 5fb662297b8a4bdadd60371c34b760efca948ebc Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 2 Aug 2008 20:02:43 -0700 Subject: [PATCH 30/78] pkt_sched: Use qdisc_lock() on already sampled root qdisc. Based upon a bug report by Jeff Kirsher. Don't use qdisc_root_lock() in these cases as the root qdisc could have been changed, and we'd thus lock the wrong object. Tested by Emil S Tantilov who confirms that this seems to fix the problem. Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- net/sched/sch_generic.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index 69320a56a084..da7acacf02b5 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1796,7 +1796,7 @@ gso: skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_EGRESS); #endif if (q->enqueue) { - spinlock_t *root_lock = qdisc_root_lock(q); + spinlock_t *root_lock = qdisc_lock(q); spin_lock(root_lock); @@ -1995,7 +1995,7 @@ static void net_tx_action(struct softirq_action *h) smp_mb__before_clear_bit(); clear_bit(__QDISC_STATE_SCHED, &q->state); - root_lock = qdisc_root_lock(q); + root_lock = qdisc_lock(q); if (spin_trylock(root_lock)) { qdisc_run(q); spin_unlock(root_lock); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 9c9cd4d94890..7cf83b37459d 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -29,7 +29,7 @@ /* Main transmission queue. */ /* Modifications to data participating in scheduling must be protected with - * qdisc_root_lock(qdisc) spinlock. + * qdisc_lock(qdisc) spinlock. * * The idea is the following: * - enqueue, dequeue are serialized via qdisc root lock @@ -126,7 +126,7 @@ static inline int qdisc_restart(struct Qdisc *q) if (unlikely((skb = dequeue_skb(q)) == NULL)) return 0; - root_lock = qdisc_root_lock(q); + root_lock = qdisc_lock(q); /* And release qdisc */ spin_unlock(root_lock); @@ -507,7 +507,7 @@ errout: } EXPORT_SYMBOL(qdisc_create_dflt); -/* Under qdisc_root_lock(qdisc) and BH! */ +/* Under qdisc_lock(qdisc) and BH! */ void qdisc_reset(struct Qdisc *qdisc) { @@ -543,7 +543,7 @@ static void __qdisc_destroy(struct rcu_head *head) kfree((char *) qdisc - qdisc->padded); } -/* Under qdisc_root_lock(qdisc) and BH! */ +/* Under qdisc_lock(qdisc) and BH! */ void qdisc_destroy(struct Qdisc *qdisc) { @@ -659,7 +659,7 @@ static bool some_qdisc_is_running(struct net_device *dev, int lock) dev_queue = netdev_get_tx_queue(dev, i); q = dev_queue->qdisc; - root_lock = qdisc_root_lock(q); + root_lock = qdisc_lock(q); if (lock) spin_lock_bh(root_lock); @@ -735,7 +735,7 @@ static void shutdown_scheduler_queue(struct net_device *dev, struct Qdisc *qdisc_default = _qdisc_default; if (qdisc) { - spinlock_t *root_lock = qdisc_root_lock(qdisc); + spinlock_t *root_lock = qdisc_lock(qdisc); dev_queue->qdisc = qdisc_default; dev_queue->qdisc_sleeping = qdisc_default; From 35ed4e75989c4e84a44b25569bbf09b98f923880 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 2 Aug 2008 23:25:50 -0700 Subject: [PATCH 31/78] mac80211: Use queue_lock() in ieee80211_ht_agg_queue_remove(). qdisc_root_lock() is only %100 safe to use when the RTNL semaphore is held. Signed-off-by: David S. Miller --- net/mac80211/wme.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 28437f0001db..4310e2f65661 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -241,12 +241,14 @@ void ieee80211_ht_agg_queue_remove(struct ieee80211_local *local, } else { struct netdev_queue *txq; spinlock_t *root_lock; + struct Qdisc *q; txq = netdev_get_tx_queue(local->mdev, agg_queue); - root_lock = qdisc_root_lock(txq->qdisc); + q = rcu_dereference(txq->qdisc); + root_lock = qdisc_lock(q); spin_lock_bh(root_lock); - qdisc_reset(txq->qdisc); + qdisc_reset(q); spin_unlock_bh(root_lock); } } From 7e43f1128d4c4bd91786ca6abff45a91e88f9776 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 2 Aug 2008 23:27:37 -0700 Subject: [PATCH 32/78] pkt_sched: Make sure RTNL is held in qdisc_root_lock(). It is the only legal environment in which this can be used. Add some commentary explaining the situation. Signed-off-by: David S. Miller --- include/net/sch_generic.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index b5f40d7ef724..c5bb13065051 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -193,10 +193,22 @@ static inline struct Qdisc *qdisc_root(struct Qdisc *qdisc) return qdisc->dev_queue->qdisc; } +/* The qdisc root lock is a mechanism by which to top level + * of a qdisc tree can be locked from any qdisc node in the + * forest. This allows changing the configuration of some + * aspect of the qdisc tree while blocking out asynchronous + * qdisc access in the packet processing paths. + * + * It is only legal to do this when the root will not change + * on us. Otherwise we'll potentially lock the wrong qdisc + * root. This is enforced by holding the RTNL semaphore, which + * all users of this lock accessor must do. + */ static inline spinlock_t *qdisc_root_lock(struct Qdisc *qdisc) { struct Qdisc *root = qdisc_root(qdisc); + ASSERT_RTNL(); return qdisc_lock(root); } From bff69732c9947f821a64a8477f7dcaa9c30e6a69 Mon Sep 17 00:00:00 2001 From: Chris Larson Date: Sun, 3 Aug 2008 01:02:41 -0700 Subject: [PATCH 33/78] net: in the first call to neigh_seq_next, call neigh_get_first, not neigh_get_idx. neigh_seq_next won't be called both with *pos > 0 && v == SEQ_START_TOKEN, so there's no point calling neigh_get_idx when we're on the start token, just call neigh_get_first directly. Signed-off-by: Chris Larson Signed-off-by: David S. Miller --- net/core/neighbour.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f62c8af85d38..a57de755c8cc 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2385,7 +2385,7 @@ void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos) void *rc; if (v == SEQ_START_TOKEN) { - rc = neigh_get_idx(seq, pos); + rc = neigh_get_first(seq); goto out; } From 745e203164a9057e0de769ff4649e6e455daf753 Mon Sep 17 00:00:00 2001 From: Chris Larson Date: Sun, 3 Aug 2008 01:10:55 -0700 Subject: [PATCH 34/78] net: fix missing pneigh entries in the neighbor seq_file code When pneigh entries exist, but the user's read buffer isn't sufficient to hold them all, one of the pneigh entries will be missing from the results. In neigh_get_idx_any, the number of elements which neigh_get_idx encountered is not correctly subtracted from the position number before the call to pneigh_get_idx. neigh_get_idx reduces the position by 1 for each call to neigh_get_next, but it does not reduce it by one for the first element (neigh_get_first). The patch alters the neigh_get_idx and pneigh_get_idx functions to subtract one from pos, for the first element, when pos is non-zero. Signed-off-by: Chris Larson Signed-off-by: David S. Miller --- net/core/neighbour.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index a57de755c8cc..9d92e41826e7 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2281,6 +2281,7 @@ static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos) struct neighbour *n = neigh_get_first(seq); if (n) { + --(*pos); while (*pos) { n = neigh_get_next(seq, n, pos); if (!n) @@ -2341,6 +2342,7 @@ static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos) struct pneigh_entry *pn = pneigh_get_first(seq); if (pn) { + --(*pos); while (*pos) { pn = pneigh_get_next(seq, pn, pos); if (!pn) @@ -2354,10 +2356,11 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos) { struct neigh_seq_state *state = seq->private; void *rc; + loff_t idxpos = *pos; - rc = neigh_get_idx(seq, pos); + rc = neigh_get_idx(seq, &idxpos); if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY)) - rc = pneigh_get_idx(seq, pos); + rc = pneigh_get_idx(seq, &idxpos); return rc; } @@ -2366,7 +2369,6 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl __acquires(tbl->lock) { struct neigh_seq_state *state = seq->private; - loff_t pos_minus_one; state->tbl = tbl; state->bucket = 0; @@ -2374,8 +2376,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl read_lock_bh(&tbl->lock); - pos_minus_one = *pos - 1; - return *pos ? neigh_get_idx_any(seq, &pos_minus_one) : SEQ_START_TOKEN; + return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN; } EXPORT_SYMBOL(neigh_seq_start); From e5a4a72d4f88f4389e9340d383ca67031d1b8536 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 3 Aug 2008 01:23:10 -0700 Subject: [PATCH 35/78] net: use software GSO for SG+CSUM capable netdevices If a netdevice does not support hardware GSO, allowing the stack to use GSO anyway and then splitting the GSO skb into MSS-sized pieces as it is handed to the netdevice for transmitting is likely still a win as far as throughput and/or CPU usage are concerned, since it reduces the number of trips through the output path. This patch enables the use of GSO on any netdevice that supports SG. If a GSO skb is then sent to a netdevice that supports SG but does not support hardware GSO, net/core/dev.c:dev_hard_start_xmit() will take care of doing the necessary GSO segmentation in software. Signed-off-by: Lennert Buytenhek Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index da7acacf02b5..cbf80098980c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3988,6 +3988,10 @@ int register_netdevice(struct net_device *dev) } } + /* Enable software GSO if SG is supported. */ + if (dev->features & NETIF_F_SG) + dev->features |= NETIF_F_GSO; + netdev_initialize_kobject(dev); ret = netdev_register_kobject(dev); if (ret) From adf044c8778de98dae29c5ce9973b7e43964674f Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Sun, 3 Aug 2008 14:06:44 -0700 Subject: [PATCH 36/78] net: Add missing extra2 parameter for ip_default_ttl sysctl Commit 76e6ebfb40a2455c18234dcb0f9df37533215461 ("netns: add namespace parameter to rt_cache_flush") acceses the extra2 parameter of the ip_default_ttl ctl_table, but it is never set to a meaningful value. When e84f84f276473dcc673f360e8ff3203148bdf0e2 ("netns: place rt_genid into struct net") is applied, we'll oops in rt_cache_invalidate(). Set extra2 to init_net, to avoid that. Reported-by: Marcin Slusarz Signed-off-by: Sven Wegener Tested-by: Marcin Slusarz Acked-by: Denis V. Lunev Signed-off-by: David S. Miller --- net/ipv4/sysctl_net_ipv4.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 770d827f5ab8..e0689fd7b798 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -232,6 +232,7 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = &ipv4_doint_and_flush, .strategy = &ipv4_doint_and_flush_strategy, + .extra2 = &init_net, }, { .ctl_name = NET_IPV4_NO_PMTU_DISC, From 1730554f253deb65fe5112c54b2f898d5318a328 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 3 Aug 2008 18:13:44 -0700 Subject: [PATCH 37/78] ipv6: syncookies: free reqsk on xfrm_lookup error cookie_v6_check() did not call reqsk_free() if xfrm_lookup() fails, leaking the request sock. Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- net/ipv6/syncookies.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index a46badd1082d..ec394cf5a19b 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c @@ -199,10 +199,8 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) ireq6 = inet6_rsk(req); treq = tcp_rsk(req); - if (security_inet_conn_request(sk, skb, req)) { - reqsk_free(req); - goto out; - } + if (security_inet_conn_request(sk, skb, req)) + goto out_free; req->mss = mss; ireq->rmt_port = th->source; @@ -255,14 +253,13 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) fl.fl_ip_dport = inet_rsk(req)->rmt_port; fl.fl_ip_sport = inet_sk(sk)->sport; security_req_classify_flow(req, &fl); - if (ip6_dst_lookup(sk, &dst, &fl)) { - reqsk_free(req); - goto out; - } + if (ip6_dst_lookup(sk, &dst, &fl)) + goto out_free; + if (final_p) ipv6_addr_copy(&fl.fl6_dst, final_p); if ((xfrm_lookup(&dst, &fl, sk, 0)) < 0) - goto out; + goto out_free; } req->window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW); @@ -273,7 +270,10 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) ireq->rcv_wscale = rcv_wscale; ret = get_cookie_sock(sk, skb, req, dst); - -out: return ret; +out: + return ret; +out_free: + reqsk_free(req); + return NULL; } From cfb266c0ee0ea0b7bfa8189e3a3a80344dec6112 Mon Sep 17 00:00:00 2001 From: Yang Hongyang Date: Sun, 3 Aug 2008 18:16:15 -0700 Subject: [PATCH 38/78] ipv6: Fix the return value of Set Hop-by-Hop options header with NULL data pointer When Set Hop-by-Hop options header with NULL data pointer and optlen is not zero use setsockopt(), the kernel successfully return 0 instead of return error EINVAL or EFAULT. This patch fix the problem. Signed-off-by: Yang Hongyang Signed-off-by: David S. Miller --- net/ipv6/ipv6_sockglue.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index ea33b26512c2..741cfcd96f88 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -346,6 +346,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, */ if (optlen == 0) optval = NULL; + else if (optval == NULL) + goto e_inval; else if (optlen < sizeof(struct ipv6_opt_hdr) || optlen & 0x7 || optlen > 8 * 255) goto e_inval; From f880374c2fe37aad3fa62253a4bc125d7a933aad Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 3 Aug 2008 21:15:08 -0700 Subject: [PATCH 39/78] sctp: Drop ipfargok in sctp_xmit function The ipfragok flag controls whether the packet may be fragmented either on the local host on beyond. The latter is only valid on IPv4. In fact, we never want to do the latter even on IPv4 when PMTU is enabled. This is because even though we can't fragment packets within SCTP due to the prtocol's inherent faults, we can still fragment it at IP layer. By setting the DF bit we will improve the PMTU process. RFC 2960 only says that we SHOULD clear the DF bit in this case, so we're compliant even if we set the DF bit. In fact RFC 4960 no longer has this statement. Once we make this change, we only need to control the local fragmentation. There is already a bit in the skb which controls that, local_df. So this patch sets that instead of using the ipfragok argument. The only complication is that there isn't a struct sock object per transport, so for IPv4 we have to resort to changing the pmtudisc field for every packet. This should be safe though as the protocol is single-threaded. Note that after this patch we can remove ipfragok from the rest of the stack too. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 3 +-- net/sctp/ipv6.c | 8 +++++--- net/sctp/output.c | 6 ++---- net/sctp/protocol.c | 9 +++++++-- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 535a18f57a13..ab1c472ea753 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -524,8 +524,7 @@ static inline void sctp_ssn_skip(struct sctp_stream *stream, __u16 id, */ struct sctp_af { int (*sctp_xmit) (struct sk_buff *skb, - struct sctp_transport *, - int ipfragok); + struct sctp_transport *); int (*setsockopt) (struct sock *sk, int level, int optname, diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index a238d6834b33..483a01d0740a 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -195,8 +195,7 @@ out: } /* Based on tcp_v6_xmit() in tcp_ipv6.c. */ -static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, - int ipfragok) +static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) { struct sock *sk = skb->sk; struct ipv6_pinfo *np = inet6_sk(sk); @@ -231,7 +230,10 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport, SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); - return ip6_xmit(sk, skb, &fl, np->opt, ipfragok); + if (!(transport->param_flags & SPP_PMTUD_ENABLE)) + skb->local_df = 1; + + return ip6_xmit(sk, skb, &fl, np->opt, 0); } /* Returns the dst cache entry for the given source and destination ip diff --git a/net/sctp/output.c b/net/sctp/output.c index 45684646b1db..0dc4a7dfb234 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -586,10 +586,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n", nskb->len); - if (tp->param_flags & SPP_PMTUD_ENABLE) - (*tp->af_specific->sctp_xmit)(nskb, tp, packet->ipfragok); - else - (*tp->af_specific->sctp_xmit)(nskb, tp, 1); + nskb->local_df = packet->ipfragok; + (*tp->af_specific->sctp_xmit)(nskb, tp); out: packet->size = packet->overhead; diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index a6e0818bcff5..0b65354aaf64 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -862,16 +862,21 @@ static int sctp_inet_supported_addrs(const struct sctp_sock *opt, /* Wrapper routine that calls the ip transmit routine. */ static inline int sctp_v4_xmit(struct sk_buff *skb, - struct sctp_transport *transport, int ipfragok) + struct sctp_transport *transport) { + struct inet_sock *inet = inet_sk(skb->sk); + SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, " "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n", __func__, skb, skb->len, NIPQUAD(skb->rtable->rt_src), NIPQUAD(skb->rtable->rt_dst)); + inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? + IP_PMTUDISC_DO : IP_PMTUDISC_DONT; + SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); - return ip_queue_xmit(skb, ipfragok); + return ip_queue_xmit(skb, 0); } static struct sctp_af sctp_af_inet; From 283d07ac201ee9f8aa6dc6f7519436b48760baff Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 3 Aug 2008 21:15:59 -0700 Subject: [PATCH 40/78] ipv6: Do not drop packet if skb->local_df is set to true The old code will drop IPv6 packet if ipfragok is not set, since ipfragok is obsoleted, will be instead by used skb->local_df, so this check must be changed to skb->local_df. This patch fix this problem and not drop packet if skb->local_df is set to true. Signed-off-by: Wei Yongjun Acked-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv6/ip6_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index a027003d69a4..a4402de425d9 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -269,7 +269,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, skb->mark = sk->sk_mark; mtu = dst_mtu(dst); - if ((skb->len <= mtu) || ipfragok || skb_is_gso(skb)) { + if ((skb->len <= mtu) || skb->local_df || skb_is_gso(skb)) { IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_OUTREQUESTS); return NF_HOOK(PF_INET6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, From 6e583ce5242f32e925dcb198f7123256d0798370 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 3 Aug 2008 21:29:57 -0700 Subject: [PATCH 41/78] net: eliminate refcounting in backlog queue Avoid the overhead of atomic increment/decrement on each received packet. This helps performance of non-NAPI devices (like loopback). Use cleanup function to walk queue on each cpu and clean out any left over packets. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/core/dev.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/net/core/dev.c b/net/core/dev.c index cbf80098980c..fc6c9881eca8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1909,7 +1909,6 @@ int netif_rx(struct sk_buff *skb) if (queue->input_pkt_queue.qlen <= netdev_max_backlog) { if (queue->input_pkt_queue.qlen) { enqueue: - dev_hold(skb->dev); __skb_queue_tail(&queue->input_pkt_queue, skb); local_irq_restore(flags); return NET_RX_SUCCESS; @@ -2270,6 +2269,20 @@ out: return ret; } +/* Network device is going away, flush any packets still pending */ +static void flush_backlog(void *arg) +{ + struct net_device *dev = arg; + struct softnet_data *queue = &__get_cpu_var(softnet_data); + struct sk_buff *skb, *tmp; + + skb_queue_walk_safe(&queue->input_pkt_queue, skb, tmp) + if (skb->dev == dev) { + __skb_unlink(skb, &queue->input_pkt_queue); + kfree_skb(skb); + } +} + static int process_backlog(struct napi_struct *napi, int quota) { int work = 0; @@ -2279,7 +2292,6 @@ static int process_backlog(struct napi_struct *napi, int quota) napi->weight = weight_p; do { struct sk_buff *skb; - struct net_device *dev; local_irq_disable(); skb = __skb_dequeue(&queue->input_pkt_queue); @@ -2288,14 +2300,9 @@ static int process_backlog(struct napi_struct *napi, int quota) local_irq_enable(); break; } - local_irq_enable(); - dev = skb->dev; - netif_receive_skb(skb); - - dev_put(dev); } while (++work < quota && jiffies == start_time); return work; @@ -4169,6 +4176,8 @@ void netdev_run_todo(void) dev->reg_state = NETREG_UNREGISTERED; + on_each_cpu(flush_backlog, dev, 1); + netdev_wait_allrefs(dev); /* paranoia */ From ca579617d81baf5865498eb5fae58e453ee77c2c Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Fri, 18 Jul 2008 13:52:57 +0800 Subject: [PATCH 42/78] iwlwifi: add power save to 5000 HW This patch adds support for power save for 5000 HW. Signed-off-by: Mohamed Abbas Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 13 ------------- drivers/net/wireless/iwlwifi/iwl-5000.c | 1 + drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 3 ++- drivers/net/wireless/iwlwifi/iwl-power.c | 18 ++++++++++++------ drivers/net/wireless/iwlwifi/iwl-power.h | 2 +- 7 files changed, 18 insertions(+), 24 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index ba2df1ba32d2..ea23c7629575 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -875,18 +875,6 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) return 0; } -/* set card power command */ -static int iwl4965_set_power(struct iwl_priv *priv, - void *cmd) -{ - int ret = 0; - - ret = iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, - sizeof(struct iwl4965_powertable_cmd), - cmd, NULL); - return ret; -} - static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) { s32 sign = 1; @@ -2440,7 +2428,6 @@ static struct iwl_lib_ops iwl4965_lib = { .check_version = iwl4965_eeprom_check_version, .query_addr = iwlcore_eeprom_query_addr, }, - .set_power = iwl4965_set_power, .send_tx_power = iwl4965_send_tx_power, .update_chain_flags = iwl4965_update_chain_flags, .temperature = iwl4965_temperature_calib, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 878d6193b232..f91c54b5ff53 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1474,6 +1474,7 @@ static struct iwl_lib_ops iwl5000_lib = { .alive_notify = iwl5000_alive_notify, .send_tx_power = iwl5000_send_tx_power, .temperature = iwl5000_temperature, + .update_chain_flags = iwl4965_update_chain_flags, .apm_ops = { .init = iwl5000_apm_init, .reset = iwl5000_apm_reset, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index e9bb1de0ce3f..6f3555ffe527 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1993,7 +1993,7 @@ struct iwl4965_spectrum_notification { *****************************************************************************/ /** - * struct iwl4965_powertable_cmd - Power Table Command + * struct iwl_powertable_cmd - Power Table Command * @flags: See below: * * POWER_TABLE_CMD = 0x77 (command, has simple generic response) @@ -2027,7 +2027,7 @@ struct iwl4965_spectrum_notification { #define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le16(1 << 3) #define IWL_POWER_FAST_PD __constant_cpu_to_le16(1 << 4) -struct iwl4965_powertable_cmd { +struct iwl_powertable_cmd { __le16 flags; u8 keep_alive_seconds; u8 debug_flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index db66114f1e56..eaefa42f37c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -139,7 +139,6 @@ struct iwl_lib_ops { int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); } apm_ops; /* power */ - int (*set_power)(struct iwl_priv *priv, void *cmd); int (*send_tx_power) (struct iwl_priv *priv); void (*update_chain_flags)(struct iwl_priv *priv); void (*temperature) (struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 4d789e353e3a..010ed69e0e50 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -283,7 +283,7 @@ struct iwl_cmd { u32 val32; struct iwl4965_bt_cmd bt; struct iwl4965_rxon_time_cmd rxon_time; - struct iwl4965_powertable_cmd powertable; + struct iwl_powertable_cmd powertable; struct iwl_qosparam_cmd qosparam; struct iwl_tx_cmd tx; struct iwl4965_tx_beacon_cmd tx_beacon; @@ -590,6 +590,7 @@ extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, const u8 *dest, int left); extern void iwl4965_update_chain_flags(struct iwl_priv *priv); int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); +extern int iwl4965_set_power(struct iwl_priv *priv, void *cmd); extern const u8 iwl_bcast_addr[ETH_ALEN]; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 2e71803e09ba..e3c71beb01ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -112,6 +112,13 @@ static struct iwl_power_vec_entry range_2[IWL_POWER_AC] = { {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; +/* set card power command */ +static int iwl_set_power(struct iwl_priv *priv, void *cmd) +{ + return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD, + sizeof(struct iwl_powertable_cmd), + cmd, NULL); +} /* decide the right power level according to association status * and battery status */ @@ -162,7 +169,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv) if (ret != 0) return 0; else { - struct iwl4965_powertable_cmd *cmd; + struct iwl_powertable_cmd *cmd; IWL_DEBUG_POWER("adjust power command flags\n"); @@ -180,7 +187,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv) /* adjust power command according to dtim period and power level*/ static int iwl_update_power_command(struct iwl_priv *priv, - struct iwl4965_powertable_cmd *cmd, + struct iwl_powertable_cmd *cmd, u16 mode) { int ret = 0, i; @@ -204,7 +211,7 @@ static int iwl_update_power_command(struct iwl_priv *priv, range = &pow_data->pwr_range_2[0]; period = pow_data->dtim_period; - memcpy(cmd, &range[mode].cmd, sizeof(struct iwl4965_powertable_cmd)); + memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd)); if (period == 0) { period = 1; @@ -280,7 +287,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh) if (!iwl_is_rfkill(priv) && !setting->power_disabled && ((setting->power_mode != final_mode) || refresh)) { - struct iwl4965_powertable_cmd cmd; + struct iwl_powertable_cmd cmd; if (final_mode != IWL_POWER_MODE_CAM) set_bit(STATUS_POWER_PMI, &priv->status); @@ -291,8 +298,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh) if (final_mode == IWL_POWER_INDEX_5) cmd.flags |= IWL_POWER_FAST_PD; - if (priv->cfg->ops->lib->set_power) - ret = priv->cfg->ops->lib->set_power(priv, &cmd); + ret = iwl_set_power(priv, &cmd); if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index b066724a1c2b..801f6143a42c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -46,7 +46,7 @@ struct iwl_priv; /* Power management (not Tx power) structures */ struct iwl_power_vec_entry { - struct iwl4965_powertable_cmd cmd; + struct iwl_powertable_cmd cmd; u8 no_dtim; }; From 298df1f62aa69881528bf0f1c3c14395bc447846 Mon Sep 17 00:00:00 2001 From: Esti Kummer Date: Fri, 18 Jul 2008 13:52:58 +0800 Subject: [PATCH 43/78] iwlwifi: corrects power_level in sysfs This patch corrects power_level in sysfs. Signed-off-by: Esti Kummer Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-power.c | 27 +++++---- drivers/net/wireless/iwlwifi/iwl-power.h | 31 +++++++--- drivers/net/wireless/iwlwifi/iwl4965-base.c | 63 +++++++-------------- 3 files changed, 58 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index e3c71beb01ef..028e3053c0ca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -82,7 +82,7 @@ /* default power management (not Tx power) table values */ /* for tim 0-10 */ -static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = { {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, @@ -93,7 +93,7 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = { /* for tim = 3-10 */ -static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = { {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, @@ -103,7 +103,7 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = { }; /* for tim > 11 */ -static struct iwl_power_vec_entry range_2[IWL_POWER_AC] = { +static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = { {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, @@ -124,7 +124,7 @@ static int iwl_set_power(struct iwl_priv *priv, void *cmd) */ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) { - u16 mode = priv->power_data.user_power_setting; + u16 mode; switch (priv->power_data.user_power_setting) { case IWL_POWER_AUTO: @@ -136,12 +136,16 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv) else mode = IWL_POWER_ON_AC_DISASSOC; break; + /* FIXME: remove battery and ac from here */ case IWL_POWER_BATTERY: mode = IWL_POWER_INDEX_3; break; case IWL_POWER_AC: mode = IWL_POWER_MODE_CAM; break; + default: + mode = priv->power_data.user_power_setting; + break; } return mode; } @@ -151,7 +155,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv) { int ret = 0, i; struct iwl_power_mgr *pow_data; - int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC; + int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX; u16 pci_pm; IWL_DEBUG_POWER("Initialize power \n"); @@ -173,7 +177,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv) IWL_DEBUG_POWER("adjust power command flags\n"); - for (i = 0; i < IWL_POWER_AC; i++) { + for (i = 0; i < IWL_POWER_MAX; i++) { cmd = &pow_data->pwr_range_0[i].cmd; if (pci_pm & 0x1) @@ -265,17 +269,18 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh) * else user level */ switch (setting->system_power_setting) { - case IWL_POWER_AUTO: + case IWL_POWER_SYS_AUTO: final_mode = iwl_get_auto_power_mode(priv); break; - case IWL_POWER_BATTERY: + case IWL_POWER_SYS_BATTERY: final_mode = IWL_POWER_INDEX_3; break; - case IWL_POWER_AC: + case IWL_POWER_SYS_AC: final_mode = IWL_POWER_MODE_CAM; break; default: - final_mode = setting->system_power_setting; + final_mode = IWL_POWER_INDEX_3; + WARN_ON(1); } if (setting->critical_power_setting > final_mode) @@ -394,7 +399,7 @@ void iwl_power_initialize(struct iwl_priv *priv) iwl_power_init_handle(priv); priv->power_data.user_power_setting = IWL_POWER_AUTO; priv->power_data.power_disabled = 0; - priv->power_data.system_power_setting = IWL_POWER_AUTO; + priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO; priv->power_data.is_battery_active = 0; priv->power_data.power_disabled = 0; priv->power_data.critical_power_setting = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 801f6143a42c..abcbbf96a84e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -33,12 +33,25 @@ struct iwl_priv; -#define IWL_POWER_MODE_CAM 0x00 /* Continuously Aware Mode, always on */ -#define IWL_POWER_INDEX_3 0x03 -#define IWL_POWER_INDEX_5 0x05 -#define IWL_POWER_AC 0x06 -#define IWL_POWER_BATTERY 0x07 -#define IWL_POWER_AUTO 0x08 +enum { + IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */ + IWL_POWER_INDEX_1, + IWL_POWER_INDEX_2, + IWL_POWER_INDEX_3, + IWL_POWER_INDEX_4, + IWL_POWER_INDEX_5, + IWL_POWER_AUTO, + IWL_POWER_MAX = IWL_POWER_AUTO, + IWL_POWER_AC, + IWL_POWER_BATTERY, +}; + +enum { + IWL_POWER_SYS_AUTO, + IWL_POWER_SYS_AC, + IWL_POWER_SYS_BATTERY, +}; + #define IWL_POWER_LIMIT 0x08 #define IWL_POWER_MASK 0x0F #define IWL_POWER_ENABLED 0x10 @@ -52,9 +65,9 @@ struct iwl_power_vec_entry { struct iwl_power_mgr { spinlock_t lock; - struct iwl_power_vec_entry pwr_range_0[IWL_POWER_AC]; - struct iwl_power_vec_entry pwr_range_1[IWL_POWER_AC]; - struct iwl_power_vec_entry pwr_range_2[IWL_POWER_AC]; + struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX]; + struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX]; + struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX]; u32 dtim_period; /* final power level that used to calculate final power command */ u8 power_mode; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 71f5da3fe5c4..2001b09738ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3800,76 +3800,53 @@ static ssize_t store_power_level(struct device *d, const char *buf, size_t count) { struct iwl_priv *priv = dev_get_drvdata(d); - int rc; + int ret; int mode; mode = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); if (!iwl_is_ready(priv)) { - rc = -EAGAIN; + ret = -EAGAIN; goto out; } - rc = iwl_power_set_user_mode(priv, mode); - if (rc) { + ret = iwl_power_set_user_mode(priv, mode); + if (ret) { IWL_DEBUG_MAC80211("failed setting power mode.\n"); goto out; } - rc = count; + ret = count; out: mutex_unlock(&priv->mutex); - return rc; + return ret; } -#define MAX_WX_STRING 80 - -/* Values are in microsecond */ -static const s32 timeout_duration[] = { - 350000, - 250000, - 75000, - 37000, - 25000, -}; -static const s32 period_duration[] = { - 400000, - 700000, - 1000000, - 1000000, - 1000000 -}; - static ssize_t show_power_level(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = dev_get_drvdata(d); + int mode = priv->power_data.user_power_setting; + int system = priv->power_data.system_power_setting; int level = priv->power_data.power_mode; char *p = buf; - p += sprintf(p, "%d ", level); - switch (level) { - case IWL_POWER_MODE_CAM: - case IWL_POWER_AC: - p += sprintf(p, "(AC)"); + switch (system) { + case IWL_POWER_SYS_AUTO: + p += sprintf(p, "SYSTEM:auto"); break; - case IWL_POWER_BATTERY: - p += sprintf(p, "(BATTERY)"); + case IWL_POWER_SYS_AC: + p += sprintf(p, "SYSTEM:ac"); + break; + case IWL_POWER_SYS_BATTERY: + p += sprintf(p, "SYSTEM:battery"); break; - default: - p += sprintf(p, - "(Timeout %dms, Period %dms)", - timeout_duration[level - 1] / 1000, - period_duration[level - 1] / 1000); } -/* - if (!(priv->power_mode & IWL_POWER_ENABLED)) - p += sprintf(p, " OFF\n"); - else - p += sprintf(p, " \n"); -*/ - p += sprintf(p, " \n"); + + p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto"); + p += sprintf(p, "\tINDEX:%d", level); + p += sprintf(p, "\n"); return (p - buf + 1); } From 98f7dfd86cbbd377e2cbc293529681b914296f68 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 18 Jul 2008 13:52:59 +0800 Subject: [PATCH 44/78] mac80211: pass dtim_period to low level driver This patch adds the dtim_period in ieee80211_bss_conf, this allows the low level driver to know the dtim_period, and to plan power save accordingly. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Acked-by: Johannes Berg Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 13 +++++++++++++ include/net/mac80211.h | 4 +++- net/mac80211/ieee80211_i.h | 1 + net/mac80211/mlme.c | 11 +++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a1630ba0b87c..7f4df7c7659d 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -506,6 +506,19 @@ struct ieee80211_channel_sw_ie { u8 count; } __attribute__ ((packed)); +/** + * struct ieee80211_tim + * + * This structure refers to "Traffic Indication Map information element" + */ +struct ieee80211_tim_ie { + u8 dtim_count; + u8 dtim_period; + u8 bitmap_ctrl; + /* variable size: 1 - 251 bytes */ + u8 virtual_map[0]; +} __attribute__ ((packed)); + struct ieee80211_mgmt { __le16 frame_control; __le16 duration; diff --git a/include/net/mac80211.h b/include/net/mac80211.h index b52721008be8..9d99f2e0a204 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -177,9 +177,10 @@ enum ieee80211_bss_change { * @aid: association ID number, valid only when @assoc is true * @use_cts_prot: use CTS protection * @use_short_preamble: use 802.11b short preamble + * @dtim_period: num of beacons before the next DTIM, for PSM * @timestamp: beacon timestamp * @beacon_int: beacon interval - * @assoc_capability: capabbilities taken from assoc resp + * @assoc_capability: capabilities taken from assoc resp * @assoc_ht: association in HT mode * @ht_conf: ht capabilities * @ht_bss_conf: ht extended capabilities @@ -191,6 +192,7 @@ struct ieee80211_bss_conf { /* erp related data */ bool use_cts_prot; bool use_short_preamble; + u8 dtim_period; u16 beacon_int; u16 assoc_capability; u64 timestamp; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a2e200f9811e..ec59345af65b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -82,6 +82,7 @@ struct ieee80211_sta_bss { u8 bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; + u8 dtim_period; u16 capability; /* host byte order */ enum ieee80211_band band; int freq; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index acb04133a95d..591e6331c427 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -551,6 +551,7 @@ static void ieee80211_set_associated(struct net_device *dev, /* set timing information */ sdata->bss_conf.beacon_int = bss->beacon_int; sdata->bss_conf.timestamp = bss->timestamp; + sdata->bss_conf.dtim_period = bss->dtim_period; changed |= ieee80211_handle_bss_capability(sdata, bss); @@ -2688,6 +2689,16 @@ static void ieee80211_rx_bss_info(struct net_device *dev, bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); + if (elems->tim) { + struct ieee80211_tim_ie *tim_ie = + (struct ieee80211_tim_ie *)elems->tim; + bss->dtim_period = tim_ie->dtim_period; + } + + /* set default value for buggy APs */ + if (!elems->tim || bss->dtim_period == 0) + bss->dtim_period = 1; + bss->supp_rates_len = 0; if (elems->supp_rates) { clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; From ea95bba41e69c616bb1512cf59d22f33266b8568 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 18 Jul 2008 13:53:00 +0800 Subject: [PATCH 45/78] mac80211: make listen_interval be limited by low level driver This patch makes possible for a driver to specify maximal listen interval The possibility for user to configure listen interval is not implemented yet, currently the maximum provided by the driver or 1 is used. Mac80211 uses config handler to set listen interval for to the driver. Signed-off-by: Tomas Winkler Signed-off-by: Emmanuel Grumbach Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- include/net/mac80211.h | 9 ++++++++- net/mac80211/main.c | 5 +++++ net/mac80211/mlme.c | 6 ++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9d99f2e0a204..b397e4d984c7 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -432,6 +432,7 @@ enum ieee80211_conf_flags { * @radio_enabled: when zero, driver is required to switch off the radio. * TODO make a flag * @beacon_int: beacon interval (TODO make interface config) + * @listen_interval: listen interval in units of beacon interval * @flags: configuration flags defined above * @power_level: requested transmit power (in dBm) * @max_antenna_gain: maximum antenna gain (in dBi) @@ -446,6 +447,7 @@ struct ieee80211_conf { int radio_enabled; int beacon_int; + u16 listen_interval; u32 flags; int power_level; int max_antenna_gain; @@ -787,6 +789,9 @@ enum ieee80211_hw_flags { * @max_signal: Maximum value for signal (rssi) in RX information, used * only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB * + * @max_listen_interval: max listen interval in units of beacon interval + * that HW supports + * * @queues: number of available hardware transmit queues for * data packets. WMM/QoS requires at least four, these * queues need to have configurable access parameters. @@ -814,7 +819,9 @@ struct ieee80211_hw { unsigned int extra_tx_headroom; int channel_change_time; int vif_data_size; - u16 queues, ampdu_queues; + u16 queues; + u16 ampdu_queues; + u16 max_listen_interval; s8 max_signal; }; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index a4c5b90de769..0c02c471bca2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1689,6 +1689,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (local->hw.conf.beacon_int < 10) local->hw.conf.beacon_int = 100; + if (local->hw.max_listen_interval == 0) + local->hw.max_listen_interval = 1; + + local->hw.conf.listen_interval = local->hw.max_listen_interval; + local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC | IEEE80211_HW_SIGNAL_DB | IEEE80211_HW_SIGNAL_DBM) ? diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 591e6331c427..779affd8b8fe 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -774,7 +774,8 @@ static void ieee80211_send_assoc(struct net_device *dev, mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, IEEE80211_STYPE_REASSOC_REQ); mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1); + mgmt->u.reassoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid, ETH_ALEN); } else { @@ -782,7 +783,8 @@ static void ieee80211_send_assoc(struct net_device *dev, mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, IEEE80211_STYPE_ASSOC_REQ); mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); - mgmt->u.assoc_req.listen_interval = cpu_to_le16(1); + mgmt->u.reassoc_req.listen_interval = + cpu_to_le16(local->hw.conf.listen_interval); } /* SSID */ From d783b061077f92af55244aef1df8780b0f46b5af Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 18 Jul 2008 13:53:02 +0800 Subject: [PATCH 46/78] iwlwifi: move iwl4965_mac_ampdu_action to iwl4965-base.c This patch moves iwl4965_mac_ampdu_action to iwl4965-base.c. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 33 ------------------- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 35 ++++++++++++++++++++- 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index ea23c7629575..3cc6f00d96cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2067,39 +2067,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, return 0; } -int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 *ssn) -{ - struct iwl_priv *priv = hw->priv; - DECLARE_MAC_BUF(mac); - - IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", - print_mac(mac, addr), tid); - - if (!(priv->cfg->sku & IWL_SKU_N)) - return -EACCES; - - switch (action) { - case IEEE80211_AMPDU_RX_START: - IWL_DEBUG_HT("start Rx\n"); - return iwl_rx_agg_start(priv, addr, tid, *ssn); - case IEEE80211_AMPDU_RX_STOP: - IWL_DEBUG_HT("stop Rx\n"); - return iwl_rx_agg_stop(priv, addr, tid); - case IEEE80211_AMPDU_TX_START: - IWL_DEBUG_HT("start Tx\n"); - return iwl_tx_agg_start(priv, addr, tid, ssn); - case IEEE80211_AMPDU_TX_STOP: - IWL_DEBUG_HT("stop Tx\n"); - return iwl_tx_agg_stop(priv, addr, tid); - default: - IWL_DEBUG_HT("unknown\n"); - return -EINVAL; - break; - } - return 0; -} static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 010ed69e0e50..d2d4beab82a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -643,10 +643,6 @@ struct iwl_priv; * Forward declare iwl-4965.c functions for iwl-base.c */ extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv); - -int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 *ssn); int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 2001b09738ff..a34280f65c1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -65,7 +65,7 @@ * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk */ -#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link 4965AGN driver for Linux" +#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux" #ifdef CONFIG_IWLWIFI_DEBUG #define VD "d" @@ -3345,6 +3345,39 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, return 0; } +static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, + enum ieee80211_ampdu_mlme_action action, + const u8 *addr, u16 tid, u16 *ssn) +{ + struct iwl_priv *priv = hw->priv; + DECLARE_MAC_BUF(mac); + + IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n", + print_mac(mac, addr), tid); + + if (!(priv->cfg->sku & IWL_SKU_N)) + return -EACCES; + + switch (action) { + case IEEE80211_AMPDU_RX_START: + IWL_DEBUG_HT("start Rx\n"); + return iwl_rx_agg_start(priv, addr, tid, *ssn); + case IEEE80211_AMPDU_RX_STOP: + IWL_DEBUG_HT("stop Rx\n"); + return iwl_rx_agg_stop(priv, addr, tid); + case IEEE80211_AMPDU_TX_START: + IWL_DEBUG_HT("start Tx\n"); + return iwl_tx_agg_start(priv, addr, tid, ssn); + case IEEE80211_AMPDU_TX_STOP: + IWL_DEBUG_HT("stop Tx\n"); + return iwl_tx_agg_stop(priv, addr, tid); + default: + IWL_DEBUG_HT("unknown\n"); + return -EINVAL; + break; + } + return 0; +} static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats) { From 4bf64efd26f5610cde4fb7846e2f37bd1f62d3a9 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 18 Jul 2008 13:53:03 +0800 Subject: [PATCH 47/78] iwlwifi: move beacon handling to iwl4965-base.c This patch concentrates becaon handling in iwl4965-base.c. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 32 ----------------- drivers/net/wireless/iwlwifi/iwl-commands.h | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 39 ++++++++++++++++++--- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3cc6f00d96cd..9ae8525b9b60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1689,38 +1689,6 @@ static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv) return le32_to_cpu(s->rb_closed) & 0xFFF; } -unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, - struct iwl_frame *frame, u8 rate) -{ - struct iwl4965_tx_beacon_cmd *tx_beacon_cmd; - unsigned int frame_size; - - tx_beacon_cmd = &frame->u.beacon; - memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - - tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; - tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - frame_size = iwl4965_fill_beacon_frame(priv, - tx_beacon_cmd->frame, - iwl_bcast_addr, - sizeof(frame->u) - sizeof(*tx_beacon_cmd)); - - BUG_ON(frame_size > MAX_MPDU_SIZE); - tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); - - if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) - tx_beacon_cmd->tx.rate_n_flags = - iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); - else - tx_beacon_cmd->tx.rate_n_flags = - iwl_hw_set_rate_n_flags(rate, 0); - - tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | - TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK); - return (sizeof(*tx_beacon_cmd) + frame_size); -} - static int iwl4965_alloc_shared_mem(struct iwl_priv *priv) { priv->shared_virt = pci_alloc_consistent(priv->pci_dev, diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6f3555ffe527..cd6d668f4e00 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -2324,7 +2324,7 @@ struct iwl4965_beacon_notif { /* * REPLY_TX_BEACON = 0x91 (command, has simple generic response) */ -struct iwl4965_tx_beacon_cmd { +struct iwl_tx_beacon_cmd { struct iwl_tx_cmd tx; __le16 tim_idx; u8 tim_size; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d2d4beab82a0..ff16cca2b8c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -219,7 +219,7 @@ enum iwl_pwr_src { struct iwl_frame { union { struct ieee80211_hdr frame; - struct iwl4965_tx_beacon_cmd beacon; + struct iwl_tx_beacon_cmd beacon; u8 raw[IEEE80211_FRAME_LEN]; u8 cmd[360]; } u; @@ -286,7 +286,6 @@ struct iwl_cmd { struct iwl_powertable_cmd powertable; struct iwl_qosparam_cmd qosparam; struct iwl_tx_cmd tx; - struct iwl4965_tx_beacon_cmd tx_beacon; struct iwl4965_rxon_assoc_cmd rxon_assoc; struct iwl_rem_sta_cmd rm_sta; u8 *indirect; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index a34280f65c1a..94ce026ba602 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -444,11 +444,10 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) list_add(&frame->list, &priv->free_frames); } -unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - const u8 *dest, int left) +static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, + struct ieee80211_hdr *hdr, + const u8 *dest, int left) { - if (!iwl_is_associated(priv) || !priv->ibss_beacon || ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) && (priv->iw_mode != IEEE80211_IF_TYPE_AP))) @@ -487,6 +486,38 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv) return IWL_RATE_6M_PLCP; } +unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, + struct iwl_frame *frame, u8 rate) +{ + struct iwl_tx_beacon_cmd *tx_beacon_cmd; + unsigned int frame_size; + + tx_beacon_cmd = &frame->u.beacon; + memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); + + tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; + tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; + + frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, + iwl_bcast_addr, + sizeof(frame->u) - sizeof(*tx_beacon_cmd)); + + BUG_ON(frame_size > MAX_MPDU_SIZE); + tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); + + if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) + tx_beacon_cmd->tx.rate_n_flags = + iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); + else + tx_beacon_cmd->tx.rate_n_flags = + iwl_hw_set_rate_n_flags(rate, 0); + + tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | + TX_CMD_FLG_TSF_MSK | + TX_CMD_FLG_STA_RATE_MSK; + + return sizeof(*tx_beacon_cmd) + frame_size; +} static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) { struct iwl_frame *frame; From e2e3c57b271d74ed8fd4d378f1517525ef7e5921 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 18 Jul 2008 13:53:04 +0800 Subject: [PATCH 48/78] iwlwifi: move iwl4965_set_pwr_src to iwl4965-base.c This patch moves iwl4965_set_pwr_src to iwl4965-base.c. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 33 --------------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 31 +++++++++++++++++++ 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9ae8525b9b60..c0ba28fa6724 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -341,39 +341,6 @@ err: return -EINVAL; } -int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - ret = iwl_grab_nic_access(priv); - if (ret) { - spin_unlock_irqrestore(&priv->lock, flags); - return ret; - } - - if (src == IWL_PWR_SRC_VAUX) { - u32 val; - ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE, - &val); - - if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } - } else { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } - - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return ret; -} /* * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 94ce026ba602..ac02342d2281 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1262,6 +1262,37 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, wake_up_interruptible(&priv->wait_command_queue); } +int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + ret = iwl_grab_nic_access(priv); + if (ret) + goto err; + + if (src == IWL_PWR_SRC_VAUX) { + u32 val; + ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE, + &val); + + if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VAUX, + ~APMG_PS_CTRL_MSK_PWR_SRC); + } else { + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, + ~APMG_PS_CTRL_MSK_PWR_SRC); + } + + iwl_release_nic_access(priv); +err: + spin_unlock_irqrestore(&priv->lock, flags); + return ret; +} + /** * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks * From e227ceac8429ecd775c213838f0415700727b7b4 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 18 Jul 2008 13:53:05 +0800 Subject: [PATCH 49/78] iwlwifi: rename iwl-4695-rs to iwl-agn-rs This patch renames iwl-4965-rs to iwl-agn-rs as it provides rate scale capability for all AGN capable iwlwifi drivers. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- .../iwlwifi/{iwl-4965-rs.c => iwl-agn-rs.c} | 219 +++++++++--------- .../iwlwifi/{iwl-4965-rs.h => iwl-agn-rs.h} | 14 +- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 +- 7 files changed, 119 insertions(+), 128 deletions(-) rename drivers/net/wireless/iwlwifi/{iwl-4965-rs.c => iwl-agn-rs.c} (93%) rename drivers/net/wireless/iwlwifi/{iwl-4965-rs.h => iwl-agn-rs.h} (96%) diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 1f52b92f08b5..f50d2f8fd5c9 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -11,7 +11,7 @@ iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o +iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-agn-rs.o ifeq ($(CONFIG_IWL5000),y) iwl4965-objs += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c similarity index 93% rename from drivers/net/wireless/iwlwifi/iwl-4965-rs.c rename to drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 3ccb84aa5dbc..eee22c6dec73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -42,7 +42,7 @@ #include "iwl-core.h" #include "iwl-helpers.h" -#define RS_NAME "iwl-4965-rs" +#define RS_NAME "iwl-agn-rs" #define NUM_TRY_BEFORE_ANT_TOGGLE 1 #define IWL_NUMBER_TRY 1 @@ -77,9 +77,9 @@ static const u8 ant_toggle_lookup[] = { }; /** - * struct iwl4965_rate_scale_data -- tx success history for one rate + * struct iwl_rate_scale_data -- tx success history for one rate */ -struct iwl4965_rate_scale_data { +struct iwl_rate_scale_data { u64 data; /* bitmap of successful frames */ s32 success_counter; /* number of frames successful */ s32 success_ratio; /* per-cent * 128 */ @@ -89,12 +89,12 @@ struct iwl4965_rate_scale_data { }; /** - * struct iwl4965_scale_tbl_info -- tx params and success history for all rates + * struct iwl_scale_tbl_info -- tx params and success history for all rates * - * There are two of these in struct iwl4965_lq_sta, + * There are two of these in struct iwl_lq_sta, * one for "active", and one for "search". */ -struct iwl4965_scale_tbl_info { +struct iwl_scale_tbl_info { enum iwl_table_type lq_type; u8 ant_type; u8 is_SGI; /* 1 = short guard interval */ @@ -103,10 +103,10 @@ struct iwl4965_scale_tbl_info { u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ u32 current_rate; /* rate_n_flags, uCode API format */ - struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ + struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ }; -struct iwl4965_traffic_load { +struct iwl_traffic_load { unsigned long time_stamp; /* age of the oldest statistics */ u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time * slice */ @@ -118,11 +118,11 @@ struct iwl4965_traffic_load { }; /** - * struct iwl4965_lq_sta -- driver's rate scaling private structure + * struct iwl_lq_sta -- driver's rate scaling private structure * * Pointer to this gets passed back and forth between driver and mac80211. */ -struct iwl4965_lq_sta { +struct iwl_lq_sta { u8 active_tbl; /* index of active table, range 0-1 */ u8 enable_counter; /* indicates HT mode */ u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ @@ -153,8 +153,8 @@ struct iwl4965_lq_sta { u16 active_rate_basic; struct iwl_link_quality_cmd lq; - struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ - struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; + struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ + struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; u8 tx_agg_tid_en; #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *rs_sta_dbgfs_scale_table_file; @@ -170,16 +170,15 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, struct ieee80211_hdr *hdr, struct sta_info *sta); static void rs_fill_link_cmd(const struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, - u32 rate_n_flags); + struct iwl_lq_sta *lq_sta, u32 rate_n_flags); #ifdef CONFIG_MAC80211_DEBUGFS -static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, - u32 *rate_n_flags, int index); +static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, + u32 *rate_n_flags, int index); #else -static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, - u32 *rate_n_flags, int index) +static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, + u32 *rate_n_flags, int index) {} #endif @@ -234,7 +233,7 @@ static inline u8 rs_extract_rate(u32 rate_n_flags) return (u8)(rate_n_flags & 0xFF); } -static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) +static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) { window->data = 0; window->success_counter = 0; @@ -253,7 +252,7 @@ static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) * removes the old data from the statistics. All data that is older than * TID_MAX_TIME_DIFF, will be deleted. */ -static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time) +static void rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time) { /* The oldest age we want to keep */ u32 oldest_time = curr_time - TID_MAX_TIME_DIFF; @@ -274,13 +273,13 @@ static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time) * increment traffic load value for tid and also remove * any old values if passed the certain time period */ -static u8 rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, +static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, struct ieee80211_hdr *hdr) { u32 curr_time = jiffies_to_msecs(jiffies); u32 time_diff; s32 index; - struct iwl4965_traffic_load *tl = NULL; + struct iwl_traffic_load *tl = NULL; __le16 fc = hdr->frame_control; u8 tid; @@ -325,12 +324,12 @@ static u8 rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, /* get the traffic load value for tid */ -static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid) +static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) { u32 curr_time = jiffies_to_msecs(jiffies); u32 time_diff; s32 index; - struct iwl4965_traffic_load *tl = NULL; + struct iwl_traffic_load *tl = NULL; if (tid >= TID_MAX_LOAD_COUNT) return 0; @@ -354,8 +353,8 @@ static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid) } static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_data, u8 tid, - struct sta_info *sta) + struct iwl_lq_sta *lq_data, u8 tid, + struct sta_info *sta) { unsigned long state; DECLARE_MAC_BUF(mac); @@ -373,8 +372,8 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, } static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, - struct iwl4965_lq_sta *lq_data, - struct sta_info *sta) + struct iwl_lq_sta *lq_data, + struct sta_info *sta) { if ((tid < TID_MAX_LOAD_COUNT)) rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); @@ -397,11 +396,11 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags) * at this rate. window->data contains the bitmask of successful * packets. */ -static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, +static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, int scale_index, s32 tpt, int retries, int successes) { - struct iwl4965_rate_scale_data *window = NULL; + struct iwl_rate_scale_data *window = NULL; static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); s32 fail_count; @@ -473,7 +472,7 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, * Fill uCode API rate_n_flags field, based on "search" or "active" table. */ /* FIXME:RS:remove this function and put the flags statically in the table */ -static u32 rate_n_flags_from_tbl(struct iwl4965_scale_tbl_info *tbl, +static u32 rate_n_flags_from_tbl(struct iwl_scale_tbl_info *tbl, int index, u8 use_green) { u32 rate_n_flags = 0; @@ -530,7 +529,7 @@ static u32 rate_n_flags_from_tbl(struct iwl4965_scale_tbl_info *tbl, */ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, enum ieee80211_band band, - struct iwl4965_scale_tbl_info *tbl, + struct iwl_scale_tbl_info *tbl, int *rate_idx) { u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); @@ -591,7 +590,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, /* switch to another antenna/antennas and return 1 */ /* if no other valid antenna found, return 0 */ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, - struct iwl4965_scale_tbl_info *tbl) + struct iwl_scale_tbl_info *tbl) { u8 new_ant_type; @@ -638,9 +637,9 @@ static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf * basic available rates. * */ -static u16 rs_get_supported_rates(struct iwl4965_lq_sta *lq_sta, - struct ieee80211_hdr *hdr, - enum iwl_table_type rate_type) +static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, + struct ieee80211_hdr *hdr, + enum iwl_table_type rate_type) { if (hdr && is_multicast_ether_addr(hdr->addr1) && lq_sta->active_rate_basic) @@ -714,9 +713,9 @@ static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, return (high << 8) | low; } -static u32 rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta, - struct iwl4965_scale_tbl_info *tbl, u8 scale_index, - u8 ht_possible) +static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, + u8 scale_index, u8 ht_possible) { s32 low; u16 rate_mask; @@ -780,7 +779,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, int status; u8 retries; int rs_index, index = 0; - struct iwl4965_lq_sta *lq_sta; + struct iwl_lq_sta *lq_sta; struct iwl_link_quality_cmd *table; struct sta_info *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -788,11 +787,11 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = local_to_hw(local); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl4965_rate_scale_data *window = NULL; - struct iwl4965_rate_scale_data *search_win = NULL; + struct iwl_rate_scale_data *window = NULL; + struct iwl_rate_scale_data *search_win = NULL; u32 tx_rate; - struct iwl4965_scale_tbl_info tbl_type; - struct iwl4965_scale_tbl_info *curr_tbl, *search_tbl; + struct iwl_scale_tbl_info tbl_type; + struct iwl_scale_tbl_info *curr_tbl, *search_tbl; u8 active_index = 0; __le16 fc = hdr->frame_control; s32 tpt = 0; @@ -820,7 +819,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, goto out; - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && !lq_sta->ibss_sta_added) @@ -831,10 +830,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, curr_tbl = &(lq_sta->lq_info[active_index]); search_tbl = &(lq_sta->lq_info[(1 - active_index)]); - window = (struct iwl4965_rate_scale_data *) - &(curr_tbl->win[0]); - search_win = (struct iwl4965_rate_scale_data *) - &(search_tbl->win[0]); + window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); + search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); /* * Ignore this Tx frame response if its initial rate doesn't match @@ -983,7 +980,7 @@ out: * searching for a new mode. */ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, - struct iwl4965_lq_sta *lq_sta) + struct iwl_lq_sta *lq_sta) { IWL_DEBUG_RATE("we are staying in the same table\n"); lq_sta->stay_in_tbl = 1; /* only place this gets set */ @@ -1004,8 +1001,8 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, /* * Find correct throughput table for given mode of modulation */ -static void rs_set_expected_tpt_table(struct iwl4965_lq_sta *lq_sta, - struct iwl4965_scale_tbl_info *tbl) +static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl) { if (is_legacy(tbl->lq_type)) { if (!is_a_band(tbl->lq_type)) @@ -1050,12 +1047,12 @@ static void rs_set_expected_tpt_table(struct iwl4965_lq_sta *lq_sta, * bit rate will typically need to increase, but not if performance was bad. */ static s32 rs_get_best_rate(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, - struct iwl4965_scale_tbl_info *tbl, /* "search" */ + struct iwl_lq_sta *lq_sta, + struct iwl_scale_tbl_info *tbl, /* "search" */ u16 rate_mask, s8 index) { /* "active" values */ - struct iwl4965_scale_tbl_info *active_tbl = + struct iwl_scale_tbl_info *active_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); s32 active_sr = active_tbl->win[index].success_ratio; s32 active_tpt = active_tbl->expected_tpt[index]; @@ -1143,10 +1140,10 @@ static s32 rs_get_best_rate(struct iwl_priv *priv, * Set up search table for MIMO */ static int rs_switch_to_mimo2(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, - struct iwl4965_scale_tbl_info *tbl, int index) + struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; s32 rate; @@ -1210,10 +1207,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, * Set up search table for SISO */ static int rs_switch_to_siso(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, - struct iwl4965_scale_tbl_info *tbl, int index) + struct iwl_scale_tbl_info *tbl, int index) { u16 rate_mask; u8 is_green = lq_sta->is_green; @@ -1270,18 +1267,17 @@ static int rs_switch_to_siso(struct iwl_priv *priv, * Try to switch to new modulation mode from legacy */ static int rs_move_legacy_other(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, int index) { - struct iwl4965_scale_tbl_info *tbl = - &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl4965_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl4965_rate_scale_data *window = &(tbl->win[index]); - u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - - (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct iwl_rate_scale_data *window = &(tbl->win[index]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; int ret = 0; @@ -1360,19 +1356,17 @@ static int rs_move_legacy_other(struct iwl_priv *priv, * Try to switch to new modulation mode from SISO */ static int rs_move_siso_to_other(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, - int index) + struct sta_info *sta, int index) { u8 is_green = lq_sta->is_green; - struct iwl4965_scale_tbl_info *tbl = - &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl4965_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl4965_rate_scale_data *window = &(tbl->win[index]); - u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - - (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + struct iwl_rate_scale_data *window = &(tbl->win[index]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; u8 valid_tx_ant = priv->hw_params.valid_tx_ant; int ret; @@ -1455,18 +1449,16 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, * Try to switch to new modulation mode from MIMO */ static int rs_move_mimo_to_other(struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, + struct iwl_lq_sta *lq_sta, struct ieee80211_conf *conf, - struct sta_info *sta, - int index) + struct sta_info *sta, int index) { s8 is_green = lq_sta->is_green; - struct iwl4965_scale_tbl_info *tbl = - &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl4965_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - u32 sz = (sizeof(struct iwl4965_scale_tbl_info) - - (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT)); + struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); + struct iwl_scale_tbl_info *search_tbl = + &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); + u32 sz = (sizeof(struct iwl_scale_tbl_info) - + (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); u8 start_action = tbl->action; /*u8 valid_tx_ant = priv->hw_params.valid_tx_ant;*/ int ret; @@ -1552,9 +1544,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv, * 2) # times calling this function * 3) elapsed time in this mode (not used, for now) */ -static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta) +static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) { - struct iwl4965_scale_tbl_info *tbl; + struct iwl_scale_tbl_info *tbl; int i; int active_tbl; int flush_interval_passed = 0; @@ -1642,7 +1634,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, int high = IWL_RATE_INVALID; int index; int i; - struct iwl4965_rate_scale_data *window = NULL; + struct iwl_rate_scale_data *window = NULL; int current_tpt = IWL_INVALID_VALUE; int low_tpt = IWL_INVALID_VALUE; int high_tpt = IWL_INVALID_VALUE; @@ -1651,8 +1643,8 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, __le16 fc; u16 rate_mask; u8 update_lq = 0; - struct iwl4965_lq_sta *lq_sta; - struct iwl4965_scale_tbl_info *tbl, *tbl1; + struct iwl_lq_sta *lq_sta; + struct iwl_scale_tbl_info *tbl, *tbl1; u16 rate_scale_index_msk = 0; u32 rate; u8 is_green = 0; @@ -1675,7 +1667,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (!sta || !sta->rate_ctrl_priv) return; - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; tid = rs_tl_add_packet(lq_sta, hdr); @@ -2030,8 +2022,8 @@ static void rs_initialize_lq(struct iwl_priv *priv, struct ieee80211_conf *conf, struct sta_info *sta) { - struct iwl4965_lq_sta *lq_sta; - struct iwl4965_scale_tbl_info *tbl; + struct iwl_lq_sta *lq_sta; + struct iwl_scale_tbl_info *tbl; int rate_idx; int i; u32 rate; @@ -2042,7 +2034,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, if (!sta || !sta->rate_ctrl_priv) goto out; - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; i = sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && @@ -2096,7 +2088,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, struct sta_info *sta; __le16 fc; struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct iwl4965_lq_sta *lq_sta; + struct iwl_lq_sta *lq_sta; IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); @@ -2113,7 +2105,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, goto out; } - lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; + lq_sta = (struct iwl_lq_sta *)sta->rate_ctrl_priv; i = sta->last_txrate_idx; if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && @@ -2149,14 +2141,14 @@ out: static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) { - struct iwl4965_lq_sta *lq_sta; + struct iwl_lq_sta *lq_sta; struct iwl_priv *priv; int i, j; priv = (struct iwl_priv *)priv_rate; IWL_DEBUG_RATE("create station rate scale window\n"); - lq_sta = kzalloc(sizeof(struct iwl4965_lq_sta), gfp); + lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); if (lq_sta == NULL) return NULL; @@ -2178,7 +2170,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, struct ieee80211_conf *conf = &local->hw.conf; struct ieee80211_supported_band *sband; struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct iwl4965_lq_sta *lq_sta = priv_sta; + struct iwl_lq_sta *lq_sta = priv_sta; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; @@ -2271,10 +2263,9 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, } static void rs_fill_link_cmd(const struct iwl_priv *priv, - struct iwl4965_lq_sta *lq_sta, - u32 new_rate) + struct iwl_lq_sta *lq_sta, u32 new_rate) { - struct iwl4965_scale_tbl_info tbl_type; + struct iwl_scale_tbl_info tbl_type; int index = 0; int rate_idx; int repeat_rate = 0; @@ -2413,7 +2404,7 @@ static void rs_clear(void *priv_rate) static void rs_free_sta(void *priv_rate, void *priv_sta) { - struct iwl4965_lq_sta *lq_sta = priv_sta; + struct iwl_lq_sta *lq_sta = priv_sta; struct iwl_priv *priv; priv = (struct iwl_priv *)priv_rate; @@ -2429,8 +2420,8 @@ static int open_file_generic(struct inode *inode, struct file *file) file->private_data = inode->i_private; return 0; } -static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, - u32 *rate_n_flags, int index) +static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, + u32 *rate_n_flags, int index) { struct iwl_priv *priv; @@ -2453,7 +2444,7 @@ static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) { - struct iwl4965_lq_sta *lq_sta = file->private_data; + struct iwl_lq_sta *lq_sta = file->private_data; struct iwl_priv *priv; char buf[64]; int buf_size; @@ -2493,7 +2484,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, int desc = 0; int i = 0; - struct iwl4965_lq_sta *lq_sta = file->private_data; + struct iwl_lq_sta *lq_sta = file->private_data; desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", @@ -2541,7 +2532,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, int desc = 0; int i, j; - struct iwl4965_lq_sta *lq_sta = file->private_data; + struct iwl_lq_sta *lq_sta = file->private_data; for (i = 0; i < LQ_SIZE; i++) { desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n" "rate=0x%X\n", @@ -2570,7 +2561,7 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = { static void rs_add_debugfs(void *priv, void *priv_sta, struct dentry *dir) { - struct iwl4965_lq_sta *lq_sta = priv_sta; + struct iwl_lq_sta *lq_sta = priv_sta; lq_sta->rs_sta_dbgfs_scale_table_file = debugfs_create_file("rate_scale_table", 0600, dir, lq_sta, &rs_sta_dbgfs_scale_table_ops); @@ -2585,7 +2576,7 @@ static void rs_add_debugfs(void *priv, void *priv_sta, static void rs_remove_debugfs(void *priv, void *priv_sta) { - struct iwl4965_lq_sta *lq_sta = priv_sta; + struct iwl_lq_sta *lq_sta = priv_sta; debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); @@ -2613,7 +2604,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) { struct ieee80211_local *local = hw_to_local(hw); struct iwl_priv *priv = hw->priv; - struct iwl4965_lq_sta *lq_sta; + struct iwl_lq_sta *lq_sta; struct sta_info *sta; int cnt = 0, i; u32 samples = 0, success = 0, good = 0; @@ -2701,12 +2692,12 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) return cnt; } -int iwl4965_rate_control_register(void) +int iwlagn_rate_control_register(void) { return ieee80211_rate_control_register(&rs_ops); } -void iwl4965_rate_control_unregister(void) +void iwlagn_rate_control_unregister(void) { ieee80211_rate_control_unregister(&rs_ops); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h similarity index 96% rename from drivers/net/wireless/iwlwifi/iwl-4965-rs.h rename to drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 9b9972885aa5..3b06c9da77e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -24,8 +24,8 @@ * *****************************************************************************/ -#ifndef __iwl_4965_rs_h__ -#define __iwl_4965_rs_h__ +#ifndef __iwl_agn_rs_h__ +#define __iwl_agn_rs_h__ #include "iwl-dev.h" @@ -88,7 +88,7 @@ enum { #define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX) #define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) -/* 4965 uCode API values for legacy bit rates, both OFDM and CCK */ +/* uCode API values for legacy bit rates, both OFDM and CCK */ enum { IWL_RATE_6M_PLCP = 13, IWL_RATE_9M_PLCP = 15, @@ -107,7 +107,7 @@ enum { /*FIXME:RS:add IWL_RATE_LEGACY_INVM_PLCP = 0,*/ }; -/* 4965 uCode API values for OFDM high-throughput (HT) bit rates */ +/* uCode API values for OFDM high-throughput (HT) bit rates */ enum { IWL_RATE_SISO_6M_PLCP = 0, IWL_RATE_SISO_12M_PLCP = 1, @@ -305,7 +305,7 @@ extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); * ieee80211_register_hw * */ -extern int iwl4965_rate_control_register(void); +extern int iwlagn_rate_control_register(void); /** * iwl4965_rate_control_unregister - Unregister the rate control callbacks @@ -313,6 +313,6 @@ extern int iwl4965_rate_control_register(void); * This should be called after calling ieee80211_unregister_hw, but before * the driver is unloaded. */ -extern void iwl4965_rate_control_unregister(void); +extern void iwlagn_rate_control_unregister(void); -#endif +#endif /* __iwl_agn__rs__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e3427c205ccf..60d443e77c38 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -815,7 +815,7 @@ int iwl_setup_mac(struct iwl_priv *priv) { int ret; struct ieee80211_hw *hw = priv->hw; - hw->rate_control_algorithm = "iwl-4965-rs"; + hw->rate_control_algorithm = "iwl-agn-rs"; /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM | diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ff16cca2b8c7..7ac56b1350b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -45,6 +45,7 @@ #include "iwl-debug.h" #include "iwl-led.h" #include "iwl-power.h" +#include "iwl-agn-rs.h" /* configuration for the iwl4965 */ extern struct iwl_cfg iwl4965_agn_cfg; @@ -191,7 +192,6 @@ struct iwl4965_clip_group { const s8 clip_powers[IWL_MAX_RATES]; }; -#include "iwl-4965-rs.h" #define IWL_TX_FIFO_AC0 0 #define IWL_TX_FIFO_AC1 1 diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 6d1467d0bd9d..10af82170f6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -839,7 +839,7 @@ EXPORT_SYMBOL(iwl_send_lq_cmd); * for automatic fallback during transmission. * * NOTE: This sets up a default set of values. These will be replaced later - * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of + * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of * rc80211_simple. * * NOTE: Run REPLY_ADD_STA command to set up station table entry, before diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index ac02342d2281..dcd11e9bd86c 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4503,7 +4503,7 @@ static int __init iwl4965_init(void) printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); - ret = iwl4965_rate_control_register(); + ret = iwlagn_rate_control_register(); if (ret) { IWL_ERROR("Unable to register rate control algorithm: %d\n", ret); return ret; @@ -4518,14 +4518,14 @@ static int __init iwl4965_init(void) return ret; error_register: - iwl4965_rate_control_unregister(); + iwlagn_rate_control_unregister(); return ret; } static void __exit iwl4965_exit(void) { pci_unregister_driver(&iwl_driver); - iwl4965_rate_control_unregister(); + iwlagn_rate_control_unregister(); } module_exit(iwl4965_exit); From 3ce84b9f2f495f59c4a4e68d814c348eaa497f65 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 18 Jul 2008 13:53:06 +0800 Subject: [PATCH 50/78] iwlwifi: kill iwl4965_fill_rs_info iwl4965_fill_rs_info was used in sysfs. This info is already present in iwl-agn-rs debugfs. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 92 --------------------- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 9 -- drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 --- 3 files changed, 111 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index eee22c6dec73..0e8100e70620 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2600,98 +2600,6 @@ static struct rate_control_ops rs_ops = { #endif }; -int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) -{ - struct ieee80211_local *local = hw_to_local(hw); - struct iwl_priv *priv = hw->priv; - struct iwl_lq_sta *lq_sta; - struct sta_info *sta; - int cnt = 0, i; - u32 samples = 0, success = 0, good = 0; - unsigned long now = jiffies; - u32 max_time = 0; - u8 lq_type, antenna; - - rcu_read_lock(); - - sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); - if (!sta || !sta->rate_ctrl_priv) { - if (sta) - IWL_DEBUG_RATE("leave - no private rate data!\n"); - else - IWL_DEBUG_RATE("leave - no station!\n"); - rcu_read_unlock(); - return sprintf(buf, "station %d not found\n", sta_id); - } - - lq_sta = (void *)sta->rate_ctrl_priv; - - lq_type = lq_sta->lq_info[lq_sta->active_tbl].lq_type; - antenna = lq_sta->lq_info[lq_sta->active_tbl].ant_type; - - if (is_legacy(lq_type)) - i = IWL_RATE_54M_INDEX; - else - i = IWL_RATE_60M_INDEX; - while (1) { - u64 mask; - int j; - int active = lq_sta->active_tbl; - - cnt += - sprintf(&buf[cnt], " %2dMbs: ", iwl_rates[i].ieee / 2); - - mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1)); - for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1) - buf[cnt++] = - (lq_sta->lq_info[active].win[i].data & mask) - ? '1' : '0'; - - samples += lq_sta->lq_info[active].win[i].counter; - good += lq_sta->lq_info[active].win[i].success_counter; - success += lq_sta->lq_info[active].win[i].success_counter * - iwl_rates[i].ieee; - - if (lq_sta->lq_info[active].win[i].stamp) { - int delta = - jiffies_to_msecs(now - - lq_sta->lq_info[active].win[i].stamp); - - if (delta > max_time) - max_time = delta; - - cnt += sprintf(&buf[cnt], "%5dms\n", delta); - } else - buf[cnt++] = '\n'; - - j = iwl4965_get_prev_ieee_rate(i); - if (j == i) - break; - i = j; - } - - /* - * Display the average rate of all samples taken. - * NOTE: We multiply # of samples by 2 since the IEEE measurement - * added from iwl_rates is actually 2X the rate. - */ - if (samples) - cnt += sprintf(&buf[cnt], - "\nAverage rate is %3d.%02dMbs over last %4dms\n" - "%3d%% success (%d good packets over %d tries)\n", - success / (2 * samples), (success * 5 / samples) % 10, - max_time, good * 100 / samples, good, samples); - else - cnt += sprintf(&buf[cnt], "\nAverage rate: 0Mbs\n"); - - cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d " - "active_search %d rate index %d\n", lq_type, antenna, - lq_sta->search_better_tbl, sta->last_txrate_idx); - - rcu_read_unlock(); - return cnt; -} - int iwlagn_rate_control_register(void) { return ieee80211_rate_control_register(&rs_ops); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 3b06c9da77e3..84d4d1e33755 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -286,15 +286,6 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index) return rate; } -/** - * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation - * - * NOTE: This is provided as a quick mechanism for a user to visualize - * the performance of the rate control algorithm and is not meant to be - * parsed software. - */ -extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id); - /** * iwl4965_rate_control_register - Register the rate control algorithm callbacks * diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index dcd11e9bd86c..9db6aac02185 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3687,15 +3687,6 @@ static ssize_t show_temperature(struct device *d, static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); -static ssize_t show_rs_window(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct iwl_priv *priv = d->driver_data; - return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID); -} -static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); - static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { @@ -4118,7 +4109,6 @@ static struct attribute *iwl4965_sysfs_entries[] = { #endif &dev_attr_power_level.attr, &dev_attr_retry_rate.attr, - &dev_attr_rs_window.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, From c785d1d5018b93878a9280b0c04df96682cc6eff Mon Sep 17 00:00:00 2001 From: Esti Kummer Date: Fri, 18 Jul 2008 13:53:07 +0800 Subject: [PATCH 51/78] iwlwifi: set led register in disassociation This patch sets the led register in disassociation flow according to rf-kill state : off - in case of rf_kill, on - otherwise. Signed-off-by: Esti Kummer Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-led.c | 40 +++++++++++++++----------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 61250e6a7d1b..0a01f091c516 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -161,11 +161,31 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id) /* Set led register off */ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) { - IWL_DEBUG_LED("radio off\n"); + IWL_DEBUG_LED("LED Reg off\n"); iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); return 0; } +/* + * Set led register in case of disassociation according to rfkill state + */ +static int iwl_led_associate(struct iwl_priv *priv, int led_id) +{ + IWL_DEBUG_LED("Associated\n"); + priv->allow_blinking = 1; + return iwl4965_led_on_reg(priv, led_id); +} +static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) +{ + priv->allow_blinking = 0; + if (iwl_is_rfkill(priv)) + iwl4965_led_off_reg(priv, led_id); + else + iwl4965_led_on_reg(priv, led_id); + + return 0; +} + /* * brightness call back function for Tx/Rx LED */ @@ -199,16 +219,10 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, led_type_str[led->type], brightness); switch (brightness) { case LED_FULL: - if (led->type == IWL_LED_TRG_ASSOC) - priv->allow_blinking = 1; - if (led->led_on) led->led_on(priv, IWL_LED_LINK); break; case LED_OFF: - if (led->type == IWL_LED_TRG_ASSOC) - priv->allow_blinking = 0; - if (led->led_off) led->led_off(priv, IWL_LED_LINK); break; @@ -284,12 +298,6 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) return i; } -static inline int is_rf_kill(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); -} - /* * this function called from handler. Since setting Led command can * happen very frequent we postpone led command to be called from @@ -303,7 +311,7 @@ void iwl_leds_background(struct iwl_priv *priv) priv->last_blink_time = 0; return; } - if (is_rf_kill(priv)) { + if (iwl_is_rfkill(priv)) { priv->last_blink_time = 0; return; } @@ -366,8 +374,8 @@ int iwl_leds_register(struct iwl_priv *priv) IWL_LED_TRG_ASSOC, 0, name, trigger); /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate; priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; if (ret) From 4aa41f12aa4f08a10b0b07ed334faa3638ba8e9c Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Fri, 18 Jul 2008 13:53:09 +0800 Subject: [PATCH 52/78] iwlwifi: bug fix in AGG flow - cast const to ULL This patch fixes a bug in AGG flow: u64 bitmap = 0; bitmap |= 1 << 32 results to be 0xffffffff80000000. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-tx.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index c0ba28fa6724..f356f4f0944b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2130,9 +2130,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, bitmap = bitmap << sh; sh = 0; } - bitmap |= (1 << sh); - IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n", - start, (u32)(bitmap & 0xFFFFFFFF)); + bitmap |= 1ULL << sh; + IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", + start, (unsigned long long)bitmap); } agg->bitmap = bitmap; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f91c54b5ff53..076d3560302b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1228,9 +1228,9 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, bitmap = bitmap << sh; sh = 0; } - bitmap |= (1 << sh); - IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n", - start, (u32)(bitmap & 0xFFFFFFFF)); + bitmap |= 1ULL << sh; + IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n", + start, (unsigned long long)bitmap); } agg->bitmap = bitmap; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 0182e4da8e35..39f19ebee973 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1391,7 +1391,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, /* For each frame attempted in aggregation, * update driver's record of tx frame's status. */ for (i = 0; i < agg->frame_count ; i++) { - ack = bitmap & (1 << i); + ack = bitmap & (1ULL << i); successes += !!ack; IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff, From e170402e5459c12ed8f5bfaa11e6550eba09e57a Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Sat, 19 Jul 2008 04:04:18 +0300 Subject: [PATCH 53/78] iwlwifi: RS small compile warnings without CONFIG_IWLWIFI_DEBUG iwl-agn-rs.c: In function 'rs_clear': iwl-agn-rs.c:2405: warning: unused variable 'priv Signed-off-by: Denis V. Lunev Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 0e8100e70620..b498b58d81fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -2393,6 +2393,7 @@ static void rs_free(void *priv_rate) static void rs_clear(void *priv_rate) { +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl_priv *priv = (struct iwl_priv *) priv_rate; IWL_DEBUG_RATE("enter\n"); @@ -2400,6 +2401,7 @@ static void rs_clear(void *priv_rate) /* TODO - add rate scale state reset */ IWL_DEBUG_RATE("leave\n"); +#endif /* CONFIG_IWLWIFI_DEBUG */ } static void rs_free_sta(void *priv_rate, void *priv_sta) From b5d7be5e665f29274cfe6645b661acb38cb1d19b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sat, 19 Jul 2008 04:41:24 +0300 Subject: [PATCH 54/78] iwlwifi: use dtim_period from association, and set listen_interval This patch uses dtim_period from association, and sets the listen_interval. Signed-off-by: Tomas Winkler Signed-off-by: Emmanuel Grumbach Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-commands.h | 3 +-- drivers/net/wireless/iwlwifi/iwl-core.c | 1 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index cd6d668f4e00..5e57f3ae2ea6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -666,8 +666,7 @@ struct iwl4965_rxon_assoc_cmd { __le16 reserved; } __attribute__ ((packed)); - - +#define IWL_CONN_MAX_LISTEN_INTERVAL 10 /* * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 60d443e77c38..96beacf703a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -827,6 +827,7 @@ int iwl_setup_mac(struct iwl_priv *priv) hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues; hw->conf.beacon_int = 100; + hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 9db6aac02185..f71b3f3f81ba 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -639,7 +639,6 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force) } #define MAX_UCODE_BEACON_INTERVAL 4096 -#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA) static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val) { @@ -669,7 +668,7 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv) priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp & 0xFFFFFFFF); - priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL; + priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); tsf = priv->timestamp; @@ -2835,6 +2834,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); + /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not * support ht */ @@ -3164,6 +3164,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, if (bss_conf->assoc) { priv->assoc_id = bss_conf->aid; priv->beacon_int = bss_conf->beacon_int; + priv->power_data.dtim_period = bss_conf->dtim_period; priv->timestamp = bss_conf->timestamp; priv->assoc_capability = bss_conf->assoc_capability; priv->next_scan_jiffies = jiffies + From 80693ceb78b08baa3b66a900d9225b2cf9c6f0ed Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Sat, 19 Jul 2008 23:31:17 +0100 Subject: [PATCH 55/78] mac80211: automatic IBSS channel selection When joining an ad-hoc network, the user is currently required to specify the channel. The network will not be joined otherwise, unless it happens to be sitting on the currently active channel. This patch implements automatic channel selection when the user has not locked the interface onto a specific channel. Signed-off-by: Daniel Drake Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 779affd8b8fe..5358420d8796 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3663,11 +3663,21 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, "%s\n", print_mac(mac, bssid), print_mac(mac2, ifsta->bssid)); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ - if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 && - (bss = ieee80211_rx_bss_get(dev, bssid, - local->hw.conf.channel->center_freq, - ifsta->ssid, ifsta->ssid_len))) { + + if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { int ret; + int search_freq; + + if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) + search_freq = bss->freq; + else + search_freq = local->hw.conf.channel->center_freq; + + bss = ieee80211_rx_bss_get(dev, bssid, search_freq, + ifsta->ssid, ifsta->ssid_len); + if (!bss) + goto dont_join; + printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" " based on configured SSID\n", dev->name, print_mac(mac, bssid)); @@ -3675,6 +3685,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, ieee80211_rx_bss_put(local, bss); return ret; } + +dont_join: #ifdef CONFIG_MAC80211_IBSS_DEBUG printk(KERN_DEBUG " did not try to join ibss\n"); #endif /* CONFIG_MAC80211_IBSS_DEBUG */ From 25bc2deda9e8a430ed49f507a1120fb2c86abf33 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 21 Jul 2008 02:40:13 +0300 Subject: [PATCH 56/78] iwlwifi: rename iwl4965-base.c to iwl-agn.c This patch renames iwl4965-base.c to iwl-agn.c Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 6 ++---- drivers/net/wireless/iwlwifi/{iwl4965-base.c => iwl-agn.c} | 0 2 files changed, 2 insertions(+), 4 deletions(-) rename drivers/net/wireless/iwlwifi/{iwl4965-base.c => iwl-agn.c} (100%) diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index f50d2f8fd5c9..6bf3998736b5 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -11,10 +11,8 @@ iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-agn-rs.o +iwl4965-objs := iwl-agn.o iwl-4965.o iwl-agn-rs.o -ifeq ($(CONFIG_IWL5000),y) - iwl4965-objs += iwl-5000.o -endif +iwl4965-$(CONFIG_IWL5000) += iwl-5000.o diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl-agn.c similarity index 100% rename from drivers/net/wireless/iwlwifi/iwl4965-base.c rename to drivers/net/wireless/iwlwifi/iwl-agn.c From 3ac7f14694dd38273d9d96f1c873233d71190c15 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 21 Jul 2008 02:40:14 +0300 Subject: [PATCH 57/78] iwlwifi: fix checkpatch.pl errors This patch fixes errors reported by checkpatch in iwlwifi drivers Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 7 ++- drivers/net/wireless/iwlwifi/iwl-4965.c | 4 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 16 +++---- drivers/net/wireless/iwlwifi/iwl-agn.c | 10 ++--- drivers/net/wireless/iwlwifi/iwl-core.c | 4 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 4 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 11 +++-- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 3 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 50 +++++++++------------ 11 files changed, 54 insertions(+), 59 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 56a9361a847f..b3931f6135a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -795,8 +795,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)header; __le32 *pos; - pos = - (__le32 *) & mgmt->u.beacon. + pos = (__le32 *)&mgmt->u.beacon. timestamp; priv->timestamp0 = le32_to_cpu(pos[0]); priv->timestamp1 = le32_to_cpu(pos[1]); @@ -1509,7 +1508,7 @@ static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading) */ static inline int iwl3945_hw_reg_temp_out_of_range(int temperature) { - return (((temperature < -260) || (temperature > 25)) ? 1 : 0); + return ((temperature < -260) || (temperature > 25)) ? 1 : 0; } int iwl3945_hw_get_temperature(struct iwl3945_priv *priv) @@ -2630,7 +2629,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, tx_beacon_cmd->tx.supp_rates[1] = (IWL_CCK_BASIC_RATES_MASK & 0xF); - return (sizeof(struct iwl3945_tx_beacon_cmd) + frame_size); + return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size; } void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index f356f4f0944b..718f9d9e4947 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1515,11 +1515,11 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, c, atten_value, power_index, tx_power.s.radio_tx_gain[c], tx_power.s.dsp_predis_atten[c]); - }/* for each chain */ + } /* for each chain */ tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw); - }/* for each rate */ + } /* for each rate */ return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 076d3560302b..f7bbd12193f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1131,7 +1131,7 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) { - return le32_to_cpup((__le32*)&tx_resp->status + + return le32_to_cpup((__le32 *)&tx_resp->status + tx_resp->frame_count) & MAX_SN; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index b498b58d81fa..754fef5b592f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -245,7 +245,7 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) { - return ((ant_type & valid_antenna) == ant_type); + return (ant_type & valid_antenna) == ant_type; } /* @@ -384,9 +384,9 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, static inline int get_num_of_ant_from_rate(u32 rate_n_flags) { - return (!!(rate_n_flags & RATE_MCS_ANT_A_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_C_MSK)); + return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + + !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + + !!(rate_n_flags & RATE_MCS_ANT_C_MSK); } /** @@ -620,9 +620,9 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, #if 0 static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) { - return ((conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && + return (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && priv->current_ht_config.is_green_field && - !priv->current_ht_config.non_GF_STA_present); + !priv->current_ht_config.non_GF_STA_present; } #endif static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) @@ -2157,7 +2157,7 @@ static void *rs_alloc_sta(void *priv_rate, gfp_t gfp) for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i])); + rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); return lq_sta; } @@ -2179,7 +2179,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, sta->txrate_idx = 3; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i])); + rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); IWL_DEBUG_RATE("LQ: *** rate scale global init ***\n"); /* TODO: what is a good starting rate for STA? About middle? Maybe not diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index f71b3f3f81ba..4ff0636dbddc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2476,7 +2476,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) unsigned long flags; if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); + IWL_ERROR("%s Should not be called in AP mode\n", __func__); return; } @@ -2552,7 +2552,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv) default: IWL_ERROR("%s Should not be called in %d mode\n", - __FUNCTION__, priv->iw_mode); + __func__, priv->iw_mode); break; } @@ -3794,7 +3794,7 @@ static ssize_t show_measurement(struct device *d, struct iwl_priv *priv = dev_get_drvdata(d); struct iwl4965_spectrum_notification measure_report; u32 size = sizeof(measure_report), len = 0, ofs = 0; - u8 *data = (u8 *) & measure_report; + u8 *data = (u8 *)&measure_report; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -3934,7 +3934,7 @@ static ssize_t show_power_level(struct device *d, p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto"); p += sprintf(p, "\tINDEX:%d", level); p += sprintf(p, "\n"); - return (p - buf + 1); + return p - buf + 1; } static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, @@ -4009,7 +4009,7 @@ static ssize_t show_statistics(struct device *d, struct iwl_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl_notif_statistics); u32 len = 0, ofs = 0; - u8 *data = (u8 *) & priv->statistics; + u8 *data = (u8 *)&priv->statistics; int rc = 0; if (!iwl_is_alive(priv)) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 96beacf703a6..9bd61809129f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -383,8 +383,8 @@ void iwl_reset_qos(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_reset_qos); -#define MAX_BIT_RATE_40_MHZ 0x96; /* 150 Mbps */ -#define MAX_BIT_RATE_20_MHZ 0x48; /* 72 Mbps */ +#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */ +#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, struct ieee80211_ht_info *ht_info, enum ieee80211_band band) diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index d6d729e86bdb..b4ffd33ef98c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -33,12 +33,12 @@ #define IWL_DEBUG(level, fmt, args...) \ do { if (priv->debug_level & (level)) \ dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) #define IWL_DEBUG_LIMIT(level, fmt, args...) \ do { if ((priv->debug_level & (level)) && net_ratelimit()) \ dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) #ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl_debugfs { diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index ed948dc59b3d..20db0eb636a8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -231,7 +231,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, DECLARE_MAC_BUF(mac); buf = kmalloc(bufsz, GFP_KERNEL); - if(!buf) + if (!buf) return -ENOMEM; pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", @@ -364,16 +364,19 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) { struct iwl_debugfs *dbgfs; struct dentry *phyd = priv->hw->wiphy->debugfsdir; + int ret = 0; dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); if (!dbgfs) { + ret = -ENOMEM; goto err; } priv->dbgfs = dbgfs; dbgfs->name = name; dbgfs->dir_drv = debugfs_create_dir(name, phyd); - if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){ + if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { + ret = -ENOENT; goto err; } @@ -394,7 +397,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) err: IWL_ERROR("Can't open the debugfs directory\n"); iwl_dbgfs_unregister(priv); - return -ENOENT; + return ret; } EXPORT_SYMBOL(iwl_dbgfs_register); @@ -404,7 +407,7 @@ EXPORT_SYMBOL(iwl_dbgfs_register); */ void iwl_dbgfs_unregister(struct iwl_priv *priv) { - if (!(priv->dbgfs)) + if (!priv->dbgfs) return; DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom); diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 4a08a1b50979..bce53830b301 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -273,8 +273,7 @@ EXPORT_SYMBOL(iwl_eeprom_init); void iwl_eeprom_free(struct iwl_priv *priv) { - if(priv->eeprom) - kfree(priv->eeprom); + kfree(priv->eeprom); priv->eeprom = NULL; } EXPORT_SYMBOL(iwl_eeprom_free); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 10af82170f6b..60a6e0106036 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -823,7 +823,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, if (lq->sta_id == 0xFF) lq->sta_id = IWL_AP_ID; - iwl_dump_lq_cmd(priv,lq); + iwl_dump_lq_cmd(priv, lq); if (iwl_is_associated(priv) && priv->assoc_station_added) return iwl_send_cmd(priv, &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7c82ecfa30a4..eb41b02b506d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -275,10 +275,8 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv, return 0; error: - if (txq->txb) { - kfree(txq->txb); - txq->txb = NULL; - } + kfree(txq->txb); + txq->txb = NULL; return -ENOMEM; } @@ -365,10 +363,8 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t txq->q.n_bd, txq->bd, txq->q.dma_addr); /* De-alloc array of per-TFD driver data */ - if (txq->txb) { - kfree(txq->txb); - txq->txb = NULL; - } + kfree(txq->txb); + txq->txb = NULL; /* 0-fill queue descriptor structure */ memset(txq, 0, sizeof(*txq)); @@ -2703,9 +2699,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb) if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; - if (qc) { + if (qc) priv->stations[sta_id].tid[tid].seq_number = seq_number; - } } else { wait_write_ptr = 1; txq->need_update = 0; @@ -3813,7 +3808,7 @@ int iwl3945_calc_db_from_ratio(int sig_ratio) /* 100:1 or higher, divide by 10 and use table, * add 20 dB to make up for divide by 10 */ if (sig_ratio >= 100) - return (20 + (int)ratio2dB[sig_ratio/10]); + return 20 + (int)ratio2dB[sig_ratio/10]; /* We shouldn't see this */ if (sig_ratio < 1) @@ -5088,7 +5083,7 @@ static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv) * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host, * looking at all data. */ -static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 * image, u32 len) +static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u32 len) { u32 val; u32 save_len = len; @@ -5237,7 +5232,7 @@ static int iwl3945_verify_bsm(struct iwl3945_priv *priv) val = iwl3945_read_prph(priv, BSM_WR_DWCOUNT_REG); for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len; - reg += sizeof(u32), image ++) { + reg += sizeof(u32), image++) { val = iwl3945_read_prph(priv, reg); if (val != le32_to_cpu(*image)) { IWL_ERROR("BSM uCode verification failed at " @@ -6336,7 +6331,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data) DECLARE_MAC_BUF(mac); if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); + IWL_ERROR("%s Should not be called in AP mode\n", __func__); return; } @@ -6417,7 +6412,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data) default: IWL_ERROR("%s Should not be called in %d mode\n", - __FUNCTION__, priv->iw_mode); + __func__, priv->iw_mode); break; } @@ -7456,7 +7451,7 @@ static ssize_t show_measurement(struct device *d, struct iwl3945_priv *priv = dev_get_drvdata(d); struct iwl3945_spectrum_notification measure_report; u32 size = sizeof(measure_report), len = 0, ofs = 0; - u8 *data = (u8 *) & measure_report; + u8 *data = (u8 *)&measure_report; unsigned long flags; spin_lock_irqsave(&priv->lock, flags); @@ -7627,7 +7622,7 @@ static ssize_t show_power_level(struct device *d, else p += sprintf(p, " \n"); - return (p - buf + 1); + return p - buf + 1; } @@ -7649,7 +7644,7 @@ static ssize_t show_statistics(struct device *d, struct iwl3945_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl3945_notif_statistics); u32 len = 0, ofs = 0; - u8 *data = (u8 *) & priv->statistics; + u8 *data = (u8 *)&priv->statistics; int rc = 0; if (!iwl3945_is_alive(priv)) @@ -8003,16 +7998,16 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* nic init */ iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); + CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - err = iwl3945_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (err < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); + iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + err = iwl3945_poll_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); + if (err < 0) { + IWL_DEBUG_INFO("Failed to init the card\n"); goto out_remove_sysfs; - } + } /* Read the EEPROM */ err = iwl3945_eeprom_init(priv); if (err) { @@ -8114,9 +8109,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_unset_hw_setting(priv); iwl3945_clear_stations_table(priv); - if (priv->mac80211_registered) { + if (priv->mac80211_registered) ieee80211_unregister_hw(priv->hw); - } /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); From 4fc22b21b3fcb3580c32b70605ef114178f8e611 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 21 Jul 2008 18:54:42 +0300 Subject: [PATCH 58/78] iwlwifi: rename 4965 to AGN This patch renames driver name from 4965 to AGN The driver supports both 4965AGN and 5000AGN family The driver's original module name iwl4965.ko remains as an alias Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 98 ++++++++++++++------------ drivers/net/wireless/iwlwifi/Makefile | 11 +-- drivers/net/wireless/iwlwifi/iwl-agn.c | 15 ++-- drivers/net/wireless/iwlwifi/iwl-dev.h | 7 +- 4 files changed, 68 insertions(+), 63 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 82b66a3d3a5d..b0ac0ce3fb9f 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -14,18 +14,49 @@ config IWLWIFI_LEDS default n config IWLWIFI_RFKILL - boolean "IWLWIFI RF kill support" + boolean "Iwlwifi RF kill support" depends on IWLCORE -config IWL4965 - tristate "Intel Wireless WiFi 4965AGN" +config IWLWIFI_DEBUG + bool "Enable full debugging output in iwlagn driver" + depends on IWLCORE + ---help--- + This option will enable debug tracing output for the iwlwifi drivers + + This will result in the kernel module being ~100k larger. You can + control which debug output is sent to the kernel log by setting the + value in + + /sys/class/net/wlan0/device/debug_level + + This entry will only exist if this option is enabled. + + To set a value, simply echo an 8-byte hex value to the same file: + + % echo 0x43fff > /sys/class/net/wlan0/device/debug_level + + You can find the list of debug mask values in: + drivers/net/wireless/iwlwifi/iwl-debug.h + + If this is your first time using this driver, you should say Y here + as the debug information can assist others in helping you resolve + any problems you may encounter. + +config IWLWIFI_DEBUGFS + bool "Iwlwifi debugfs support" + depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS + ---help--- + Enable creation of debugfs files for the iwlwifi drivers. + +config IWLAGN + tristate "Intel Wireless WiFi Next Gen AGN" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER select IWLCORE ---help--- Select to build the driver supporting the: - Intel Wireless WiFi Link 4965AGN + Intel Wireless WiFi Link Next-Gen AGN This driver uses the kernel's mac80211 subsystem. @@ -42,60 +73,33 @@ config IWL4965 If you want to compile the driver as a module ( = code which can be inserted in and removed from the running kernel whenever you want), say M here and read . The - module will be called iwl4965.ko. + module will be called iwlagn.ko. -config IWL4965_LEDS - bool "Enable LEDS features in iwl4965 driver" - depends on IWL4965 +config IWLAGN_SPECTRUM_MEASUREMENT + bool "Enable Spectrum Measurement in iwlagn driver" + depends on IWLAGN + ---help--- + This option will enable spectrum measurement for the iwlagn driver. + +config IWLAGN_LEDS + bool "Enable LEDS features in iwlagn driver" + depends on IWLAGN select IWLWIFI_LEDS ---help--- - This option enables LEDS for the iwlwifi drivers + This option enables LEDS for the iwlagn drivers -config IWL4965_SPECTRUM_MEASUREMENT - bool "Enable Spectrum Measurement in iwl4965 driver" - depends on IWL4965 +config IWL4965 + bool "Intel Wireless WiFi 4965AGN" + depends on IWLAGN ---help--- - This option will enable spectrum measurement for the iwl4965 driver. - -config IWLWIFI_DEBUG - bool "Enable full debugging output in iwl4965 driver" - depends on IWL4965 - ---help--- - This option will enable debug tracing output for the iwl4965 - driver. - - This will result in the kernel module being ~100k larger. You can - control which debug output is sent to the kernel log by setting the - value in - - /sys/class/net/wlan0/device/debug_level - - This entry will only exist if this option is enabled. - - To set a value, simply echo an 8-byte hex value to the same file: - - % echo 0x43fff > /sys/class/net/wlan0/device/debug_level - - You can find the list of debug mask values in: - drivers/net/wireless/iwlwifi/iwl-4965-debug.h - - If this is your first time using this driver, you should say Y here - as the debug information can assist others in helping you resolve - any problems you may encounter. + This option enables support for Intel Wireless WiFi Link 4965AGN config IWL5000 bool "Intel Wireless WiFi 5000AGN" - depends on IWL4965 + depends on IWLAGN ---help--- This option enables support for Intel Wireless WiFi Link 5000AGN Family - Dependency on 4965 is temporary - -config IWLWIFI_DEBUGFS - bool "Iwlwifi debugfs support" - depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS - ---help--- - Enable creation of debugfs files for the iwlwifi drivers. config IWL3945 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection" diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 6bf3998736b5..47aa28f6a513 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -6,13 +6,14 @@ iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o +obj-$(CONFIG_IWLAGN) += iwlagn.o +iwlagn-objs := iwl-agn.o iwl-agn-rs.o + +iwlagn-$(CONFIG_IWL4965) += iwl-4965.o +iwlagn-$(CONFIG_IWL5000) += iwl-5000.o + obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o -obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs := iwl-agn.o iwl-4965.o iwl-agn-rs.o - -iwl4965-$(CONFIG_IWL5000) += iwl-5000.o - diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4ff0636dbddc..6503b3ac8d66 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -73,7 +73,7 @@ #define VD #endif -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT #define VS "s" #else #define VS @@ -86,6 +86,7 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL"); +MODULE_ALIAS("iwl4965"); /*************** STATION TABLE MANAGEMENT **** * mac80211 should be examined to determine if sta_info is duplicating @@ -883,7 +884,7 @@ static void iwl4965_set_rate(struct iwl_priv *priv) (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT #include "iwl-spectrum.h" @@ -1087,7 +1088,7 @@ static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif); @@ -3786,7 +3787,7 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT static ssize_t show_measurement(struct device *d, struct device_attribute *attr, char *buf) @@ -3857,7 +3858,7 @@ static ssize_t store_measurement(struct device *d, static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, show_measurement, store_measurement); -#endif /* CONFIG_IWL4965_SPECTRUM_MEASUREMENT */ +#endif /* CONFIG_IWLAGN_SPECTRUM_MEASUREMENT */ static ssize_t store_retry_rate(struct device *d, struct device_attribute *attr, @@ -4105,7 +4106,7 @@ static struct attribute *iwl4965_sysfs_entries[] = { &dev_attr_channels.attr, &dev_attr_flags.attr, &dev_attr_filter_flags.attr, -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT &dev_attr_measurement.attr, #endif &dev_attr_power_level.attr, @@ -4457,8 +4458,10 @@ static int iwl4965_pci_resume(struct pci_dev *pdev) /* Hardware specific file defines the PCI IDs table for that hardware module */ static struct pci_device_id iwl_hw_card_ids[] = { +#ifdef CONFIG_IWL4965 {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, +#endif /* CONFIG_IWL4965 */ #ifdef CONFIG_IWL5000 {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 7ac56b1350b7..848786ab7916 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -36,7 +36,7 @@ #include #include -#define DRV_NAME "iwl4965" +#define DRV_NAME "iwlagn" #include "iwl-rfkill.h" #include "iwl-eeprom.h" #include "iwl-4965-hw.h" @@ -808,14 +808,11 @@ struct iwl_chain_noise_data { #define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT - enum { MEASUREMENT_READY = (1 << 0), MEASUREMENT_ACTIVE = (1 << 1), }; -#endif #define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ @@ -840,7 +837,7 @@ struct iwl_priv { struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; -#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT +#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT /* spectrum measurement report caching */ struct iwl4965_spectrum_notification measure_report; u8 measurement_status; From 5cbbb376d65ed181ed290cea505ba37a0425ee25 Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Fri, 1 Aug 2008 21:57:16 +0200 Subject: [PATCH 59/78] iwlwifi: Don't use buffer allocated on the stack for led names Having the buffer on the stack and even re-using it for all led devices is bad. Not being able to resolve the name member of the led device structure to a meaningful value leads to confusion during ad-hoc debugging and potential breakage in the future, if we ever decide to access the name member outside of the registration function. Move the buffer to our private per led device structures so that it is accessible after registration. A quick grep didn't yield any occurence of using the led device name parameter outside of the led device registration function, so currently we should already be safe for normal operation. Signed-off-by: Sven Wegener Cc: Richard Purdie Acked-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-led.c | 33 +++++++++++---------- drivers/net/wireless/iwlwifi/iwl-3945-led.h | 1 + drivers/net/wireless/iwlwifi/iwl-led.c | 29 ++++++++++-------- drivers/net/wireless/iwlwifi/iwl-led.h | 1 + 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index 6be1fe13fa57..d3336966b6b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -206,12 +206,12 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, static int iwl3945_led_register_led(struct iwl3945_priv *priv, struct iwl3945_led *led, enum led_type type, u8 set_led, - const char *name, char *trigger) + char *trigger) { struct device *device = wiphy_dev(priv->hw->wiphy); int ret; - led->led_dev.name = name; + led->led_dev.name = led->name; led->led_dev.brightness_set = iwl3945_led_brightness_set; led->led_dev.default_trigger = trigger; @@ -308,7 +308,6 @@ void iwl3945_led_background(struct iwl3945_priv *priv) int iwl3945_led_register(struct iwl3945_priv *priv) { char *trigger; - char name[32]; int ret; priv->last_blink_rate = 0; @@ -318,7 +317,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv) priv->allow_blinking = 0; trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:radio", + snprintf(priv->led[IWL_LED_TRG_RADIO].name, + sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", wiphy_name(priv->hw->wiphy)); priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; @@ -327,19 +327,20 @@ int iwl3945_led_register(struct iwl3945_priv *priv) ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, - name, trigger); + IWL_LED_TRG_RADIO, 1, trigger); + if (ret) goto exit_fail; trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:assoc", + snprintf(priv->led[IWL_LED_TRG_ASSOC].name, + sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, - name, trigger); + IWL_LED_TRG_ASSOC, 0, trigger); + /* for assoc always turn led on */ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; @@ -349,14 +350,13 @@ int iwl3945_led_register(struct iwl3945_priv *priv) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:RX", + snprintf(priv->led[IWL_LED_TRG_RX].name, + sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); - ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, - name, trigger); + IWL_LED_TRG_RX, 0, trigger); priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; @@ -366,13 +366,14 @@ int iwl3945_led_register(struct iwl3945_priv *priv) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:TX", + snprintf(priv->led[IWL_LED_TRG_TX].name, + sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); ret = iwl3945_led_register_led(priv, &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, - name, trigger); + IWL_LED_TRG_TX, 0, trigger); + priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h index 47b7e0bac802..2fbd126c1347 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -50,6 +50,7 @@ enum led_type { struct iwl3945_led { struct iwl3945_priv *priv; struct led_classdev led_dev; + char name[32]; int (*led_on) (struct iwl3945_priv *priv, int led_id); int (*led_off) (struct iwl3945_priv *priv, int led_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 0a01f091c516..cb11c4a4d691 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -242,12 +242,12 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev, */ static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, enum led_type type, u8 set_led, - const char *name, char *trigger) + char *trigger) { struct device *device = wiphy_dev(priv->hw->wiphy); int ret; - led->led_dev.name = name; + led->led_dev.name = led->name; led->led_dev.brightness_set = iwl_led_brightness_set; led->led_dev.default_trigger = trigger; @@ -345,7 +345,6 @@ EXPORT_SYMBOL(iwl_leds_background); int iwl_leds_register(struct iwl_priv *priv) { char *trigger; - char name[32]; int ret; priv->last_blink_rate = 0; @@ -354,7 +353,8 @@ int iwl_leds_register(struct iwl_priv *priv) priv->allow_blinking = 0; trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:radio", + snprintf(priv->led[IWL_LED_TRG_RADIO].name, + sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio", wiphy_name(priv->hw->wiphy)); priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg; @@ -362,16 +362,17 @@ int iwl_leds_register(struct iwl_priv *priv) priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, name, trigger); + IWL_LED_TRG_RADIO, 1, trigger); if (ret) goto exit_fail; trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:assoc", + snprintf(priv->led[IWL_LED_TRG_ASSOC].name, + sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc", wiphy_name(priv->hw->wiphy)); ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, name, trigger); + IWL_LED_TRG_ASSOC, 0, trigger); /* for assoc always turn led on */ priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate; @@ -382,11 +383,12 @@ int iwl_leds_register(struct iwl_priv *priv) goto exit_fail; trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy)); - + snprintf(priv->led[IWL_LED_TRG_RX].name, + sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX", + wiphy_name(priv->hw->wiphy)); ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, name, trigger); + IWL_LED_TRG_RX, 0, trigger); priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; @@ -396,9 +398,12 @@ int iwl_leds_register(struct iwl_priv *priv) goto exit_fail; trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy)); + snprintf(priv->led[IWL_LED_TRG_TX].name, + sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX", + wiphy_name(priv->hw->wiphy)); + ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, name, trigger); + IWL_LED_TRG_TX, 0, trigger); priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 1980ae5a7e82..588c9ad20e83 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -52,6 +52,7 @@ enum led_type { struct iwl_led { struct iwl_priv *priv; struct led_classdev led_dev; + char name[32]; int (*led_on) (struct iwl_priv *priv, int led_id); int (*led_off) (struct iwl_priv *priv, int led_id); From d06193f311102b2c990ec5f66b470ea49ecc73a4 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Aug 2008 23:36:01 +0200 Subject: [PATCH 60/78] rt2x00: Disable link tuning in rt2500usb In the legacy rt2570 driver the link tuner was never really called. And now the reason has finally become apparent: It breaks TX capabilities As soon as the device has been associated all following TX frames will be queued in the hardware and never transmitted to the air. Disabling sections of the link tuner did not have the expected result, but completely disabling the link tuner did have the right result (Both of my rt2570 devices came back to life). This should fix Fedora bug: 411481 v2: Fix typos Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c6f6eb6e17a1..cd5af656932d 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -633,6 +633,16 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev) rt2x00dev->link.vgc_level = value; } +/* + * NOTE: This function is directly ported from legacy driver, but + * despite it being declared it was never called. Although link tuning + * sounds like a good idea, and usually works well for the other drivers, + * it does _not_ work with rt2500usb. Enabling this function will result + * in TX capabilities only until association kicks in. Immediately + * after the successful association all TX frames will be kept in the + * hardware queue and never transmitted. + */ +#if 0 static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) { int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); @@ -752,6 +762,9 @@ dynamic_cca_tune: rt2x00dev->link.vgc_level = r17; } } +#else +#define rt2500usb_link_tuner NULL +#endif /* * Initialization functions. @@ -1737,6 +1750,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); + __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); /* * Set the rssi offset. From 6041e2a08c50e3fcaf1e56422bfafda62c597cea Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 3 Aug 2008 17:58:36 -0500 Subject: [PATCH 61/78] p54: Fix potential concurrent access to private data Experience with the rtl8187 driver has shown that mac80211 can make calls to the config callback routine in rapid succession. This patch creates a mutex that protects the private data in several of the routines called by mac80211. Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54.h | 1 + drivers/net/wireless/p54/p54common.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index c6f27b9022f9..cac9a515b82d 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h @@ -52,6 +52,7 @@ struct p54_common { int (*open)(struct ieee80211_hw *dev); void (*stop)(struct ieee80211_hw *dev); int mode; + struct mutex conf_mutex; u8 mac_addr[ETH_ALEN]; u8 bssid[ETH_ALEN]; struct pda_iq_autocal_entry *iq_autocal; diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index ffaf7a6b6810..4da89ea9b561 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -886,9 +886,12 @@ static void p54_remove_interface(struct ieee80211_hw *dev, static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { int ret; + struct p54_common *priv = dev->priv; + mutex_lock(&priv->conf_mutex); ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); p54_set_vdcf(dev); + mutex_unlock(&priv->conf_mutex); return ret; } @@ -898,10 +901,12 @@ static int p54_config_interface(struct ieee80211_hw *dev, { struct p54_common *priv = dev->priv; + mutex_lock(&priv->conf_mutex); p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642); p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0); p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); memcpy(priv->bssid, conf->bssid, ETH_ALEN); + mutex_unlock(&priv->conf_mutex); return 0; } @@ -1009,6 +1014,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) } p54_init_vdcf(dev); + mutex_init(&priv->conf_mutex); return dev; } From 4c43e0d0ecd5196ed5c67f64ed2f1860770eed34 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 4 Aug 2008 16:00:39 +0800 Subject: [PATCH 62/78] iwlwifi: HW bug fixes This patch adds few HW bug fixes. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 15 +++++++++++++++ drivers/net/wireless/iwlwifi/iwl-csr.h | 10 +++++++++- drivers/net/wireless/iwlwifi/iwl-prph.h | 12 +++++++----- net/mac80211/mlme.c | 2 +- 4 files changed, 32 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f7bbd12193f9..1d793c093f1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -93,6 +93,13 @@ static int iwl5000_apm_init(struct iwl_priv *priv) iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); + /* Set FH wait treshold to maximum (HW error during stress W/A) */ + iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); + + /* enable HAP INTA to move device L1a -> L0s */ + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); + iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); /* set "initialization complete" bit to move adapter @@ -230,6 +237,14 @@ static void iwl5000_nic_config(struct iwl_priv *priv) CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); + /* W/A : NIC is stuck in a reset state after Early PCIe power off + * (PCIe power is lost before PERST# is asserted), + * causing ME FW to lose ownership and not being able to obtain it back. + */ + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, + ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); + spin_unlock_irqrestore(&priv->lock, flags); } diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 545ed692d889..52629fbd835a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -104,6 +104,7 @@ * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step */ #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) +#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) /* Bits for CSR_HW_IF_CONFIG_REG */ #define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) @@ -118,7 +119,12 @@ #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) -#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) +#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) +#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) +#define CSR_HW_IF_CONFIG_REG_BIT_PCI_OWN_SEM (0x00400000) +#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN (0x02000000) +#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME (0x08000000) + /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), * acknowledged (reset) by host writing "1" to flagged bits. */ @@ -236,6 +242,8 @@ #define CSR39_ANA_PLL_CFG_VAL (0x01000000) #define CSR50_ANA_PLL_CFG_VAL (0x00880300) +/* HPET MEM debug */ +#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000) /*=== HBUS (Host-side Bus) ===*/ #define HBUS_BASE (0x400) /* diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 70d9c7568b98..ee5afd48d3af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -84,14 +84,16 @@ #define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200) #define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800) -#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) -#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) +#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000) +#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) +#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) +#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) +#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ +#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) -#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) -#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) -#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x01000000) +#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) /** * BSM (Bootstrap State Machine) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5358420d8796..e1d11c9b6729 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -3920,7 +3920,7 @@ done: if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { struct ieee80211_if_sta *ifsta = &sdata->u.sta; if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || - (!ifsta->state == IEEE80211_IBSS_JOINED && + (!(ifsta->state == IEEE80211_IBSS_JOINED) && !ieee80211_sta_active_ibss(dev))) ieee80211_sta_find_ibss(dev, ifsta); } From da99c4b6c25964b90c79f19beccda208df1a865a Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Mon, 4 Aug 2008 16:00:40 +0800 Subject: [PATCH 63/78] iwlwifi: memory allocation optimization This patch optimizes memory allocation. The cmd member of iwl_tx_queue was allocated previously as a continuous block of memory. This patch allocates separate memory chunks for each command and maps/unmaps these chunks in the run time. Signed-off-by: Gregory Greenman Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 6 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 3 +- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 2 +- drivers/net/wireless/iwlwifi/iwl-tx.c | 76 ++++++++++++++++++------- 4 files changed, 59 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1d793c093f1a..56dbc8144a34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -939,8 +939,8 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; if (txq_id != IWL_CMD_QUEUE_NUM) { - sta = txq->cmd[txq->q.write_ptr].cmd.tx.sta_id; - sec_ctl = txq->cmd[txq->q.write_ptr].cmd.tx.sec_ctl; + sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; + sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; switch (sec_ctl & TX_CMD_SEC_MSK) { case TX_CMD_SEC_CCM: @@ -979,7 +979,7 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, u8 sta = 0; if (txq_id != IWL_CMD_QUEUE_NUM) - sta = txq->cmd[txq->q.read_ptr].cmd.tx.sta_id; + sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id; shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr]. val = cpu_to_le16(1 | (sta << 12)); diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 848786ab7916..c19db438306c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -135,8 +135,7 @@ struct iwl_tx_info { struct iwl_tx_queue { struct iwl_queue q; struct iwl_tfd_frame *bd; - struct iwl_cmd *cmd; - dma_addr_t dma_addr_cmd; + struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS]; struct iwl_tx_info *txb; int need_update; int sched_retry; diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 8fa991b7202a..6512834bb916 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -228,7 +228,7 @@ cancel: * TX cmd queue. Otherwise in case the cmd comes * in later, it will possibly set an invalid * address (cmd->meta.source). */ - qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; + qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; qcmd->meta.flags &= ~CMD_WANT_SKB; } fail: diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 39f19ebee973..aa98c76d8195 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -208,11 +208,12 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr); * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) +static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) { + struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; struct pci_dev *dev = priv->pci_dev; - int len; + int i, slots_num, len; if (q->n_bd == 0) return; @@ -227,7 +228,12 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq) len += IWL_MAX_SCAN_SIZE; /* De-alloc array of command/tx buffers */ - pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); + slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? + TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + for (i = 0; i < slots_num; i++) + kfree(txq->cmd[i]); + if (txq_id == IWL_CMD_QUEUE_NUM) + kfree(txq->cmd[slots_num]); /* De-alloc circular buffer of TFDs */ if (txq->q.n_bd) @@ -400,8 +406,7 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id) { - struct pci_dev *dev = priv->pci_dev; - int len; + int i, len; int rc = 0; /* @@ -412,17 +417,25 @@ static int iwl_tx_queue_init(struct iwl_priv *priv, * For normal Tx queues (all other queues), no super-size command * space is needed. */ - len = sizeof(struct iwl_cmd) * slots_num; - if (txq_id == IWL_CMD_QUEUE_NUM) - len += IWL_MAX_SCAN_SIZE; - txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd); - if (!txq->cmd) - return -ENOMEM; + len = sizeof(struct iwl_cmd); + for (i = 0; i <= slots_num; i++) { + if (i == slots_num) { + if (txq_id == IWL_CMD_QUEUE_NUM) + len += IWL_MAX_SCAN_SIZE; + else + continue; + } + + txq->cmd[i] = kmalloc(len, GFP_KERNEL | GFP_DMA); + if (!txq->cmd[i]) + return -ENOMEM; + } /* Alloc driver data array and TFD circular buffer */ rc = iwl_tx_queue_alloc(priv, txq, txq_id); if (rc) { - pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd); + for (i = 0; i < slots_num; i++) + kfree(txq->cmd[i]); return -ENOMEM; } @@ -451,7 +464,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv) /* Tx queues */ for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - iwl_tx_queue_free(priv, &priv->txq[txq_id]); + iwl_tx_queue_free(priv, txq_id); /* Keep-warm buffer */ iwl_kw_free(priv); @@ -859,7 +872,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) txq->txb[q->write_ptr].skb[0] = skb; /* Set up first empty entry in queue's array of Tx/cmd buffers */ - out_cmd = &txq->cmd[idx]; + out_cmd = txq->cmd[idx]; tx_cmd = &out_cmd->cmd.tx; memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); @@ -899,8 +912,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx + - offsetof(struct iwl_cmd, hdr); + txcmd_phys = pci_map_single(priv->pci_dev, out_cmd, + sizeof(struct iwl_cmd), PCI_DMA_TODEVICE); + txcmd_phys += offsetof(struct iwl_cmd, hdr); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ @@ -1004,7 +1018,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) u32 idx; u16 fix_size; dma_addr_t phys_addr; - int ret; + int len, ret; unsigned long flags; cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); @@ -1034,7 +1048,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) control_flags = (u32 *) tfd; idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE); - out_cmd = &txq->cmd[idx]; + out_cmd = txq->cmd[idx]; out_cmd->hdr.cmd = cmd->id; memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta)); @@ -1048,9 +1062,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) INDEX_TO_SEQ(q->write_ptr)); if (out_cmd->meta.flags & CMD_SIZE_HUGE) out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME); - - phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + - offsetof(struct iwl_cmd, hdr); + len = (idx == TFD_CMD_SLOTS) ? + IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd); + phys_addr = pci_map_single(priv->pci_dev, out_cmd, len, + PCI_DMA_TODEVICE); + phys_addr += offsetof(struct iwl_cmd, hdr); iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " @@ -1115,6 +1131,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { struct iwl_tx_queue *txq = &priv->txq[txq_id]; struct iwl_queue *q = &txq->q; + struct iwl_tfd_frame *bd = &txq->bd[index]; + dma_addr_t dma_addr; + int is_odd, buf_len; int nfreed = 0; if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { @@ -1132,6 +1151,19 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) q->write_ptr, q->read_ptr); queue_work(priv->workqueue, &priv->restart); } + is_odd = (index/2) & 0x1; + if (is_odd) { + dma_addr = IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) | + (IWL_GET_BITS(bd->pa[index], + tb2_addr_hi20) << 16); + buf_len = IWL_GET_BITS(bd->pa[index], tb2_len); + } else { + dma_addr = le32_to_cpu(bd->pa[index].tb1_addr); + buf_len = IWL_GET_BITS(bd->pa[index], tb1_len); + } + + pci_unmap_single(priv->pci_dev, dma_addr, buf_len, + PCI_DMA_TODEVICE); nfreed++; } } @@ -1163,7 +1195,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); - cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; + cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; /* Input error checking is done when commands are added to queue. */ if (cmd->meta.flags & CMD_WANT_SKB) { From caab8f1a5d0da583b6ffe41afea2774c676444ca Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 4 Aug 2008 16:00:42 +0800 Subject: [PATCH 64/78] iwlwifi: implement iwl5000_calc_rssi This patch implements rssi calculation for 5000 HW. Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 35 ++++++++++++ drivers/net/wireless/iwlwifi/iwl-5000.c | 39 ++++++++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 35 +++++++++--- drivers/net/wireless/iwlwifi/iwl-core.h | 2 + drivers/net/wireless/iwlwifi/iwl-rx.c | 59 ++++++--------------- 5 files changed, 119 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 718f9d9e4947..22bb26985c2e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2258,6 +2258,40 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); } +static int iwl4965_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) +{ + /* data from PHY/DSP regarding signal strength, etc., + * contents are always there, not configurable by host. */ + struct iwl4965_rx_non_cfg_phy *ncphy = + (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf; + u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK) + >> IWL49_AGC_DB_POS; + + u32 valid_antennae = + (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK) + >> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET; + u8 max_rssi = 0; + u32 i; + + /* Find max rssi among 3 possible receivers. + * These values are measured by the digital signal processor (DSP). + * They should stay fairly constant even as the signal strength varies, + * if the radio's automatic gain control (AGC) is working right. + * AGC value (see below) will provide the "interesting" info. */ + for (i = 0; i < 3; i++) + if (valid_antennae & (1 << i)) + max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); + + IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", + ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], + max_rssi, agc); + + /* dBm = max_rssi dB - agc dB - constant. + * Higher AGC (higher radio gain) means lower signal. */ + return max_rssi - agc - IWL_RSSI_OFFSET; +} + /* Set up 4965-specific Rx frame reply handlers */ static void iwl4965_rx_handler_setup(struct iwl_priv *priv) @@ -2289,6 +2323,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .chain_noise_reset = iwl4965_chain_noise_reset, .gain_computation = iwl4965_gain_computation, .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, + .calc_rssi = iwl4965_calc_rssi, }; static struct iwl_lib_ops iwl4965_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 56dbc8144a34..c5b104fd149c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1459,6 +1459,44 @@ static void iwl5000_temperature(struct iwl_priv *priv) priv->temperature = le32_to_cpu(priv->statistics.general.temperature); } +/* Calc max signal level (dBm) among 3 possible receivers */ +static int iwl5000_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) +{ + /* data from PHY/DSP regarding signal strength, etc., + * contents are always there, not configurable by host + */ + struct iwl5000_non_cfg_phy *ncphy = + (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; + u32 val, rssi_a, rssi_b, rssi_c, max_rssi; + u8 agc; + + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); + agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; + + /* Find max rssi among 3 possible receivers. + * These values are measured by the digital signal processor (DSP). + * They should stay fairly constant even as the signal strength varies, + * if the radio's automatic gain control (AGC) is working right. + * AGC value (see below) will provide the "interesting" info. + */ + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); + rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; + rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; + val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); + rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; + + max_rssi = max_t(u32, rssi_a, rssi_b); + max_rssi = max_t(u32, max_rssi, rssi_c); + + IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", + rssi_a, rssi_b, rssi_c, max_rssi, agc); + + /* dBm = max_rssi dB - agc dB - constant. + * Higher AGC (higher radio gain) means lower signal. */ + return max_rssi - agc - IWL_RSSI_OFFSET; +} + static struct iwl_hcmd_ops iwl5000_hcmd = { .rxon_assoc = iwl5000_send_rxon_assoc, }; @@ -1469,6 +1507,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { .gain_computation = iwl5000_gain_computation, .chain_noise_reset = iwl5000_chain_noise_reset, .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, + .calc_rssi = iwl5000_calc_rssi, }; static struct iwl_lib_ops iwl5000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 5e57f3ae2ea6..28b5b09996ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -1075,10 +1075,12 @@ struct iwl4965_rx_frame { } __attribute__ ((packed)); /* Fixed (non-configurable) rx data from phy */ -#define RX_PHY_FLAGS_ANTENNAE_OFFSET (4) -#define RX_PHY_FLAGS_ANTENNAE_MASK (0x70) -#define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ -#define IWL_AGC_DB_POS (7) + +#define IWL49_RX_RES_PHY_CNT 14 +#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET (4) +#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK (0x70) +#define IWL49_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ +#define IWL49_AGC_DB_POS (7) struct iwl4965_rx_non_cfg_phy { __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */ __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ @@ -1086,12 +1088,30 @@ struct iwl4965_rx_non_cfg_phy { u8 pad[0]; } __attribute__ ((packed)); + +#define IWL50_RX_RES_PHY_CNT 8 +#define IWL50_RX_RES_AGC_IDX 1 +#define IWL50_RX_RES_RSSI_AB_IDX 2 +#define IWL50_RX_RES_RSSI_C_IDX 3 +#define IWL50_OFDM_AGC_MSK 0xfe00 +#define IWL50_OFDM_AGC_BIT_POS 9 +#define IWL50_OFDM_RSSI_A_MSK 0x00ff +#define IWL50_OFDM_RSSI_A_BIT_POS 0 +#define IWL50_OFDM_RSSI_B_MSK 0xff0000 +#define IWL50_OFDM_RSSI_B_BIT_POS 16 +#define IWL50_OFDM_RSSI_C_MSK 0x00ff +#define IWL50_OFDM_RSSI_C_BIT_POS 0 + +struct iwl5000_non_cfg_phy { + __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* upto 8 phy entries */ +} __attribute__ ((packed)); + + /* * REPLY_RX = 0xc3 (response only, not a command) * Used only for legacy (non 11n) frames. */ -#define RX_RES_PHY_CNT 14 -struct iwl4965_rx_phy_res { +struct iwl_rx_phy_res { u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */ u8 cfg_phy_cnt; /* configurable DSP phy data byte count */ u8 stat_id; /* configurable DSP phy data set ID */ @@ -1100,8 +1120,7 @@ struct iwl4965_rx_phy_res { __le32 beacon_time_stamp; /* beacon at on-air rise */ __le16 phy_flags; /* general phy flags: band, modulation, ... */ __le16 channel; /* channel number */ - __le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */ - __le32 reserved2; + u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ __le32 rate_n_flags; /* RATE_MCS_* */ __le16 byte_count; /* frame's byte-count */ __le16 reserved3; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index eaefa42f37c5..64f139e97444 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -95,6 +95,8 @@ struct iwl_hcmd_utils_ops { void (*chain_noise_reset)(struct iwl_priv *priv); void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, __le32 *tx_flags); + int (*calc_rssi)(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp); }; struct iwl_lib_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index e2d9afba38a5..f3f6ea49fdd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -791,7 +791,7 @@ static inline void iwl_dbg_report_frame(struct iwl_priv *priv, static void iwl_add_radiotap(struct iwl_priv *priv, struct sk_buff *skb, - struct iwl4965_rx_phy_res *rx_start, + struct iwl_rx_phy_res *rx_start, struct ieee80211_rx_status *stats, u32 ampdu_status) { @@ -1010,8 +1010,8 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, struct ieee80211_rx_status *stats) { struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl4965_rx_phy_res *rx_start = (include_phy) ? - (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL; + struct iwl_rx_phy_res *rx_start = (include_phy) ? + (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL; struct ieee80211_hdr *hdr; u16 len; __le32 *rx_end; @@ -1020,7 +1020,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, u32 ampdu_status_legacy; if (!include_phy && priv->last_phy_res[0]) - rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; + rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; if (!rx_start) { IWL_ERROR("MPDU frame without a PHY data\n"); @@ -1032,8 +1032,8 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, len = le16_to_cpu(rx_start->byte_count); - rx_end = (__le32 *) ((u8 *) &pkt->u.raw[0] + - sizeof(struct iwl4965_rx_phy_res) + + rx_end = (__le32 *)((u8 *) &pkt->u.raw[0] + + sizeof(struct iwl_rx_phy_res) + rx_start->cfg_phy_cnt + len); } else { @@ -1084,40 +1084,13 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, } /* Calc max signal level (dBm) among 3 possible receivers */ -static int iwl_calc_rssi(struct iwl_priv *priv, - struct iwl4965_rx_phy_res *rx_resp) +static inline int iwl_calc_rssi(struct iwl_priv *priv, + struct iwl_rx_phy_res *rx_resp) { - /* data from PHY/DSP regarding signal strength, etc., - * contents are always there, not configurable by host. */ - struct iwl4965_rx_non_cfg_phy *ncphy = - (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy; - u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK) - >> IWL_AGC_DB_POS; - - u32 valid_antennae = - (le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK) - >> RX_PHY_FLAGS_ANTENNAE_OFFSET; - u8 max_rssi = 0; - u32 i; - - /* Find max rssi among 3 possible receivers. - * These values are measured by the digital signal processor (DSP). - * They should stay fairly constant even as the signal strength varies, - * if the radio's automatic gain control (AGC) is working right. - * AGC value (see below) will provide the "interesting" info. */ - for (i = 0; i < 3; i++) - if (valid_antennae & (1 << i)) - max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); - - IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n", - ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], - max_rssi, agc); - - /* dBm = max_rssi dB - agc dB - constant. - * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL_RSSI_OFFSET; + return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); } + static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; @@ -1180,9 +1153,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, * this rx packet for legacy frames, * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ int include_phy = (pkt->hdr.cmd == REPLY_RX); - struct iwl4965_rx_phy_res *rx_start = (include_phy) ? - (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : - (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; + struct iwl_rx_phy_res *rx_start = (include_phy) ? + (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : + (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; __le32 *rx_end; unsigned int len = 0; u16 fc; @@ -1210,7 +1183,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, if (!include_phy) { if (priv->last_phy_res[0]) - rx_start = (struct iwl4965_rx_phy_res *) + rx_start = (struct iwl_rx_phy_res *) &priv->last_phy_res[1]; else rx_start = NULL; @@ -1227,7 +1200,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, len = le16_to_cpu(rx_start->byte_count); rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + - sizeof(struct iwl4965_rx_phy_res) + len); + sizeof(struct iwl_rx_phy_res) + len); } else { struct iwl4965_rx_mpdu_res_start *amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; @@ -1316,6 +1289,6 @@ void iwl_rx_reply_rx_phy(struct iwl_priv *priv, struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; priv->last_phy_res[0] = 1; memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), - sizeof(struct iwl4965_rx_phy_res)); + sizeof(struct iwl_rx_phy_res)); } EXPORT_SYMBOL(iwl_rx_reply_rx_phy); From c1842d6150c4efe1d01e7a8cf86c63aec6223486 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 4 Aug 2008 16:00:43 +0800 Subject: [PATCH 65/78] iwlwifi: fix unhandled interrupt when HW rfkill is on This patch fixes unhandled interrupt when HW rfkill is on during devices start up. The behavior changes, now open is successful even when rfkill is on. This is to align with the situation when rfkill is set on after opening. Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-agn.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6503b3ac8d66..b8407d5704a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2232,17 +2232,16 @@ static int __iwl4965_up(struct iwl_priv *priv) } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->status); else set_bit(STATUS_RF_KILL_HW, &priv->status); - if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && - iwl_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { + iwl4965_enable_interrupts(priv); IWL_WARNING("Radio disabled by %s RF Kill switch\n", test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); - return -ENODEV; + return 0; } iwl_write32(priv, CSR_INT, 0xFFFFFFFF); @@ -2278,11 +2277,6 @@ static int __iwl4965_up(struct iwl_priv *priv) memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, priv->ucode_data.len); - /* We return success when we resume from suspend and rf_kill is on. */ - if (test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status)) - return 0; - for (i = 0; i < MAX_HW_RESTARTS; i++) { iwl_clear_stations_table(priv); @@ -2651,6 +2645,9 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) if (ret) goto out_release_irq; + if (iwl_is_rfkill(priv)) + goto out; + IWL_DEBUG_INFO("Start UP work done.\n"); if (test_bit(STATUS_IN_SUSPEND, &priv->status)) @@ -2670,6 +2667,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) } } +out: priv->is_open = 1; IWL_DEBUG_MAC80211("leave\n"); return 0; From 14652562364dad636ddce2cd11e71702ca21bfbd Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 4 Aug 2008 16:00:46 +0800 Subject: [PATCH 66/78] iwlwifi: decrement rx skb counter in scan abort handler This patch decrements rx skb counter in scan abort handler. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-scan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 5a00ac23e2d0..9bb6adb28b73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -202,6 +202,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv) clear_bit(STATUS_SCAN_HW, &priv->status); } + priv->alloc_rxb_skb--; dev_kfree_skb_any(cmd.meta.u.skb); return ret; From 2d3db679511be102741cb2d5f8c2b8a1ededdee7 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 4 Aug 2008 16:00:47 +0800 Subject: [PATCH 67/78] iwlwifi: grap nic access before accessing periphery registers We need to grap nic access before accessing periphery registers. Signed-off-by: Tomas Winkler Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-5000.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c5b104fd149c..f3d139b663e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -241,9 +241,11 @@ static void iwl5000_nic_config(struct iwl_priv *priv) * (PCIe power is lost before PERST# is asserted), * causing ME FW to lose ownership and not being able to obtain it back. */ - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_grab_nic_access(priv); + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); } From 3e2236c108792c3afbbfbe3f373ee7fdd68eda8e Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 4 Aug 2008 16:00:48 +0800 Subject: [PATCH 68/78] iwl3945: fix merge mistake for packet injection We should allow packets transmission in monitor mode for 3945. The patch fixes a merge error with 2.6.26 kernel. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index eb41b02b506d..444847ab1b5a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6589,12 +6589,6 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) IWL_DEBUG_MAC80211("enter\n"); - if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - IWL_DEBUG_MAC80211("leave - monitor\n"); - dev_kfree_skb_any(skb); - return 0; - } - IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); From 378a2f090f7a478704a372a4869b8a9ac206234e Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 4 Aug 2008 22:31:03 -0700 Subject: [PATCH 69/78] net_sched: Add qdisc __NET_XMIT_STOLEN flag Patrick McHardy noticed: "The other problem that affects all qdiscs supporting actions is TC_ACT_QUEUED/TC_ACT_STOLEN getting mapped to NET_XMIT_SUCCESS even though the packet is not queued, corrupting upper qdiscs' qlen counters." and later explained: "The reason why it translates it at all seems to be to not increase the drops counter. Within a single qdisc this could be avoided by other means easily, upper qdiscs would still increase the counter when we return anything besides NET_XMIT_SUCCESS though. This means we need a new NET_XMIT return value to indicate this to the upper qdiscs. So I'd suggest to introduce NET_XMIT_STOLEN, return that to upper qdiscs and translate it to NET_XMIT_SUCCESS in dev_queue_xmit, similar to NET_XMIT_BYPASS." David Miller noticed: "Maybe these NET_XMIT_* values being passed around should be a set of bits. They could be composed of base meanings, combined with specific attributes. So you could say "NET_XMIT_DROP | __NET_XMIT_NO_DROP_COUNT" The attributes get masked out by the top-level ->enqueue() caller, such that the base meanings are the only thing that make their way up into the stack. If it's only about communication within the qdisc tree, let's simply code it that way." This patch is trying to realize these ideas. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- include/linux/netdevice.h | 1 + include/net/sch_generic.h | 14 +++++++++++++- net/sched/sch_atm.c | 12 +++++++----- net/sched/sch_cbq.c | 23 +++++++++++++++-------- net/sched/sch_dsmark.c | 8 +++++--- net/sched/sch_hfsc.c | 8 +++++--- net/sched/sch_htb.c | 18 +++++++++++------- net/sched/sch_netem.c | 3 ++- net/sched/sch_prio.c | 8 +++++--- net/sched/sch_red.c | 2 +- net/sched/sch_sfq.c | 2 +- net/sched/sch_tbf.c | 3 ++- 12 files changed, 68 insertions(+), 34 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index ee583f642a9f..abbf5d52ec86 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -64,6 +64,7 @@ struct wireless_dev; #define NET_XMIT_BYPASS 4 /* packet does not leave via dequeue; (TC use only - dev_queue_xmit returns this as NET_XMIT_SUCCESS) */ +#define NET_XMIT_MASK 0xFFFF /* qdisc flags in net/sch_generic.h */ /* Backlog congestion levels */ #define NET_RX_SUCCESS 0 /* keep 'em coming, baby */ diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index c5bb13065051..f15b045a85e9 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -343,6 +343,18 @@ static inline unsigned int qdisc_pkt_len(struct sk_buff *skb) return qdisc_skb_cb(skb)->pkt_len; } +#ifdef CONFIG_NET_CLS_ACT +/* additional qdisc xmit flags */ +enum net_xmit_qdisc_t { + __NET_XMIT_STOLEN = 0x00010000, +}; + +#define net_xmit_drop_count(e) ((e) & __NET_XMIT_STOLEN ? 0 : 1) + +#else +#define net_xmit_drop_count(e) (1) +#endif + static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) { #ifdef CONFIG_NET_SCHED @@ -355,7 +367,7 @@ static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch) { qdisc_skb_cb(skb)->pkt_len = skb->len; - return qdisc_enqueue(skb, sch); + return qdisc_enqueue(skb, sch) & NET_XMIT_MASK; } static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch, diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 6b517b9dac5b..27dd773481bc 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -415,7 +415,7 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) case TC_ACT_QUEUED: case TC_ACT_STOLEN: kfree_skb(skb); - return NET_XMIT_SUCCESS; + return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: kfree_skb(skb); goto drop; @@ -432,9 +432,11 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch) ret = qdisc_enqueue(skb, flow->q); if (ret != 0) { drop: __maybe_unused - sch->qstats.drops++; - if (flow) - flow->qstats.drops++; + if (net_xmit_drop_count(ret)) { + sch->qstats.drops++; + if (flow) + flow->qstats.drops++; + } return ret; } sch->bstats.bytes += qdisc_pkt_len(skb); @@ -530,7 +532,7 @@ static int atm_tc_requeue(struct sk_buff *skb, struct Qdisc *sch) if (!ret) { sch->q.qlen++; sch->qstats.requeues++; - } else { + } else if (net_xmit_drop_count(ret)) { sch->qstats.drops++; p->link.qstats.drops++; } diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 14954bf4a683..765ae5659000 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -256,7 +256,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) switch (result) { case TC_ACT_QUEUED: case TC_ACT_STOLEN: - *qerr = NET_XMIT_SUCCESS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: return NULL; case TC_ACT_RECLASSIFY: @@ -397,9 +397,11 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) return ret; } - sch->qstats.drops++; - cbq_mark_toplevel(q, cl); - cl->qstats.drops++; + if (net_xmit_drop_count(ret)) { + sch->qstats.drops++; + cbq_mark_toplevel(q, cl); + cl->qstats.drops++; + } return ret; } @@ -430,8 +432,10 @@ cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) cbq_activate_class(cl); return 0; } - sch->qstats.drops++; - cl->qstats.drops++; + if (net_xmit_drop_count(ret)) { + sch->qstats.drops++; + cl->qstats.drops++; + } return ret; } @@ -664,13 +668,15 @@ static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) q->rx_class = NULL; if (cl && (cl = cbq_reclassify(skb, cl)) != NULL) { + int ret; cbq_mark_toplevel(q, cl); q->rx_class = cl; cl->q->__parent = sch; - if (qdisc_enqueue(skb, cl->q) == 0) { + ret = qdisc_enqueue(skb, cl->q); + if (ret == NET_XMIT_SUCCESS) { sch->q.qlen++; sch->bstats.packets++; sch->bstats.bytes += qdisc_pkt_len(skb); @@ -678,7 +684,8 @@ static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child) cbq_activate_class(cl); return 0; } - sch->qstats.drops++; + if (net_xmit_drop_count(ret)) + sch->qstats.drops++; return 0; } diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index a935676987e2..7170275d9f99 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -236,7 +236,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) case TC_ACT_QUEUED: case TC_ACT_STOLEN: kfree_skb(skb); - return NET_XMIT_SUCCESS; + return NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: goto drop; @@ -254,7 +254,8 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) err = qdisc_enqueue(skb, p->q); if (err != NET_XMIT_SUCCESS) { - sch->qstats.drops++; + if (net_xmit_drop_count(err)) + sch->qstats.drops++; return err; } @@ -321,7 +322,8 @@ static int dsmark_requeue(struct sk_buff *skb, struct Qdisc *sch) err = p->q->ops->requeue(skb, p->q); if (err != NET_XMIT_SUCCESS) { - sch->qstats.drops++; + if (net_xmit_drop_count(err)) + sch->qstats.drops++; return err; } diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 0ae7d19dcba8..5cf9ae716118 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1166,7 +1166,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) switch (result) { case TC_ACT_QUEUED: case TC_ACT_STOLEN: - *qerr = NET_XMIT_SUCCESS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: return NULL; } @@ -1586,8 +1586,10 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) err = qdisc_enqueue(skb, cl->qdisc); if (unlikely(err != NET_XMIT_SUCCESS)) { - cl->qstats.drops++; - sch->qstats.drops++; + if (net_xmit_drop_count(err)) { + cl->qstats.drops++; + sch->qstats.drops++; + } return err; } diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 75a40951c4f2..538d79b489ae 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -221,7 +221,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, switch (result) { case TC_ACT_QUEUED: case TC_ACT_STOLEN: - *qerr = NET_XMIT_SUCCESS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: return NULL; } @@ -572,9 +572,11 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) kfree_skb(skb); return ret; #endif - } else if (qdisc_enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) { - sch->qstats.drops++; - cl->qstats.drops++; + } else if ((ret = qdisc_enqueue(skb, cl->un.leaf.q)) != NET_XMIT_SUCCESS) { + if (net_xmit_drop_count(ret)) { + sch->qstats.drops++; + cl->qstats.drops++; + } return NET_XMIT_DROP; } else { cl->bstats.packets += @@ -615,10 +617,12 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) kfree_skb(skb); return ret; #endif - } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != + } else if ((ret = cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q)) != NET_XMIT_SUCCESS) { - sch->qstats.drops++; - cl->qstats.drops++; + if (net_xmit_drop_count(ret)) { + sch->qstats.drops++; + cl->qstats.drops++; + } return NET_XMIT_DROP; } else htb_activate(q, cl); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index a59085700678..6cd6f2bc749e 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -240,8 +240,9 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) sch->q.qlen++; sch->bstats.bytes += qdisc_pkt_len(skb); sch->bstats.packets++; - } else + } else if (net_xmit_drop_count(ret)) { sch->qstats.drops++; + } pr_debug("netem: enqueue ret %d\n", ret); return ret; diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index f849243eb095..adb1a52b77d3 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -45,7 +45,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) switch (err) { case TC_ACT_STOLEN: case TC_ACT_QUEUED: - *qerr = NET_XMIT_SUCCESS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: return NULL; } @@ -88,7 +88,8 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) sch->q.qlen++; return NET_XMIT_SUCCESS; } - sch->qstats.drops++; + if (net_xmit_drop_count(ret)) + sch->qstats.drops++; return ret; } @@ -114,7 +115,8 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch) sch->qstats.requeues++; return 0; } - sch->qstats.drops++; + if (net_xmit_drop_count(ret)) + sch->qstats.drops++; return NET_XMIT_DROP; } diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 3f2d1d7f3bbd..5da05839e225 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -97,7 +97,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) sch->bstats.bytes += qdisc_pkt_len(skb); sch->bstats.packets++; sch->q.qlen++; - } else { + } else if (net_xmit_drop_count(ret)) { q->stats.pdrop++; sch->qstats.drops++; } diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 8589da666568..3a456e1b829a 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -178,7 +178,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, switch (result) { case TC_ACT_STOLEN: case TC_ACT_QUEUED: - *qerr = NET_XMIT_SUCCESS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; case TC_ACT_SHOT: return 0; } diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index b296672f7632..7d3b7ff3bf07 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -135,7 +135,8 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) ret = qdisc_enqueue(skb, q->qdisc); if (ret != 0) { - sch->qstats.drops++; + if (net_xmit_drop_count(ret)) + sch->qstats.drops++; return ret; } From c27f339af90bb874a7a9c680b17abfd32d4a727b Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Mon, 4 Aug 2008 22:39:11 -0700 Subject: [PATCH 70/78] net_sched: Add qdisc __NET_XMIT_BYPASS flag Patrick McHardy noticed that it would be nice to handle NET_XMIT_BYPASS by NET_XMIT_SUCCESS with an internal qdisc flag __NET_XMIT_BYPASS and to remove the mapping from dev_queue_xmit(). David Miller spotted a serious bug in the first version of this patch. Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- include/net/sch_generic.h | 6 +++--- net/core/dev.c | 1 - net/sched/sch_atm.c | 2 +- net/sched/sch_cbq.c | 4 ++-- net/sched/sch_dsmark.c | 2 +- net/sched/sch_hfsc.c | 4 ++-- net/sched/sch_htb.c | 6 +++--- net/sched/sch_netem.c | 2 +- net/sched/sch_prio.c | 6 +++--- net/sched/sch_sfq.c | 6 +++--- 10 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index f15b045a85e9..a7abfda3e447 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -343,14 +343,14 @@ static inline unsigned int qdisc_pkt_len(struct sk_buff *skb) return qdisc_skb_cb(skb)->pkt_len; } -#ifdef CONFIG_NET_CLS_ACT -/* additional qdisc xmit flags */ +/* additional qdisc xmit flags (NET_XMIT_MASK in linux/netdevice.h) */ enum net_xmit_qdisc_t { __NET_XMIT_STOLEN = 0x00010000, + __NET_XMIT_BYPASS = 0x00020000, }; +#ifdef CONFIG_NET_CLS_ACT #define net_xmit_drop_count(e) ((e) & __NET_XMIT_STOLEN ? 0 : 1) - #else #define net_xmit_drop_count(e) (1) #endif diff --git a/net/core/dev.c b/net/core/dev.c index fc6c9881eca8..01993ad74e76 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1805,7 +1805,6 @@ gso: spin_unlock(root_lock); - rc = rc == NET_XMIT_BYPASS ? NET_XMIT_SUCCESS : rc; goto out; } diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 27dd773481bc..43d37256c15e 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -457,7 +457,7 @@ drop: __maybe_unused return 0; } tasklet_schedule(&p->task); - return NET_XMIT_BYPASS; + return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; } /* diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 765ae5659000..4e261ce62f48 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -230,7 +230,7 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) (cl = cbq_class_lookup(q, prio)) != NULL) return cl; - *qerr = NET_XMIT_BYPASS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; for (;;) { int result = 0; defmap = head->defaults; @@ -377,7 +377,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->rx_class = cl; #endif if (cl == NULL) { - if (ret == NET_XMIT_BYPASS) + if (ret & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c index 7170275d9f99..edd1298f85f6 100644 --- a/net/sched/sch_dsmark.c +++ b/net/sched/sch_dsmark.c @@ -268,7 +268,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch) drop: kfree_skb(skb); sch->qstats.drops++; - return NET_XMIT_BYPASS; + return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; } static struct sk_buff *dsmark_dequeue(struct Qdisc *sch) diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 5cf9ae716118..c2b8d9cce3d2 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -1159,7 +1159,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) if (cl->level == 0) return cl; - *qerr = NET_XMIT_BYPASS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; tcf = q->root.filter_list; while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { #ifdef CONFIG_NET_CLS_ACT @@ -1578,7 +1578,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch) cl = hfsc_classify(skb, sch, &err); if (cl == NULL) { - if (err == NET_XMIT_BYPASS) + if (err & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return err; diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 538d79b489ae..be35422711a3 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -214,7 +214,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, if ((cl = htb_find(skb->priority, sch)) != NULL && cl->level == 0) return cl; - *qerr = NET_XMIT_BYPASS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; tcf = q->filter_list; while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) { #ifdef CONFIG_NET_CLS_ACT @@ -567,7 +567,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) } #ifdef CONFIG_NET_CLS_ACT } else if (!cl) { - if (ret == NET_XMIT_BYPASS) + if (ret & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; @@ -612,7 +612,7 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) } #ifdef CONFIG_NET_CLS_ACT } else if (!cl) { - if (ret == NET_XMIT_BYPASS) + if (ret & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 6cd6f2bc749e..fb0294d0b55e 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -176,7 +176,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (count == 0) { sch->qstats.drops++; kfree_skb(skb); - return NET_XMIT_BYPASS; + return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; } skb_orphan(skb); diff --git a/net/sched/sch_prio.c b/net/sched/sch_prio.c index adb1a52b77d3..eac197610edf 100644 --- a/net/sched/sch_prio.c +++ b/net/sched/sch_prio.c @@ -38,7 +38,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) struct tcf_result res; int err; - *qerr = NET_XMIT_BYPASS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; if (TC_H_MAJ(skb->priority) != sch->handle) { err = tc_classify(skb, q->filter_list, &res); #ifdef CONFIG_NET_CLS_ACT @@ -74,7 +74,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch) #ifdef CONFIG_NET_CLS_ACT if (qdisc == NULL) { - if (ret == NET_XMIT_BYPASS) + if (ret & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; @@ -103,7 +103,7 @@ prio_requeue(struct sk_buff *skb, struct Qdisc* sch) qdisc = prio_classify(skb, sch, &ret); #ifdef CONFIG_NET_CLS_ACT if (qdisc == NULL) { - if (ret == NET_XMIT_BYPASS) + if (ret & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index 3a456e1b829a..6e041d10dbdb 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c @@ -171,7 +171,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch, if (!q->filter_list) return sfq_hash(q, skb) + 1; - *qerr = NET_XMIT_BYPASS; + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; result = tc_classify(skb, q->filter_list, &res); if (result >= 0) { #ifdef CONFIG_NET_CLS_ACT @@ -285,7 +285,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) hash = sfq_classify(skb, sch, &ret); if (hash == 0) { - if (ret == NET_XMIT_BYPASS) + if (ret & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; @@ -339,7 +339,7 @@ sfq_requeue(struct sk_buff *skb, struct Qdisc *sch) hash = sfq_classify(skb, sch, &ret); if (hash == 0) { - if (ret == NET_XMIT_BYPASS) + if (ret & __NET_XMIT_BYPASS) sch->qstats.drops++; kfree_skb(skb); return ret; From cc6533e98a7f3cb7fce9d740da49195c7aa523a4 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 4 Aug 2008 23:04:08 -0700 Subject: [PATCH 71/78] net: Kill plain NET_XMIT_BYPASS. dst_input() was doing something completely absurd, looping on skb->dst->input() if NET_XMIT_BYPASS was seen, but these functions never return such an error. And as a result plain ole' NET_XMIT_BYPASS has no more references and can be completely killed off. Signed-off-by: David S. Miller --- include/linux/netdevice.h | 3 --- include/net/dst.h | 12 +----------- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index abbf5d52ec86..488c56e649b5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -61,9 +61,6 @@ struct wireless_dev; #define NET_XMIT_DROP 1 /* skb dropped */ #define NET_XMIT_CN 2 /* congestion notification */ #define NET_XMIT_POLICED 3 /* skb is shot by police */ -#define NET_XMIT_BYPASS 4 /* packet does not leave via dequeue; - (TC use only - dev_queue_xmit - returns this as NET_XMIT_SUCCESS) */ #define NET_XMIT_MASK 0xFFFF /* qdisc flags in net/sch_generic.h */ /* Backlog congestion levels */ diff --git a/include/net/dst.h b/include/net/dst.h index c5c318a628f8..8a8b71e5f3f1 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -252,17 +252,7 @@ static inline int dst_output(struct sk_buff *skb) /* Input packet from network to transport. */ static inline int dst_input(struct sk_buff *skb) { - int err; - - for (;;) { - err = skb->dst->input(skb); - - if (likely(err == 0)) - return err; - /* Oh, Jamal... Seems, I will not forgive you this mess. :-) */ - if (unlikely(err != NET_XMIT_BYPASS)) - return err; - } + return skb->dst->input(skb); } static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie) From 2f751b67a8be698cec52f786910ef4f0beffe9a7 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Mon, 4 Aug 2008 23:17:34 -0700 Subject: [PATCH 72/78] tg3: Fix 'scheduling while atomic' errors This patch fixes the 'scheduling while atomic' errors introduced by commit 12dac0756d357325b107fe6ec24921ec38661839 ("tg3: adapt tg3 to use reworked PCI PM code"). The first hunk of the patch removes an unnecessary tg3_set_power_state() call. The chip will already be in the D0 state either due to a chip reset or through a previous call to tg3_set_power_state(). The second hunk of the patch moves the tg3_set_power_state() call outside the critical section guarded by tg3_full_lock() and tg3_full_unlock() functions. The power state of the device is and should be outside the lock's domain and all other tg3_set_power_state() calls support this. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 26aa37aa531f..d2439b85a790 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7687,21 +7687,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) */ static int tg3_init_hw(struct tg3 *tp, int reset_phy) { - int err; - - /* Force the chip into D0. */ - err = tg3_set_power_state(tp, PCI_D0); - if (err) - goto out; - tg3_switch_clocks(tp); tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); - err = tg3_reset_hw(tp, reset_phy); - -out: - return err; + return tg3_reset_hw(tp, reset_phy); } #define TG3_STAT_ADD32(PSTAT, REG) \ @@ -8016,13 +8006,11 @@ static int tg3_open(struct net_device *dev) netif_carrier_off(tp->dev); - tg3_full_lock(tp, 0); - err = tg3_set_power_state(tp, PCI_D0); - if (err) { - tg3_full_unlock(tp); + if (err) return err; - } + + tg3_full_lock(tp, 0); tg3_disable_ints(tp); tp->tg3_flags &= ~TG3_FLAG_INIT_COMPLETE; From 95c3e8bfcdea8676e2d4d61910c379f4502049bf Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Tue, 5 Aug 2008 01:19:50 -0700 Subject: [PATCH 73/78] ipv4: remove unused field in struct flowi (include/net/flow.h). This patch removes an unused field (flags) from struct flowi; it seems that this "flags" field was used once in the past for multipath routing with FLOWI_FLAG_MULTIPATHOLDROUTE flag (which does no longer exist); however, the "flags" field of struct flowi is not used anymore. Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- include/net/flow.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/flow.h b/include/net/flow.h index ad16e0076c89..228b2477ceec 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -47,7 +47,6 @@ struct flowi { #define fl4_scope nl_u.ip4_u.scope __u8 proto; - __u8 flags; union { struct { __be16 sport; From ad619800e4e034cad44299b2a22df9eebb043ac3 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Tue, 5 Aug 2008 01:21:22 -0700 Subject: [PATCH 74/78] bridge: fix compile warning in net/bridge/br_netfilter.c This patch fixes the following warning due to incompatible pointer assignment: net/bridge/br_netfilter.c: In function 'br_netfilter_rtable_init': net/bridge/br_netfilter.c:116: warning: assignment from incompatible pointer type This warning is due to commit 4adf0af6818f3ea52421dc0bae836cfaf20ef72a from July 30 (send correct MTU value in PMTU (revised)). Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- net/bridge/br_netfilter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 6e280a8a31ee..6a9a6cd74b1e 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -113,7 +113,7 @@ void br_netfilter_rtable_init(struct net_bridge *br) struct rtable *rt = &br->fake_rtable; atomic_set(&rt->u.dst.__refcnt, 1); - rt->u.dst.dev = &br->dev; + rt->u.dst.dev = br->dev; rt->u.dst.path = &rt->u.dst; rt->u.dst.metrics[RTAX_MTU - 1] = 1500; rt->u.dst.flags = DST_NOXFRM; From ef647f1300d69adb8223d970554d59d7e244db6d Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 5 Aug 2008 18:42:51 -0700 Subject: [PATCH 75/78] bridge: Eliminate unnecessary forward delay From: Stephen Hemminger Based upon original patch by Herbert Xu, which contained the following problem description: -------------------- When the forward delay is set to zero, we still delay the setting of the forwarding state by one or possibly two timers depending on whether STP is enabled. This could either turn out to be instantaneous, or horribly slow depending on the load of the machine. As there is nothing preventing us from enabling forwarding straight away, this patch eliminates this potential delay by executing the code directly if the forward delay is zero. The effect of this problem is that immediately after the carrier comes on a port, the bridge will drop all packets received from that port until it enters forwarding mode, thus causing unnecessary packet loss. Note that this patch doesn't fully remove the delay due to the link watcher. We should also check the carrier state when we are about to drop an incoming packet because the port is disabled. But that's for another patch. -------------------- This version of the fix takes a different approach, in that it just does the state change directly. Signed-off-by: David S. Miller --- net/bridge/br_stp.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 921bbe5cb94a..6e63ec3f1fcf 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -368,14 +368,25 @@ static void br_make_blocking(struct net_bridge_port *p) /* called under bridge lock */ static void br_make_forwarding(struct net_bridge_port *p) { - if (p->state == BR_STATE_BLOCKING) { - if (p->br->stp_enabled == BR_KERNEL_STP) - p->state = BR_STATE_LISTENING; - else - p->state = BR_STATE_LEARNING; + struct net_bridge *br = p->br; - br_log_state(p); - mod_timer(&p->forward_delay_timer, jiffies + p->br->forward_delay); } + if (p->state != BR_STATE_BLOCKING) + return; + + if (br->forward_delay == 0) { + p->state = BR_STATE_FORWARDING; + br_topology_change_detection(br); + del_timer(&p->forward_delay_timer); + } + else if (p->br->stp_enabled == BR_KERNEL_STP) + p->state = BR_STATE_LISTENING; + else + p->state = BR_STATE_LEARNING; + + br_log_state(p); + + if (br->forward_delay != 0) + mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay); } /* called under bridge lock */ From 1211a64554065316e02b3c62b320088ad4f63260 Mon Sep 17 00:00:00 2001 From: Robert Olsson Date: Tue, 5 Aug 2008 18:44:26 -0700 Subject: [PATCH 76/78] pktgen: random flow Random flow generation has not worked. This fixes it. Signed-off-by: Robert Olsson Signed-off-by: David S. Miller --- net/core/pktgen.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 3284605f2ec7..9c87320fdf3f 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2085,15 +2085,19 @@ static inline int f_pick(struct pktgen_dev *pkt_dev) if (pkt_dev->flows[flow].count >= pkt_dev->lflow) { /* reset time */ pkt_dev->flows[flow].count = 0; + pkt_dev->flows[flow].flags = 0; pkt_dev->curfl += 1; if (pkt_dev->curfl >= pkt_dev->cflows) pkt_dev->curfl = 0; /*reset */ } } else { flow = random32() % pkt_dev->cflows; + pkt_dev->curfl = flow; - if (pkt_dev->flows[flow].count > pkt_dev->lflow) + if (pkt_dev->flows[flow].count > pkt_dev->lflow) { pkt_dev->flows[flow].count = 0; + pkt_dev->flows[flow].flags = 0; + } } return pkt_dev->curfl; From ff2a79a5a934fe0dbb136ffad61f79b5c6385614 Mon Sep 17 00:00:00 2001 From: Robert Olsson Date: Tue, 5 Aug 2008 18:45:05 -0700 Subject: [PATCH 77/78] pktgen: mac count dst_mac_count and src_mac_count patch from Eneas Hunguana We have sent one mac address to much. Signed-off-by: Robert Olsson Signed-off-by: David S. Miller --- net/core/pktgen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 9c87320fdf3f..2498cdaf8cbe 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2166,7 +2166,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) mc = random32() % pkt_dev->src_mac_count; else { mc = pkt_dev->cur_src_mac_offset++; - if (pkt_dev->cur_src_mac_offset > + if (pkt_dev->cur_src_mac_offset >= pkt_dev->src_mac_count) pkt_dev->cur_src_mac_offset = 0; } @@ -2193,7 +2193,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev) else { mc = pkt_dev->cur_dst_mac_offset++; - if (pkt_dev->cur_dst_mac_offset > + if (pkt_dev->cur_dst_mac_offset >= pkt_dev->dst_mac_count) { pkt_dev->cur_dst_mac_offset = 0; } From ffb208479bd62ab26c29a242faeb1de1c6d5fcdc Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Tue, 5 Aug 2008 18:46:57 -0700 Subject: [PATCH 78/78] AX.25: Fix sysctl registration if !CONFIG_AX25_DAMA_SLAVE Since 49ffcf8f99e8d33ec8afb450956804af518fd788 ("sysctl: update sysctl_check_table") setting struct ctl_table.procname = NULL does no longer work as it used to the way the AX.25 code is expecting it to resulting in the AX.25 sysctl registration code to break if CONFIG_AX25_DAMA_SLAVE was not set as in some distribution kernels. Kernel releases from 2.6.24 are affected. Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- net/ax25/sysctl_net_ax25.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index f597987b2424..f288fc4aef9b 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -36,6 +36,7 @@ static struct ctl_path ax25_path[] = { { .procname = "ax25", .ctl_name = NET_AX25, }, { } }; + static const ctl_table ax25_param_table[] = { { .ctl_name = NET_AX25_IP_DEFAULT_MODE, @@ -167,6 +168,7 @@ static const ctl_table ax25_param_table[] = { .extra1 = &min_proto, .extra2 = &max_proto }, +#ifdef CONFIG_AX25_DAMA_SLAVE { .ctl_name = NET_AX25_DAMA_SLAVE_TIMEOUT, .procname = "dama_slave_timeout", @@ -177,6 +179,8 @@ static const ctl_table ax25_param_table[] = { .extra1 = &min_ds_timeout, .extra2 = &max_ds_timeout }, +#endif + { .ctl_name = 0 } /* that's all, folks! */ }; @@ -210,16 +214,6 @@ void ax25_register_sysctl(void) ax25_table[n].procname = ax25_dev->dev->name; ax25_table[n].mode = 0555; -#ifndef CONFIG_AX25_DAMA_SLAVE - /* - * We do not wish to have a representation of this parameter - * in /proc/sys/ when configured *not* to include the - * AX.25 DAMA slave code, do we? - */ - - child[AX25_VALUES_DS_TIMEOUT].procname = NULL; -#endif - child[AX25_MAX_VALUES].ctl_name = 0; /* just in case... */ for (k = 0; k < AX25_MAX_VALUES; k++)