Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller 2009-11-09 11:17:24 -08:00
commit f6d773cd4f
147 changed files with 8315 additions and 9872 deletions

View file

@ -16,118 +16,9 @@ menuconfig WLAN
if WLAN
menuconfig WLAN_PRE80211
bool "Wireless LAN (pre-802.11)"
depends on NETDEVICES
---help---
Say Y if you have any pre-802.11 wireless LAN hardware.
This option does not affect the kernel build, it only
lets you choose drivers.
config STRIP
tristate "STRIP (Metricom starmode radio IP)"
depends on INET && WLAN_PRE80211
select WIRELESS_EXT
---help---
Say Y if you have a Metricom radio and intend to use Starmode Radio
IP. STRIP is a radio protocol developed for the MosquitoNet project
to send Internet traffic using Metricom radios. Metricom radios are
small, battery powered, 100kbit/sec packet radio transceivers, about
the size and weight of a cellular telephone. (You may also have heard
them called "Metricom modems" but we avoid the term "modem" because
it misleads many people into thinking that you can plug a Metricom
modem into a phone line and use it as a modem.)
You can use STRIP on any Linux machine with a serial port, although
it is obviously most useful for people with laptop computers. If you
think you might get a Metricom radio in the future, there is no harm
in saying Y to STRIP now, except that it makes the kernel a bit
bigger.
To compile this as a module, choose M here: the module will be
called strip.
config ARLAN
tristate "Aironet Arlan 655 & IC2200 DS support"
depends on ISA && !64BIT && WLAN_PRE80211
select WIRELESS_EXT
---help---
Aironet makes Arlan, a class of wireless LAN adapters. These use the
www.Telxon.com chip, which is also used on several similar cards.
This driver is tested on the 655 and IC2200 series cards. Look at
<http://www.ylenurme.ee/~elmer/655/> for the latest information.
The driver is built as two modules, arlan and arlan-proc. The latter
is the /proc interface and is not needed most of time.
On some computers the card ends up in non-valid state after some
time. Use a ping-reset script to clear it.
config WAVELAN
tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
depends on ISA && WLAN_PRE80211
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
---help---
The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is
a Radio LAN (wireless Ethernet-like Local Area Network) using the
radio frequencies 900 MHz and 2.4 GHz.
If you want to use an ISA WaveLAN card under Linux, say Y and read
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>. Some more specific
information is contained in
<file:Documentation/networking/wavelan.txt> and in the source code
<file:drivers/net/wireless/wavelan.p.h>.
You will also need the wireless tools package available from
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
Please read the man pages contained therein.
To compile this driver as a module, choose M here: the module will be
called wavelan.
config PCMCIA_WAVELAN
tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
depends on PCMCIA && WLAN_PRE80211
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
help
Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA
(PC-card) wireless Ethernet networking card to your computer. This
driver is for the non-IEEE-802.11 Wavelan cards.
To compile this driver as a module, choose M here: the module will be
called wavelan_cs. If unsure, say N.
config PCMCIA_NETWAVE
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
depends on PCMCIA && WLAN_PRE80211
select WIRELESS_EXT
select WEXT_PRIV
help
Say Y here if you intend to attach this type of PCMCIA (PC-card)
wireless Ethernet networking card to your computer.
To compile this driver as a module, choose M here: the module will be
called netwave_cs. If unsure, say N.
menuconfig WLAN_80211
bool "Wireless LAN (IEEE 802.11)"
depends on NETDEVICES
---help---
Say Y if you have any 802.11 wireless LAN hardware.
This option does not affect the kernel build, it only
lets you choose drivers.
config PCMCIA_RAYCS
tristate "Aviator/Raytheon 2.4GHz wireless support"
depends on PCMCIA && WLAN_80211
depends on PCMCIA
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
@ -142,7 +33,7 @@ config PCMCIA_RAYCS
config LIBERTAS_THINFIRM
tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
depends on WLAN_80211 && MAC80211
depends on MAC80211
select FW_LOADER
---help---
A library for Marvell Libertas 8xxx devices using thinfirm.
@ -155,7 +46,7 @@ config LIBERTAS_THINFIRM_USB
config AIRO
tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN)
depends on ISA_DMA_API && (PCI || BROKEN)
select WIRELESS_EXT
select CRYPTO
select WEXT_SPY
@ -175,7 +66,7 @@ config AIRO
config ATMEL
tristate "Atmel at76c50x chipset 802.11b support"
depends on (PCI || PCMCIA) && WLAN_80211
depends on (PCI || PCMCIA)
select WIRELESS_EXT
select WEXT_PRIV
select FW_LOADER
@ -210,7 +101,7 @@ config PCMCIA_ATMEL
config AT76C50X_USB
tristate "Atmel at76c503/at76c505/at76c505a USB cards"
depends on MAC80211 && WLAN_80211 && USB
depends on MAC80211 && USB
select FW_LOADER
---help---
Enable support for USB Wireless devices using Atmel at76c503,
@ -218,8 +109,9 @@ config AT76C50X_USB
config AIRO_CS
tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards"
depends on PCMCIA && (BROKEN || !M32R) && WLAN_80211
depends on PCMCIA && (BROKEN || !M32R)
select WIRELESS_EXT
select WEXT_SPY
select CRYPTO
select CRYPTO_AES
---help---
@ -238,7 +130,7 @@ config AIRO_CS
config PCMCIA_WL3501
tristate "Planet WL3501 PCMCIA cards"
depends on EXPERIMENTAL && PCMCIA && WLAN_80211
depends on EXPERIMENTAL && PCMCIA
select WIRELESS_EXT
select WEXT_SPY
help
@ -248,7 +140,7 @@ config PCMCIA_WL3501
config PRISM54
tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)'
depends on PCI && EXPERIMENTAL && WLAN_80211
depends on PCI && EXPERIMENTAL
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
@ -272,7 +164,7 @@ config PRISM54
config USB_ZD1201
tristate "USB ZD1201 based Wireless device support"
depends on USB && WLAN_80211
depends on USB
select WIRELESS_EXT
select WEXT_PRIV
select FW_LOADER
@ -291,7 +183,7 @@ config USB_ZD1201
config USB_NET_RNDIS_WLAN
tristate "Wireless RNDIS USB support"
depends on USB && WLAN_80211 && EXPERIMENTAL
depends on USB && EXPERIMENTAL
depends on CFG80211
select USB_USBNET
select USB_NET_CDCETHER
@ -319,7 +211,7 @@ config USB_NET_RNDIS_WLAN
config RTL8180
tristate "Realtek 8180/8185 PCI support"
depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
depends on MAC80211 && PCI && EXPERIMENTAL
select EEPROM_93CX6
---help---
This is a driver for RTL8180 and RTL8185 based cards.
@ -375,7 +267,7 @@ config RTL8180
config RTL8187
tristate "Realtek 8187 and 8187B USB support"
depends on MAC80211 && USB && WLAN_80211
depends on MAC80211 && USB
select EEPROM_93CX6
---help---
This is a driver for RTL8187 and RTL8187B based cards.
@ -404,7 +296,7 @@ config RTL8187_LEDS
config ADM8211
tristate "ADMtek ADM8211 support"
depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
depends on MAC80211 && PCI && EXPERIMENTAL
select CRC32
select EEPROM_93CX6
---help---
@ -431,7 +323,7 @@ config ADM8211
config MAC80211_HWSIM
tristate "Simulated radio testing tool for mac80211"
depends on MAC80211 && WLAN_80211
depends on MAC80211
---help---
This driver is a developer testing tool that can be used to test
IEEE 802.11 networking stack (mac80211) functionality. This is not
@ -444,7 +336,7 @@ config MAC80211_HWSIM
config MWL8K
tristate "Marvell 88W8xxx PCI/PCIe Wireless support"
depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
depends on MAC80211 && PCI && EXPERIMENTAL
---help---
This driver supports Marvell TOPDOG 802.11 wireless cards.

View file

@ -5,16 +5,6 @@
obj-$(CONFIG_IPW2100) += ipw2x00/
obj-$(CONFIG_IPW2200) += ipw2x00/
obj-$(CONFIG_STRIP) += strip.o
obj-$(CONFIG_ARLAN) += arlan.o
arlan-objs := arlan-main.o arlan-proc.o
# Obsolete cards
obj-$(CONFIG_WAVELAN) += wavelan.o
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o
obj-$(CONFIG_HERMES) += orinoco/
obj-$(CONFIG_AIRO) += airo.o

View file

@ -1,6 +1,5 @@
menuconfig ATH_COMMON
tristate "Atheros Wireless Cards"
depends on WLAN_80211
depends on CFG80211
---help---
This will enable the support for the Atheros wireless drivers.

View file

@ -1,6 +1,6 @@
config AR9170_USB
tristate "Atheros AR9170 802.11n USB support"
depends on USB && MAC80211 && WLAN_80211
depends on USB && MAC80211
select FW_LOADER
help
This is a driver for the Atheros "otus" 802.11n USB devices.

View file

@ -1,6 +1,6 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
depends on PCI && MAC80211 && WLAN_80211
depends on PCI && MAC80211
select MAC80211_LEDS
select LEDS_CLASS
select NEW_LEDS

View file

@ -59,6 +59,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
{ ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) },
/* Acer Aspire One A150 (maximlevitsky@gmail.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) },
/* Acer Aspire One AO531h AO751h (keng-yu.lin@canonical.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe00d), ATH_LED(3, 0) },
/* Acer Ferrari 5000 (russ.dill@gmail.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) },
/* E-machines E510 (tuliom@gmail.com) */

View file

@ -3,7 +3,7 @@ config ATH9K_HW
config ATH9K
tristate "Atheros 802.11n wireless cards support"
depends on PCI && MAC80211 && WLAN_80211
depends on PCI && MAC80211
select ATH9K_HW
select MAC80211_LEDS
select LEDS_CLASS

View file

@ -69,6 +69,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
int irq;
int ret = 0;
struct ath_hw *ah;
char hw_name[64];
if (!pdev->dev.platform_data) {
dev_err(&pdev->dev, "no platform data specified\n");
@ -133,14 +134,11 @@ static int ath_ahb_probe(struct platform_device *pdev)
}
ah = sc->sc_ah;
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
printk(KERN_INFO
"%s: Atheros AR%s MAC/BB Rev:%x, "
"AR%s RF Rev:%x, mem=0x%lx, irq=%d\n",
"%s: %s mem=0x%lx, irq=%d\n",
wiphy_name(hw->wiphy),
ath_mac_bb_name(ah->hw_version.macVersion),
ah->hw_version.macRev,
ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
ah->hw_version.phyRev,
hw_name,
(unsigned long)mem, irq);
return 0;

View file

@ -877,7 +877,7 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset)
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0);
/* find off_6_1; */
for (i = 6; i >= 0; i--) {
for (i = 6; i > 0; i--) {
regVal = REG_READ(ah, 0x7834);
regVal |= (1 << (20 + i));
REG_WRITE(ah, 0x7834, regVal);

View file

@ -1112,6 +1112,10 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
pModal->txEndToRxOn);
if (AR_SREV_9271_10(ah))
REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
pModal->txEndToRxOn);
REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
pModal->thresh62);
REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,

View file

@ -30,8 +30,6 @@ static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan);
static u32 ath9k_hw_ini_fixup(struct ath_hw *ah,
struct ar5416_eeprom_def *pEepData,
u32 reg, u32 value);
static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards.");
@ -454,21 +452,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->power_mode = ATH9K_PM_UNDEFINED;
}
static int ath9k_hw_rfattach(struct ath_hw *ah)
{
bool rfStatus = false;
int ecode = 0;
rfStatus = ath9k_hw_init_rf(ah, &ecode);
if (!rfStatus) {
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
"RF setup failed, status: %u\n", ecode);
return ecode;
}
return 0;
}
static int ath9k_hw_rf_claim(struct ath_hw *ah)
{
u32 val;
@ -585,9 +568,15 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
ah->eep_ops->get_eeprom_ver(ah),
ah->eep_ops->get_eeprom_rev(ah));
ecode = ath9k_hw_rfattach(ah);
if (ecode != 0)
return ecode;
if (!AR_SREV_9280_10_OR_LATER(ah)) {
ecode = ath9k_hw_rf_alloc_ext_banks(ah);
if (ecode) {
ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
"Failed allocating banks for "
"external radio\n");
return ecode;
}
}
if (!AR_SREV_9100(ah)) {
ath9k_hw_ani_setup(ah);
@ -662,10 +651,13 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
{
if (AR_SREV_9271(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271_1_0,
ARRAY_SIZE(ar9271Modes_9271_1_0), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271_1_0,
ARRAY_SIZE(ar9271Common_9271_1_0), 2);
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
ARRAY_SIZE(ar9271Modes_9271), 6);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_1_0_only,
ar9271Modes_9271_1_0_only,
ARRAY_SIZE(ar9271Modes_9271_1_0_only), 6);
return;
}
@ -957,8 +949,14 @@ int ath9k_hw_init(struct ath_hw *ah)
ath9k_hw_init_cal_settings(ah);
ah->ani_function = ATH9K_ANI_ALL;
if (AR_SREV_9280_10_OR_LATER(ah))
if (AR_SREV_9280_10_OR_LATER(ah)) {
ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
ah->ath9k_hw_rf_set_freq = &ath9k_hw_ar9280_set_channel;
ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_9280_spur_mitigate;
} else {
ah->ath9k_hw_rf_set_freq = &ath9k_hw_set_channel;
ah->ath9k_hw_spur_mitigate_freq = &ath9k_hw_spur_mitigate;
}
ath9k_hw_init_mode_regs(ah);
@ -1037,6 +1035,22 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
}
static void ath9k_hw_change_target_baud(struct ath_hw *ah, u32 freq, u32 baud)
{
u32 lcr;
u32 baud_divider = freq * 1000 * 1000 / 16 / baud;
lcr = REG_READ(ah , 0x5100c);
lcr |= 0x80;
REG_WRITE(ah, 0x5100c, lcr);
REG_WRITE(ah, 0x51004, (baud_divider >> 8));
REG_WRITE(ah, 0x51000, (baud_divider & 0xff));
lcr &= ~0x80;
REG_WRITE(ah, 0x5100c, lcr);
}
static void ath9k_hw_init_pll(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@ -1100,6 +1114,26 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
}
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
/* Switch the core clock for ar9271 to 117Mhz */
if (AR_SREV_9271(ah)) {
if ((pll == 0x142c) || (pll == 0x2850) ) {
udelay(500);
/* set CLKOBS to output AHB clock */
REG_WRITE(ah, 0x7020, 0xe);
/*
* 0x304: 117Mhz, ahb_ratio: 1x1
* 0x306: 40Mhz, ahb_ratio: 1x1
*/
REG_WRITE(ah, 0x50040, 0x304);
/*
* makes adjustments for the baud dividor to keep the
* targetted baud rate based on the used core clock.
*/
ath9k_hw_change_target_baud(ah, AR9271_CORE_CLOCK,
AR9271_TARGET_BAUD_RATE);
}
}
udelay(RTC_PLL_SETTLE_DELAY);
REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
@ -1252,7 +1286,8 @@ void ath9k_hw_detach(struct ath_hw *ah)
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
free_hw:
ath9k_hw_rf_free(ah);
if (!AR_SREV_9280_10_OR_LATER(ah))
ath9k_hw_rf_free_ext_banks(ah);
kfree(ah);
ah = NULL;
}
@ -1274,7 +1309,8 @@ static void ath9k_hw_override_ini(struct ath_hw *ah,
* AR9271 1.1
*/
if (AR_SREV_9271_10(ah)) {
val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | AR_PHY_SPECTRAL_SCAN_ENABLE;
val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) |
AR_PHY_SPECTRAL_SCAN_ENABLE;
REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val);
}
else if (AR_SREV_9271_11(ah))
@ -1489,7 +1525,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
DO_DELAY(regWrites);
}
ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
ath9k_hw_write_regs(ah, freqIndex, regWrites);
if (AR_SREV_9271_10(ah))
REG_WRITE_ARRAY(&ah->iniModes_9271_1_0_only,
modesIndex, regWrites);
if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
@ -1832,6 +1872,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_channel *channel = chan->chan;
u32 synthDelay, qnum;
int r;
for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
if (ath9k_hw_numtxpending(ah, qnum)) {
@ -1852,14 +1893,11 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
ath9k_hw_set_regs(ah, chan);
if (AR_SREV_9280_10_OR_LATER(ah)) {
ath9k_hw_ar9280_set_channel(ah, chan);
} else {
if (!(ath9k_hw_set_channel(ah, chan))) {
ath_print(common, ATH_DBG_FATAL,
"Failed to set channel\n");
return false;
}
r = ah->ath9k_hw_rf_set_freq(ah, chan);
if (r) {
ath_print(common, ATH_DBG_FATAL,
"Failed to set channel\n");
return false;
}
ah->eep_ops->set_txpower(ah, chan,
@ -1882,10 +1920,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
ath9k_hw_set_delta_slope(ah, chan);
if (AR_SREV_9280_10_OR_LATER(ah))
ath9k_hw_9280_spur_mitigate(ah, chan);
else
ath9k_hw_spur_mitigate(ah, chan);
ah->ath9k_hw_spur_mitigate_freq(ah, chan);
if (!chan->oneTimeCalsDone)
chan->oneTimeCalsDone = true;
@ -1893,457 +1928,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
return true;
}
static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
{
int bb_spur = AR_NO_SPUR;
int freq;
int bin, cur_bin;
int bb_spur_off, spur_subchannel_sd;
int spur_freq_sd;
int spur_delta_phase;
int denominator;
int upper, lower, cur_vit_mask;
int tmp, newVal;
int i;
int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
};
int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
};
int inc[4] = { 0, 100, 0, 0 };
struct chan_centers centers;
int8_t mask_m[123];
int8_t mask_p[123];
int8_t mask_amt;
int tmp_mask;
int cur_bb_spur;
bool is2GHz = IS_CHAN_2GHZ(chan);
memset(&mask_m, 0, sizeof(int8_t) * 123);
memset(&mask_p, 0, sizeof(int8_t) * 123);
ath9k_hw_get_channel_centers(ah, chan, &centers);
freq = centers.synth_center;
ah->config.spurmode = SPUR_ENABLE_EEPROM;
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
if (is2GHz)
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
else
cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
if (AR_NO_SPUR == cur_bb_spur)
break;
cur_bb_spur = cur_bb_spur - freq;
if (IS_CHAN_HT40(chan)) {
if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
bb_spur = cur_bb_spur;
break;
}
} else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
(cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
bb_spur = cur_bb_spur;
break;
}
}
if (AR_NO_SPUR == bb_spur) {
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
return;
} else {
REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK,
AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
}
bin = bb_spur * 320;
tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal);
newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
if (IS_CHAN_HT40(chan)) {
if (bb_spur < 0) {
spur_subchannel_sd = 1;
bb_spur_off = bb_spur + 10;
} else {
spur_subchannel_sd = 0;
bb_spur_off = bb_spur - 10;
}
} else {
spur_subchannel_sd = 0;
bb_spur_off = bb_spur;
}
if (IS_CHAN_HT40(chan))
spur_delta_phase =
((bb_spur * 262144) /
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
else
spur_delta_phase =
((bb_spur * 524288) /
10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
denominator = IS_CHAN_2GHZ(chan) ? 44 : 40;
spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
REG_WRITE(ah, AR_PHY_TIMING11, newVal);
newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
cur_bin = -6000;
upper = bin + 100;
lower = bin - 100;
for (i = 0; i < 4; i++) {
int pilot_mask = 0;
int chan_mask = 0;
int bp = 0;
for (bp = 0; bp < 30; bp++) {
if ((cur_bin > lower) && (cur_bin < upper)) {
pilot_mask = pilot_mask | 0x1 << bp;
chan_mask = chan_mask | 0x1 << bp;
}
cur_bin += 100;
}
cur_bin += inc[i];
REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
REG_WRITE(ah, chan_mask_reg[i], chan_mask);
}
cur_vit_mask = 6100;
upper = bin + 120;
lower = bin - 120;
for (i = 0; i < 123; i++) {
if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
/* workaround for gcc bug #37014 */
volatile int tmp_v = abs(cur_vit_mask - bin);
if (tmp_v < 75)
mask_amt = 1;
else
mask_amt = 0;
if (cur_vit_mask < 0)
mask_m[abs(cur_vit_mask / 100)] = mask_amt;
else
mask_p[cur_vit_mask / 100] = mask_amt;
}
cur_vit_mask -= 100;
}
tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
| (mask_m[48] << 26) | (mask_m[49] << 24)
| (mask_m[50] << 22) | (mask_m[51] << 20)
| (mask_m[52] << 18) | (mask_m[53] << 16)
| (mask_m[54] << 14) | (mask_m[55] << 12)
| (mask_m[56] << 10) | (mask_m[57] << 8)
| (mask_m[58] << 6) | (mask_m[59] << 4)
| (mask_m[60] << 2) | (mask_m[61] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
tmp_mask = (mask_m[31] << 28)
| (mask_m[32] << 26) | (mask_m[33] << 24)
| (mask_m[34] << 22) | (mask_m[35] << 20)
| (mask_m[36] << 18) | (mask_m[37] << 16)
| (mask_m[48] << 14) | (mask_m[39] << 12)
| (mask_m[40] << 10) | (mask_m[41] << 8)
| (mask_m[42] << 6) | (mask_m[43] << 4)
| (mask_m[44] << 2) | (mask_m[45] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
| (mask_m[18] << 26) | (mask_m[18] << 24)
| (mask_m[20] << 22) | (mask_m[20] << 20)
| (mask_m[22] << 18) | (mask_m[22] << 16)
| (mask_m[24] << 14) | (mask_m[24] << 12)
| (mask_m[25] << 10) | (mask_m[26] << 8)
| (mask_m[27] << 6) | (mask_m[28] << 4)
| (mask_m[29] << 2) | (mask_m[30] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
| (mask_m[2] << 26) | (mask_m[3] << 24)
| (mask_m[4] << 22) | (mask_m[5] << 20)
| (mask_m[6] << 18) | (mask_m[7] << 16)
| (mask_m[8] << 14) | (mask_m[9] << 12)
| (mask_m[10] << 10) | (mask_m[11] << 8)
| (mask_m[12] << 6) | (mask_m[13] << 4)
| (mask_m[14] << 2) | (mask_m[15] << 0);
REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
tmp_mask = (mask_p[15] << 28)
| (mask_p[14] << 26) | (mask_p[13] << 24)
| (mask_p[12] << 22) | (mask_p[11] << 20)
| (mask_p[10] << 18) | (mask_p[9] << 16)
| (mask_p[8] << 14) | (mask_p[7] << 12)
| (mask_p[6] << 10) | (mask_p[5] << 8)
| (mask_p[4] << 6) | (mask_p[3] << 4)
| (mask_p[2] << 2) | (mask_p[1] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
tmp_mask = (mask_p[30] << 28)
| (mask_p[29] << 26) | (mask_p[28] << 24)
| (mask_p[27] << 22) | (mask_p[26] << 20)
| (mask_p[25] << 18) | (mask_p[24] << 16)
| (mask_p[23] << 14) | (mask_p[22] << 12)
| (mask_p[21] << 10) | (mask_p[20] << 8)
| (mask_p[19] << 6) | (mask_p[18] << 4)
| (mask_p[17] << 2) | (mask_p[16] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
tmp_mask = (mask_p[45] << 28)
| (mask_p[44] << 26) | (mask_p[43] << 24)
| (mask_p[42] << 22) | (mask_p[41] << 20)
| (mask_p[40] << 18) | (mask_p[39] << 16)
| (mask_p[38] << 14) | (mask_p[37] << 12)
| (mask_p[36] << 10) | (mask_p[35] << 8)
| (mask_p[34] << 6) | (mask_p[33] << 4)
| (mask_p[32] << 2) | (mask_p[31] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
| (mask_p[59] << 26) | (mask_p[58] << 24)
| (mask_p[57] << 22) | (mask_p[56] << 20)
| (mask_p[55] << 18) | (mask_p[54] << 16)
| (mask_p[53] << 14) | (mask_p[52] << 12)
| (mask_p[51] << 10) | (mask_p[50] << 8)
| (mask_p[49] << 6) | (mask_p[48] << 4)
| (mask_p[47] << 2) | (mask_p[46] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan)
{
int bb_spur = AR_NO_SPUR;
int bin, cur_bin;
int spur_freq_sd;
int spur_delta_phase;
int denominator;
int upper, lower, cur_vit_mask;
int tmp, new;
int i;
int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60
};
int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60
};
int inc[4] = { 0, 100, 0, 0 };
int8_t mask_m[123];
int8_t mask_p[123];
int8_t mask_amt;
int tmp_mask;
int cur_bb_spur;
bool is2GHz = IS_CHAN_2GHZ(chan);
memset(&mask_m, 0, sizeof(int8_t) * 123);
memset(&mask_p, 0, sizeof(int8_t) * 123);
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz);
if (AR_NO_SPUR == cur_bb_spur)
break;
cur_bb_spur = cur_bb_spur - (chan->channel * 10);
if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
bb_spur = cur_bb_spur;
break;
}
}
if (AR_NO_SPUR == bb_spur)
return;
bin = bb_spur * 32;
tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0));
new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new);
new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
AR_PHY_SPUR_REG_MASK_RATE_SELECT |
AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
REG_WRITE(ah, AR_PHY_SPUR_REG, new);
spur_delta_phase = ((bb_spur * 524288) / 100) &
AR_PHY_TIMING11_SPUR_DELTA_PHASE;
denominator = IS_CHAN_2GHZ(chan) ? 440 : 400;
spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
REG_WRITE(ah, AR_PHY_TIMING11, new);
cur_bin = -6000;
upper = bin + 100;
lower = bin - 100;
for (i = 0; i < 4; i++) {
int pilot_mask = 0;
int chan_mask = 0;
int bp = 0;
for (bp = 0; bp < 30; bp++) {
if ((cur_bin > lower) && (cur_bin < upper)) {
pilot_mask = pilot_mask | 0x1 << bp;
chan_mask = chan_mask | 0x1 << bp;
}
cur_bin += 100;
}
cur_bin += inc[i];
REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
REG_WRITE(ah, chan_mask_reg[i], chan_mask);
}
cur_vit_mask = 6100;
upper = bin + 120;
lower = bin - 120;
for (i = 0; i < 123; i++) {
if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
/* workaround for gcc bug #37014 */
volatile int tmp_v = abs(cur_vit_mask - bin);
if (tmp_v < 75)
mask_amt = 1;
else
mask_amt = 0;
if (cur_vit_mask < 0)
mask_m[abs(cur_vit_mask / 100)] = mask_amt;
else
mask_p[cur_vit_mask / 100] = mask_amt;
}
cur_vit_mask -= 100;
}
tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
| (mask_m[48] << 26) | (mask_m[49] << 24)
| (mask_m[50] << 22) | (mask_m[51] << 20)
| (mask_m[52] << 18) | (mask_m[53] << 16)
| (mask_m[54] << 14) | (mask_m[55] << 12)
| (mask_m[56] << 10) | (mask_m[57] << 8)
| (mask_m[58] << 6) | (mask_m[59] << 4)
| (mask_m[60] << 2) | (mask_m[61] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
tmp_mask = (mask_m[31] << 28)
| (mask_m[32] << 26) | (mask_m[33] << 24)
| (mask_m[34] << 22) | (mask_m[35] << 20)
| (mask_m[36] << 18) | (mask_m[37] << 16)
| (mask_m[48] << 14) | (mask_m[39] << 12)
| (mask_m[40] << 10) | (mask_m[41] << 8)
| (mask_m[42] << 6) | (mask_m[43] << 4)
| (mask_m[44] << 2) | (mask_m[45] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
| (mask_m[18] << 26) | (mask_m[18] << 24)
| (mask_m[20] << 22) | (mask_m[20] << 20)
| (mask_m[22] << 18) | (mask_m[22] << 16)
| (mask_m[24] << 14) | (mask_m[24] << 12)
| (mask_m[25] << 10) | (mask_m[26] << 8)
| (mask_m[27] << 6) | (mask_m[28] << 4)
| (mask_m[29] << 2) | (mask_m[30] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28)
| (mask_m[2] << 26) | (mask_m[3] << 24)
| (mask_m[4] << 22) | (mask_m[5] << 20)
| (mask_m[6] << 18) | (mask_m[7] << 16)
| (mask_m[8] << 14) | (mask_m[9] << 12)
| (mask_m[10] << 10) | (mask_m[11] << 8)
| (mask_m[12] << 6) | (mask_m[13] << 4)
| (mask_m[14] << 2) | (mask_m[15] << 0);
REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
tmp_mask = (mask_p[15] << 28)
| (mask_p[14] << 26) | (mask_p[13] << 24)
| (mask_p[12] << 22) | (mask_p[11] << 20)
| (mask_p[10] << 18) | (mask_p[9] << 16)
| (mask_p[8] << 14) | (mask_p[7] << 12)
| (mask_p[6] << 10) | (mask_p[5] << 8)
| (mask_p[4] << 6) | (mask_p[3] << 4)
| (mask_p[2] << 2) | (mask_p[1] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
tmp_mask = (mask_p[30] << 28)
| (mask_p[29] << 26) | (mask_p[28] << 24)
| (mask_p[27] << 22) | (mask_p[26] << 20)
| (mask_p[25] << 18) | (mask_p[24] << 16)
| (mask_p[23] << 14) | (mask_p[22] << 12)
| (mask_p[21] << 10) | (mask_p[20] << 8)
| (mask_p[19] << 6) | (mask_p[18] << 4)
| (mask_p[17] << 2) | (mask_p[16] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
tmp_mask = (mask_p[45] << 28)
| (mask_p[44] << 26) | (mask_p[43] << 24)
| (mask_p[42] << 22) | (mask_p[41] << 20)
| (mask_p[40] << 18) | (mask_p[39] << 16)
| (mask_p[38] << 14) | (mask_p[37] << 12)
| (mask_p[36] << 10) | (mask_p[35] << 8)
| (mask_p[34] << 6) | (mask_p[33] << 4)
| (mask_p[32] << 2) | (mask_p[31] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
| (mask_p[59] << 26) | (mask_p[58] << 24)
| (mask_p[57] << 22) | (mask_p[56] << 20)
| (mask_p[55] << 18) | (mask_p[54] << 16)
| (mask_p[53] << 14) | (mask_p[52] << 12)
| (mask_p[51] << 10) | (mask_p[50] << 8)
| (mask_p[49] << 6) | (mask_p[48] << 4)
| (mask_p[47] << 2) | (mask_p[46] << 0);
REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
static void ath9k_enable_rfkill(struct ath_hw *ah)
{
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
@ -2469,14 +2053,11 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
ath9k_hw_set_delta_slope(ah, chan);
if (AR_SREV_9280_10_OR_LATER(ah))
ath9k_hw_9280_spur_mitigate(ah, chan);
else
ath9k_hw_spur_mitigate(ah, chan);
ah->ath9k_hw_spur_mitigate_freq(ah, chan);
ah->eep_ops->set_board_values(ah, chan);
ath9k_hw_decrease_chain_power(ah, chan);
if (AR_SREV_5416(ah))
ath9k_hw_decrease_chain_power(ah, chan);
REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4)
@ -2497,11 +2078,9 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
if (AR_SREV_9280_10_OR_LATER(ah))
ath9k_hw_ar9280_set_channel(ah, chan);
else
if (!(ath9k_hw_set_channel(ah, chan)))
return -EIO;
r = ah->ath9k_hw_rf_set_freq(ah, chan);
if (r)
return r;
for (i = 0; i < AR_NUM_DCU; i++)
REG_WRITE(ah, AR_DQCUMASK(i), 1 << i);
@ -4350,3 +3929,89 @@ void ath_gen_timer_isr(struct ath_hw *ah)
}
}
EXPORT_SYMBOL(ath_gen_timer_isr);
static struct {
u32 version;
const char * name;
} ath_mac_bb_names[] = {
/* Devices with external radios */
{ AR_SREV_VERSION_5416_PCI, "5416" },
{ AR_SREV_VERSION_5416_PCIE, "5418" },
{ AR_SREV_VERSION_9100, "9100" },
{ AR_SREV_VERSION_9160, "9160" },
/* Single-chip solutions */
{ AR_SREV_VERSION_9280, "9280" },
{ AR_SREV_VERSION_9285, "9285" },
{ AR_SREV_VERSION_9287, "9287" },
{ AR_SREV_VERSION_9271, "9271" },
};
/* For devices with external radios */
static struct {
u16 version;
const char * name;
} ath_rf_names[] = {
{ 0, "5133" },
{ AR_RAD5133_SREV_MAJOR, "5133" },
{ AR_RAD5122_SREV_MAJOR, "5122" },
{ AR_RAD2133_SREV_MAJOR, "2133" },
{ AR_RAD2122_SREV_MAJOR, "2122" }
};
/*
* Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
*/
static const char *ath9k_hw_mac_bb_name(u32 mac_bb_version)
{
int i;
for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
if (ath_mac_bb_names[i].version == mac_bb_version) {
return ath_mac_bb_names[i].name;
}
}
return "????";
}
/*
* Return the RF name. "????" is returned if the RF is unknown.
* Used for devices with external radios.
*/
static const char *ath9k_hw_rf_name(u16 rf_version)
{
int i;
for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
if (ath_rf_names[i].version == rf_version) {
return ath_rf_names[i].name;
}
}
return "????";
}
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
{
int used;
/* chipsets >= AR9280 are single-chip */
if (AR_SREV_9280_10_OR_LATER(ah)) {
used = snprintf(hw_name, len,
"Atheros AR%s Rev:%x",
ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
ah->hw_version.macRev);
}
else {
used = snprintf(hw_name, len,
"Atheros AR%s MAC/BB Rev:%x AR%s RF Rev:%x",
ath9k_hw_mac_bb_name(ah->hw_version.macVersion),
ah->hw_version.macRev,
ath9k_hw_rf_name((ah->hw_version.analog5GhzRev &
AR_RADIO_SREV_MAJOR)),
ah->hw_version.phyRev);
}
hw_name[used] = '\0';
}
EXPORT_SYMBOL(ath9k_hw_name);

View file

@ -148,6 +148,15 @@ enum wireless_mode {
ATH9K_MODE_MAX,
};
/**
* ath9k_ant_setting - transmit antenna settings
*
* Configures the antenna setting to use for transmit.
*
* @ATH9K_ANT_VARIABLE: this means transmit on all active antennas
* @ATH9K_ANT_FIXED_A: this means transmit on the first antenna only
* @ATH9K_ANT_FIXED_B: this means transmit on the second antenna only
*/
enum ath9k_ant_setting {
ATH9K_ANT_VARIABLE = 0,
ATH9K_ANT_FIXED_A,
@ -539,7 +548,14 @@ struct ath_hw {
DONT_USE_32KHZ,
} enable_32kHz_clock;
/* RF */
/* Callback for radio frequency change */
int (*ath9k_hw_rf_set_freq)(struct ath_hw *ah, struct ath9k_channel *chan);
/* Callback for baseband spur frequency */
void (*ath9k_hw_spur_mitigate_freq)(struct ath_hw *ah,
struct ath9k_channel *chan);
/* Used to program the radio on non single-chip devices */
u32 *analogBank0Data;
u32 *analogBank1Data;
u32 *analogBank2Data;
@ -596,6 +612,7 @@ struct ath_hw {
struct ar5416IniArray iniModesAdditional;
struct ar5416IniArray iniModesRxGain;
struct ar5416IniArray iniModesTxGain;
struct ar5416IniArray iniModes_9271_1_0_only;
struct ar5416IniArray iniCckfirNormal;
struct ar5416IniArray iniCckfirJapan2484;
@ -618,7 +635,6 @@ static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah)
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_detach(struct ath_hw *ah);
int ath9k_hw_init(struct ath_hw *ah);
void ath9k_hw_rf_free(struct ath_hw *ah);
int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
bool bChannelChange);
void ath9k_hw_fill_cap_info(struct ath_hw *ah);
@ -704,6 +720,8 @@ void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
void ath_gen_timer_isr(struct ath_hw *hw);
u32 ath9k_hw_gettsf32(struct ath_hw *ah);
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
#define ATH_PCIE_CAP_LINK_CTRL 0x70
#define ATH_PCIE_CAP_LINK_L0S 1
#define ATH_PCIE_CAP_LINK_L1 2

View file

@ -6379,8 +6379,8 @@ static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = {
};
/* AR9271 initialization values automaticaly created: 03/23/09 */
static const u_int32_t ar9271Modes_9271_1_0[][6] = {
/* AR9271 initialization values automaticaly created: 06/04/09 */
static const u_int32_t ar9271Modes_9271[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
{ 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
@ -6390,8 +6390,8 @@ static const u_int32_t ar9271Modes_9271_1_0[][6] = {
{ 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
{ 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
{ 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
{ 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
{ 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e },
{ 0x00009828, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001, 0x3a020001 },
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
{ 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
@ -6405,6 +6405,7 @@ static const u_int32_t ar9271Modes_9271_1_0[][6] = {
{ 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
{ 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
{ 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
{ 0x00009910, 0x30002310, 0x30002310, 0x30002310, 0x30002310, 0x30002310 },
{ 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
{ 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
@ -6415,7 +6416,7 @@ static const u_int32_t ar9271Modes_9271_1_0[][6] = {
{ 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
{ 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
{ 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 },
{ 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f },
{ 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
@ -6704,7 +6705,7 @@ static const u_int32_t ar9271Modes_9271_1_0[][6] = {
{ 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
};
static const u_int32_t ar9271Common_9271_1_0[][2] = {
static const u_int32_t ar9271Common_9271[][2] = {
{ 0x0000000c, 0x00000000 },
{ 0x00000030, 0x00020045 },
{ 0x00000034, 0x00000005 },
@ -6800,7 +6801,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = {
{ 0x0000803c, 0x00000000 },
{ 0x00008048, 0x00000000 },
{ 0x00008054, 0x00000000 },
{ 0x00008058, 0x02000000 },
{ 0x00008058, 0x00000000 },
{ 0x0000805c, 0x000fc78f },
{ 0x00008060, 0x0000000f },
{ 0x00008064, 0x00000000 },
@ -6831,7 +6832,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = {
{ 0x00008110, 0x00000168 },
{ 0x00008118, 0x000100aa },
{ 0x0000811c, 0x00003210 },
{ 0x00008120, 0x08f04814 },
{ 0x00008120, 0x08f04810 },
{ 0x00008124, 0x00000000 },
{ 0x00008128, 0x00000000 },
{ 0x0000812c, 0x00000000 },
@ -6878,7 +6879,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = {
{ 0x00008258, 0x00000000 },
{ 0x0000825c, 0x400000ff },
{ 0x00008260, 0x00080922 },
{ 0x00008264, 0xa8a00010 },
{ 0x00008264, 0x88a00010 },
{ 0x00008270, 0x00000000 },
{ 0x00008274, 0x40000000 },
{ 0x00008278, 0x003e4180 },
@ -6910,7 +6911,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = {
{ 0x00007814, 0x924934a8 },
{ 0x0000781c, 0x00000000 },
{ 0x00007820, 0x00000c04 },
{ 0x00007824, 0x00d86bff },
{ 0x00007824, 0x00d8abff },
{ 0x00007828, 0x66964300 },
{ 0x0000782c, 0x8db6d961 },
{ 0x00007830, 0x8db6d96c },
@ -6944,7 +6945,6 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = {
{ 0x00009904, 0x00000000 },
{ 0x00009908, 0x00000000 },
{ 0x0000990c, 0x00000000 },
{ 0x00009910, 0x30002310 },
{ 0x0000991c, 0x10000fff },
{ 0x00009920, 0x04900000 },
{ 0x00009928, 0x00000001 },
@ -6958,7 +6958,7 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = {
{ 0x00009954, 0x5f3ca3de },
{ 0x00009958, 0x0108ecff },
{ 0x00009968, 0x000003ce },
{ 0x00009970, 0x192bb515 },
{ 0x00009970, 0x192bb514 },
{ 0x00009974, 0x00000000 },
{ 0x00009978, 0x00000001 },
{ 0x0000997c, 0x00000000 },
@ -7045,3 +7045,8 @@ static const u_int32_t ar9271Common_9271_1_0[][2] = {
{ 0x0000d380, 0x7f3c7bba },
{ 0x0000d384, 0xf3307ff0 },
};
static const u_int32_t ar9271Modes_9271_1_0_only[][6] = {
{ 0x00009910, 0x30002311, 0x30002311, 0x30002311, 0x30002311, 0x30002311 },
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
};

View file

@ -3191,64 +3191,6 @@ struct ieee80211_ops ath9k_ops = {
.rfkill_poll = ath9k_rfkill_poll_state,
};
static struct {
u32 version;
const char * name;
} ath_mac_bb_names[] = {
{ AR_SREV_VERSION_5416_PCI, "5416" },
{ AR_SREV_VERSION_5416_PCIE, "5418" },
{ AR_SREV_VERSION_9100, "9100" },
{ AR_SREV_VERSION_9160, "9160" },
{ AR_SREV_VERSION_9280, "9280" },
{ AR_SREV_VERSION_9285, "9285" },
{ AR_SREV_VERSION_9287, "9287" }
};
static struct {
u16 version;
const char * name;
} ath_rf_names[] = {
{ 0, "5133" },
{ AR_RAD5133_SREV_MAJOR, "5133" },
{ AR_RAD5122_SREV_MAJOR, "5122" },
{ AR_RAD2133_SREV_MAJOR, "2133" },
{ AR_RAD2122_SREV_MAJOR, "2122" }
};
/*
* Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
*/
const char *
ath_mac_bb_name(u32 mac_bb_version)
{
int i;
for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
if (ath_mac_bb_names[i].version == mac_bb_version) {
return ath_mac_bb_names[i].name;
}
}
return "????";
}
/*
* Return the RF name. "????" is returned if the RF is unknown.
*/
const char *
ath_rf_name(u16 rf_version)
{
int i;
for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
if (ath_rf_names[i].version == rf_version) {
return ath_rf_names[i].name;
}
}
return "????";
}
static int __init ath9k_init(void)
{
int error;

View file

@ -114,6 +114,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
u32 val;
int ret = 0;
struct ath_hw *ah;
char hw_name[64];
if (pci_enable_device(pdev))
return -EIO;
@ -218,14 +219,11 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sc->irq = pdev->irq;
ah = sc->sc_ah;
ath9k_hw_name(ah, hw_name, sizeof(hw_name));
printk(KERN_INFO
"%s: Atheros AR%s MAC/BB Rev:%x "
"AR%s RF Rev:%x: mem=0x%lx, irq=%d\n",
"%s: %s mem=0x%lx, irq=%d\n",
wiphy_name(hw->wiphy),
ath_mac_bb_name(ah->hw_version.macVersion),
ah->hw_version.macRev,
ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)),
ah->hw_version.phyRev,
hw_name,
(unsigned long)mem, pdev->irq);
return 0;

File diff suppressed because it is too large Load diff

View file

@ -17,20 +17,26 @@
#ifndef PHY_H
#define PHY_H
void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
struct ath9k_channel
*chan);
bool ath9k_hw_set_channel(struct ath_hw *ah,
struct ath9k_channel *chan);
void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex,
u32 freqIndex, int regWrites);
/* Common between single chip and non single-chip solutions */
void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites);
/* Single chip radio settings */
int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
/* Routines below are for non single-chip solutions */
int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan);
int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah);
void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah);
bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
struct ath9k_channel *chan,
u16 modesIndex);
void ath9k_hw_decrease_chain_power(struct ath_hw *ah,
struct ath9k_channel *chan);
bool ath9k_hw_init_rf(struct ath_hw *ah,
int *status);
#define AR_PHY_BASE 0x9800
#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2))
@ -186,8 +192,20 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
#define AR_PHY_PLL_CTL_44_2133 0xeb
#define AR_PHY_PLL_CTL_40_2133 0xea
#define AR_PHY_SPECTRAL_SCAN 0x9912
#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
#define AR_PHY_SPECTRAL_SCAN 0x9910 /* AR9280 spectral scan configuration register */
#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1
#define AR_PHY_SPECTRAL_SCAN_ENA 0x00000001 /* Enable spectral scan, reg 68, bit 0 */
#define AR_PHY_SPECTRAL_SCAN_ENA_S 0 /* Enable spectral scan, reg 68, bit 0 */
#define AR_PHY_SPECTRAL_SCAN_ACTIVE 0x00000002 /* Activate spectral scan reg 68, bit 1*/
#define AR_PHY_SPECTRAL_SCAN_ACTIVE_S 1 /* Activate spectral scan reg 68, bit 1*/
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD 0x000000F0 /* Interval for FFT reports, reg 68, bits 4-7*/
#define AR_PHY_SPECTRAL_SCAN_FFT_PERIOD_S 4
#define AR_PHY_SPECTRAL_SCAN_PERIOD 0x0000FF00 /* Interval for FFT reports, reg 68, bits 8-15*/
#define AR_PHY_SPECTRAL_SCAN_PERIOD_S 8
#define AR_PHY_SPECTRAL_SCAN_COUNT 0x00FF0000 /* Number of reports, reg 68, bits 16-23*/
#define AR_PHY_SPECTRAL_SCAN_COUNT_S 16
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 /* Short repeat, reg 68, bit 24*/
#define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 /* Short repeat, reg 68, bit 24*/
#define AR_PHY_RX_DELAY 0x9914
#define AR_PHY_SEARCH_START_DELAY 0x9918

View file

@ -202,7 +202,8 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
}
rcu_read_lock();
sta = ieee80211_find_sta(sc->hw, hdr->addr2);
/* XXX: use ieee80211_find_sta! */
sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr2);
if (sta) {
an = (struct ath_node *) sta->drv_priv;
if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD &&

View file

@ -1704,4 +1704,7 @@ enum {
#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24)
#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28)
#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */
#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */
#endif

View file

@ -282,7 +282,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_lock();
sta = ieee80211_find_sta(sc->hw, hdr->addr1);
/* XXX: use ieee80211_find_sta! */
sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr1);
if (!sta) {
rcu_read_unlock();
return;

View file

@ -1,6 +1,6 @@
config B43
tristate "Broadcom 43xx wireless support (mac80211 stack)"
depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
select SSB
select FW_LOADER
---help---

View file

@ -26,8 +26,6 @@
# define B43_DEBUG 0
#endif
#define B43_RX_MAX_SSI 60
/* MMIO offsets */
#define B43_MMIO_DMA0_REASON 0x20
#define B43_MMIO_DMA0_IRQ_MASK 0x24

View file

@ -3573,7 +3573,7 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
if (conf->channel->hw_value != phy->channel)
b43_switch_channel(dev, conf->channel->hw_value);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {

View file

@ -67,6 +67,7 @@ static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
struct b43_phy_lp *lpphy = phy->lp;
memset(lpphy, 0, sizeof(*lpphy));
lpphy->antenna = B43_ANTENNA_DEFAULT;
//TODO
}
@ -379,8 +380,6 @@ static void lpphy_save_dig_flt_state(struct b43_wldev *dev)
}
}
/* lpphy_restore_dig_flt_state is unused but kept as a reference */
#if 0
static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
{
static const u16 addr[] = {
@ -401,7 +400,6 @@ static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
for (i = 0; i < ARRAY_SIZE(addr); i++)
b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]);
}
#endif
static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
{
@ -754,11 +752,17 @@ static void lpphy_clear_deaf(struct b43_wldev *dev, bool user)
}
}
static void lpphy_set_trsw_over(struct b43_wldev *dev, bool tx, bool rx)
{
u16 trsw = (tx << 1) | rx;
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, trsw);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
}
static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
{
lpphy_set_deaf(dev, user);
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
lpphy_set_trsw_over(dev, false, true);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7);
@ -793,6 +797,60 @@ static void lpphy_restore_crs(struct b43_wldev *dev, bool user)
struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
{
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
if (dev->phy.rev >= 2) {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
}
} else {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
}
}
static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
{
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
if (dev->phy.rev >= 2) {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
}
} else {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
}
}
static void lpphy_disable_tx_gain_override(struct b43_wldev *dev)
{
if (dev->phy.rev < 2)
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
else {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF);
}
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF);
}
static void lpphy_enable_tx_gain_override(struct b43_wldev *dev)
{
if (dev->phy.rev < 2)
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
else {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x80);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x4000);
}
b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x40);
}
static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
{
struct lpphy_tx_gains gains;
@ -822,6 +880,17 @@ static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
}
static u16 lpphy_get_pa_gain(struct b43_wldev *dev)
{
return b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F;
}
static void lpphy_set_pa_gain(struct b43_wldev *dev, u16 gain)
{
b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0xE03F, gain << 6);
b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), 0x80FF, gain << 8);
}
static void lpphy_set_tx_gains(struct b43_wldev *dev,
struct lpphy_tx_gains gains)
{
@ -832,25 +901,22 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev,
b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
0xF800, rf_gain);
} else {
pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x1FC0;
pa_gain <<= 2;
pa_gain = lpphy_get_pa_gain(dev);
b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
(gains.pga << 8) | gains.gm);
/*
* SPEC FIXME The spec calls for (pa_gain << 8) here, but that
* conflicts with the spec for set_pa_gain! Vendor driver bug?
*/
b43_phy_maskset(dev, B43_PHY_OFDM(0xFB),
0x8000, gains.pad | pa_gain);
0x8000, gains.pad | (pa_gain << 6));
b43_phy_write(dev, B43_PHY_OFDM(0xFC),
(gains.pga << 8) | gains.gm);
b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
0x8000, gains.pad | pa_gain);
0x8000, gains.pad | (pa_gain << 8));
}
lpphy_set_dac_gain(dev, gains.dac);
if (dev->phy.rev < 2) {
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
} else {
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
}
b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF, 1 << 6);
lpphy_enable_tx_gain_override(dev);
}
static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
@ -890,41 +956,6 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
}
}
/* lpphy_disable_rx_gain_override is unused but kept as a reference */
#if 0
static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
{
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
if (dev->phy.rev >= 2) {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
}
} else {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
}
}
#endif
static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
{
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
if (dev->phy.rev >= 2) {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
}
} else {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
}
}
static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
{
if (dev->phy.rev < 2)
@ -1009,8 +1040,7 @@ static int lpphy_loopback(struct b43_wldev *dev)
memset(&iq_est, 0, sizeof(iq_est));
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
lpphy_set_trsw_over(dev, true, true);
b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1);
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
@ -1132,7 +1162,7 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM,
0x8FFF, ((u16)lpphy->tssi_npt << 16));
//TODO Set "TSSI Transmit Count" variable to total transmitted frame count
//TODO Disable TX gain override
lpphy_disable_tx_gain_override(dev);
lpphy->tx_pwr_idx_over = -1;
}
}
@ -1318,15 +1348,73 @@ static void lpphy_calibrate_rc(struct b43_wldev *dev)
}
}
static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
{
if (dev->phy.rev >= 2)
return; // rev2+ doesn't support antenna diversity
if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
return;
b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
dev->phy.lp->antenna = antenna;
}
static void lpphy_set_tx_iqcc(struct b43_wldev *dev, u16 a, u16 b)
{
u16 tmp[2];
tmp[0] = a;
tmp[1] = b;
b43_lptab_write_bulk(dev, B43_LPTAB16(0, 80), 2, tmp);
}
static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
struct lpphy_tx_gains gains;
u32 iq_comp, tx_gain, coeff, rf_power;
lpphy->tx_pwr_idx_over = index;
lpphy_read_tx_pctl_mode_from_hardware(dev);
if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF)
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW);
//TODO
if (dev->phy.rev >= 2) {
iq_comp = b43_lptab_read(dev, B43_LPTAB32(7, index + 320));
tx_gain = b43_lptab_read(dev, B43_LPTAB32(7, index + 192));
gains.pad = (tx_gain >> 16) & 0xFF;
gains.gm = tx_gain & 0xFF;
gains.pga = (tx_gain >> 8) & 0xFF;
gains.dac = (iq_comp >> 28) & 0xFF;
lpphy_set_tx_gains(dev, gains);
} else {
iq_comp = b43_lptab_read(dev, B43_LPTAB32(10, index + 320));
tx_gain = b43_lptab_read(dev, B43_LPTAB32(10, index + 192));
b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
0xF800, (tx_gain >> 4) & 0x7FFF);
lpphy_set_dac_gain(dev, tx_gain & 0x7);
lpphy_set_pa_gain(dev, (tx_gain >> 24) & 0x7F);
}
lpphy_set_bb_mult(dev, (iq_comp >> 20) & 0xFF);
lpphy_set_tx_iqcc(dev, (iq_comp >> 10) & 0x3FF, iq_comp & 0x3FF);
if (dev->phy.rev >= 2) {
coeff = b43_lptab_read(dev, B43_LPTAB32(7, index + 448));
} else {
coeff = b43_lptab_read(dev, B43_LPTAB32(10, index + 448));
}
b43_lptab_write(dev, B43_LPTAB16(0, 85), coeff & 0xFFFF);
if (dev->phy.rev >= 2) {
rf_power = b43_lptab_read(dev, B43_LPTAB32(7, index + 576));
b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00,
rf_power & 0xFFFF);//SPEC FIXME mask & set != 0
}
lpphy_enable_tx_gain_override(dev);
}
static void lpphy_btcoex_override(struct b43_wldev *dev)
@ -1335,58 +1423,45 @@ static void lpphy_btcoex_override(struct b43_wldev *dev)
b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF);
}
static void lpphy_pr41573_workaround(struct b43_wldev *dev)
static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
bool blocked)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
u32 *saved_tab;
const unsigned int saved_tab_size = 256;
enum b43_lpphy_txpctl_mode txpctl_mode;
s8 tx_pwr_idx_over;
u16 tssi_npt, tssi_idx;
saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL);
if (!saved_tab) {
b43err(dev->wl, "PR41573 failed. Out of memory!\n");
return;
}
lpphy_read_tx_pctl_mode_from_hardware(dev);
txpctl_mode = lpphy->txpctl_mode;
tx_pwr_idx_over = lpphy->tx_pwr_idx_over;
tssi_npt = lpphy->tssi_npt;
tssi_idx = lpphy->tssi_idx;
if (dev->phy.rev < 2) {
b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140),
saved_tab_size, saved_tab);
//TODO check MAC control register
if (blocked) {
if (dev->phy.rev >= 2) {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x83FF);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0x80FF);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xDFFF);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0808);
} else {
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xE0FF);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFCFF);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0018);
}
} else {
b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
saved_tab_size, saved_tab);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xE0FF);
if (dev->phy.rev >= 2)
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xF7F7);
else
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFE7);
}
//TODO
kfree(saved_tab);
}
static void lpphy_calibration(struct b43_wldev *dev)
/* This was previously called lpphy_japan_filter */
static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
enum b43_lpphy_txpctl_mode saved_pctl_mode;
u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
b43_mac_suspend(dev);
lpphy_btcoex_override(dev);
lpphy_read_tx_pctl_mode_from_hardware(dev);
saved_pctl_mode = lpphy->txpctl_mode;
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
//TODO Perform transmit power table I/Q LO calibration
if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF))
lpphy_pr41573_workaround(dev);
//TODO If a full calibration has not been performed on this channel yet, perform PAPD TX-power calibration
lpphy_set_tx_power_control(dev, saved_pctl_mode);
//TODO Perform I/Q calibration with a single control value set
b43_mac_enable(dev);
if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
if ((dev->phy.rev == 1) && (lpphy->rc_cap))
lpphy_set_rc_cap(dev);
} else {
b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
}
}
static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode)
@ -1495,6 +1570,473 @@ static void lpphy_tx_pctl_init(struct b43_wldev *dev)
}
}
static void lpphy_pr41573_workaround(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
u32 *saved_tab;
const unsigned int saved_tab_size = 256;
enum b43_lpphy_txpctl_mode txpctl_mode;
s8 tx_pwr_idx_over;
u16 tssi_npt, tssi_idx;
saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL);
if (!saved_tab) {
b43err(dev->wl, "PR41573 failed. Out of memory!\n");
return;
}
lpphy_read_tx_pctl_mode_from_hardware(dev);
txpctl_mode = lpphy->txpctl_mode;
tx_pwr_idx_over = lpphy->tx_pwr_idx_over;
tssi_npt = lpphy->tssi_npt;
tssi_idx = lpphy->tssi_idx;
if (dev->phy.rev < 2) {
b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140),
saved_tab_size, saved_tab);
} else {
b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
saved_tab_size, saved_tab);
}
//FIXME PHY reset
lpphy_table_init(dev); //FIXME is table init needed?
lpphy_baseband_init(dev);
lpphy_tx_pctl_init(dev);
b43_lpphy_op_software_rfkill(dev, false);
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
if (dev->phy.rev < 2) {
b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140),
saved_tab_size, saved_tab);
} else {
b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140),
saved_tab_size, saved_tab);
}
b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel);
lpphy->tssi_npt = tssi_npt;
lpphy->tssi_idx = tssi_idx;
lpphy_set_analog_filter(dev, lpphy->channel);
if (tx_pwr_idx_over != -1)
lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over);
if (lpphy->rc_cap)
lpphy_set_rc_cap(dev);
b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna);
lpphy_set_tx_power_control(dev, txpctl_mode);
kfree(saved_tab);
}
struct lpphy_rx_iq_comp { u8 chan; s8 c1, c0; };
static const struct lpphy_rx_iq_comp lpphy_5354_iq_table[] = {
{ .chan = 1, .c1 = -66, .c0 = 15, },
{ .chan = 2, .c1 = -66, .c0 = 15, },
{ .chan = 3, .c1 = -66, .c0 = 15, },
{ .chan = 4, .c1 = -66, .c0 = 15, },
{ .chan = 5, .c1 = -66, .c0 = 15, },
{ .chan = 6, .c1 = -66, .c0 = 15, },
{ .chan = 7, .c1 = -66, .c0 = 14, },
{ .chan = 8, .c1 = -66, .c0 = 14, },
{ .chan = 9, .c1 = -66, .c0 = 14, },
{ .chan = 10, .c1 = -66, .c0 = 14, },
{ .chan = 11, .c1 = -66, .c0 = 14, },
{ .chan = 12, .c1 = -66, .c0 = 13, },
{ .chan = 13, .c1 = -66, .c0 = 13, },
{ .chan = 14, .c1 = -66, .c0 = 13, },
};
static const struct lpphy_rx_iq_comp lpphy_rev0_1_iq_table[] = {
{ .chan = 1, .c1 = -64, .c0 = 13, },
{ .chan = 2, .c1 = -64, .c0 = 13, },
{ .chan = 3, .c1 = -64, .c0 = 13, },
{ .chan = 4, .c1 = -64, .c0 = 13, },
{ .chan = 5, .c1 = -64, .c0 = 12, },
{ .chan = 6, .c1 = -64, .c0 = 12, },
{ .chan = 7, .c1 = -64, .c0 = 12, },
{ .chan = 8, .c1 = -64, .c0 = 12, },
{ .chan = 9, .c1 = -64, .c0 = 12, },
{ .chan = 10, .c1 = -64, .c0 = 11, },
{ .chan = 11, .c1 = -64, .c0 = 11, },
{ .chan = 12, .c1 = -64, .c0 = 11, },
{ .chan = 13, .c1 = -64, .c0 = 11, },
{ .chan = 14, .c1 = -64, .c0 = 10, },
{ .chan = 34, .c1 = -62, .c0 = 24, },
{ .chan = 38, .c1 = -62, .c0 = 24, },
{ .chan = 42, .c1 = -62, .c0 = 24, },
{ .chan = 46, .c1 = -62, .c0 = 23, },
{ .chan = 36, .c1 = -62, .c0 = 24, },
{ .chan = 40, .c1 = -62, .c0 = 24, },
{ .chan = 44, .c1 = -62, .c0 = 23, },
{ .chan = 48, .c1 = -62, .c0 = 23, },
{ .chan = 52, .c1 = -62, .c0 = 23, },
{ .chan = 56, .c1 = -62, .c0 = 22, },
{ .chan = 60, .c1 = -62, .c0 = 22, },
{ .chan = 64, .c1 = -62, .c0 = 22, },
{ .chan = 100, .c1 = -62, .c0 = 16, },
{ .chan = 104, .c1 = -62, .c0 = 16, },
{ .chan = 108, .c1 = -62, .c0 = 15, },
{ .chan = 112, .c1 = -62, .c0 = 14, },
{ .chan = 116, .c1 = -62, .c0 = 14, },
{ .chan = 120, .c1 = -62, .c0 = 13, },
{ .chan = 124, .c1 = -62, .c0 = 12, },
{ .chan = 128, .c1 = -62, .c0 = 12, },
{ .chan = 132, .c1 = -62, .c0 = 12, },
{ .chan = 136, .c1 = -62, .c0 = 11, },
{ .chan = 140, .c1 = -62, .c0 = 10, },
{ .chan = 149, .c1 = -61, .c0 = 9, },
{ .chan = 153, .c1 = -61, .c0 = 9, },
{ .chan = 157, .c1 = -61, .c0 = 9, },
{ .chan = 161, .c1 = -61, .c0 = 8, },
{ .chan = 165, .c1 = -61, .c0 = 8, },
{ .chan = 184, .c1 = -62, .c0 = 25, },
{ .chan = 188, .c1 = -62, .c0 = 25, },
{ .chan = 192, .c1 = -62, .c0 = 25, },
{ .chan = 196, .c1 = -62, .c0 = 25, },
{ .chan = 200, .c1 = -62, .c0 = 25, },
{ .chan = 204, .c1 = -62, .c0 = 25, },
{ .chan = 208, .c1 = -62, .c0 = 25, },
{ .chan = 212, .c1 = -62, .c0 = 25, },
{ .chan = 216, .c1 = -62, .c0 = 26, },
};
static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = {
.chan = 0,
.c1 = -64,
.c0 = 0,
};
static u8 lpphy_nbits(s32 val)
{
u32 tmp = abs(val);
u8 nbits = 0;
while (tmp != 0) {
nbits++;
tmp >>= 1;
}
return nbits;
}
static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
{
struct lpphy_iq_est iq_est;
u16 c0, c1;
int prod, ipwr, qpwr, prod_msb, q_msb, tmp1, tmp2, tmp3, tmp4, ret;
c1 = b43_phy_read(dev, B43_LPPHY_RX_COMP_COEFF_S);
c0 = c1 >> 8;
c1 |= 0xFF;
b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, 0x00C0);
b43_phy_mask(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF);
ret = lpphy_rx_iq_est(dev, samples, 32, &iq_est);
if (!ret)
goto out;
prod = iq_est.iq_prod;
ipwr = iq_est.i_pwr;
qpwr = iq_est.q_pwr;
if (ipwr + qpwr < 2) {
ret = 0;
goto out;
}
prod_msb = lpphy_nbits(prod);
q_msb = lpphy_nbits(qpwr);
tmp1 = prod_msb - 20;
if (tmp1 >= 0) {
tmp3 = ((prod << (30 - prod_msb)) + (ipwr >> (1 + tmp1))) /
(ipwr >> tmp1);
} else {
tmp3 = ((prod << (30 - prod_msb)) + (ipwr << (-1 - tmp1))) /
(ipwr << -tmp1);
}
tmp2 = q_msb - 11;
if (tmp2 >= 0)
tmp4 = (qpwr << (31 - q_msb)) / (ipwr >> tmp2);
else
tmp4 = (qpwr << (31 - q_msb)) / (ipwr << -tmp2);
tmp4 -= tmp3 * tmp3;
tmp4 = -int_sqrt(tmp4);
c0 = tmp3 >> 3;
c1 = tmp4 >> 4;
out:
b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, c1);
b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF, c0 << 8);
return ret;
}
/* Complex number using 2 32-bit signed integers */
typedef struct {s32 i, q;} lpphy_c32;
static lpphy_c32 lpphy_cordic(int theta)
{
u32 arctg[] = { 2949120, 1740967, 919879, 466945, 234379, 117304,
58666, 29335, 14668, 7334, 3667, 1833, 917, 458,
229, 115, 57, 29, };
int i, tmp, signx = 1, angle = 0;
lpphy_c32 ret = { .i = 39797, .q = 0, };
theta = clamp_t(int, theta, -180, 180);
if (theta > 90) {
theta -= 180;
signx = -1;
} else if (theta < -90) {
theta += 180;
signx = -1;
}
for (i = 0; i <= 17; i++) {
if (theta > angle) {
tmp = ret.i - (ret.q >> i);
ret.q += ret.i >> i;
ret.i = tmp;
angle += arctg[i];
} else {
tmp = ret.i + (ret.q >> i);
ret.q -= ret.i >> i;
ret.i = tmp;
angle -= arctg[i];
}
}
ret.i *= signx;
ret.q *= signx;
return ret;
}
static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
u16 wait)
{
b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL,
0xFFC0, samples - 1);
if (loops != 0xFFFF)
loops--;
b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000, loops);
b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, 0x3F, wait << 6);
b43_phy_set(dev, B43_LPPHY_A_PHY_CTL_ADDR, 0x1);
}
//SPEC FIXME what does a negative freq mean?
static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
u16 buf[64];
int i, samples = 0, angle = 0, rotation = (9 * freq) / 500;
lpphy_c32 sample;
lpphy->tx_tone_freq = freq;
if (freq) {
/* Find i for which abs(freq) integrally divides 20000 * i */
for (i = 1; samples * abs(freq) != 20000 * i; i++) {
samples = (20000 * i) / abs(freq);
if(B43_WARN_ON(samples > 63))
return;
}
} else {
samples = 2;
}
for (i = 0; i < samples; i++) {
sample = lpphy_cordic(angle);
angle += rotation;
buf[i] = ((sample.i * max) & 0xFF) << 8;
buf[i] |= (sample.q * max) & 0xFF;
}
b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
lpphy_run_samples(dev, samples, 0xFFFF, 0);
}
static void lpphy_stop_tx_tone(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
int i;
lpphy->tx_tone_freq = 0;
b43_phy_mask(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000);
for (i = 0; i < 31; i++) {
if (!(b43_phy_read(dev, B43_LPPHY_A_PHY_CTL_ADDR) & 0x1))
break;
udelay(100);
}
}
static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
int mode, bool useindex, u8 index)
{
//TODO
}
static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
struct ssb_bus *bus = dev->dev->bus;
struct lpphy_tx_gains gains, oldgains;
int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
lpphy_read_tx_pctl_mode_from_hardware(dev);
old_txpctl = lpphy->txpctl_mode;
old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
if (old_afe_ovr)
oldgains = lpphy_get_tx_gains(dev);
old_rf = b43_phy_read(dev, B43_LPPHY_RF_PWR_OVERRIDE) & 0xFF;
old_bbmult = lpphy_get_bb_mult(dev);
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
if (bus->chip_id == 0x4325 && bus->chip_rev == 0)
lpphy_papd_cal(dev, gains, 0, 1, 30);
else
lpphy_papd_cal(dev, gains, 0, 1, 65);
if (old_afe_ovr)
lpphy_set_tx_gains(dev, oldgains);
lpphy_set_bb_mult(dev, old_bbmult);
lpphy_set_tx_power_control(dev, old_txpctl);
b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, old_rf);
}
static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
bool rx, bool pa, struct lpphy_tx_gains *gains)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
struct ssb_bus *bus = dev->dev->bus;
const struct lpphy_rx_iq_comp *iqcomp = NULL;
struct lpphy_tx_gains nogains, oldgains;
u16 tmp;
int i, ret;
memset(&nogains, 0, sizeof(nogains));
memset(&oldgains, 0, sizeof(oldgains));
if (bus->chip_id == 0x5354) {
for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
iqcomp = &lpphy_5354_iq_table[i];
}
}
} else if (dev->phy.rev >= 2) {
iqcomp = &lpphy_rev2plus_iq_comp;
} else {
for (i = 0; i < ARRAY_SIZE(lpphy_rev0_1_iq_table); i++) {
if (lpphy_rev0_1_iq_table[i].chan == lpphy->channel) {
iqcomp = &lpphy_rev0_1_iq_table[i];
}
}
}
if (B43_WARN_ON(!iqcomp))
return 0;
b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, iqcomp->c1);
b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S,
0x00FF, iqcomp->c0 << 8);
if (noise) {
tx = true;
rx = false;
pa = false;
}
lpphy_set_trsw_over(dev, tx, rx);
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
0xFFF7, pa << 3);
} else {
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
0xFFDF, pa << 5);
}
tmp = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
if (noise)
lpphy_set_rx_gain(dev, 0x2D5D);
else {
if (tmp)
oldgains = lpphy_get_tx_gains(dev);
if (!gains)
gains = &nogains;
lpphy_set_tx_gains(dev, *gains);
}
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
lpphy_set_deaf(dev, false);
if (noise)
ret = lpphy_calc_rx_iq_comp(dev, 0xFFF0);
else {
lpphy_start_tx_tone(dev, 4000, 100);
ret = lpphy_calc_rx_iq_comp(dev, 0x4000);
lpphy_stop_tx_tone(dev);
}
lpphy_clear_deaf(dev, false);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFC);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFDF);
if (!noise) {
if (tmp)
lpphy_set_tx_gains(dev, oldgains);
else
lpphy_disable_tx_gain_override(dev);
}
lpphy_disable_rx_gain_override(dev);
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xF7FF);
return ret;
}
static void lpphy_calibration(struct b43_wldev *dev)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
enum b43_lpphy_txpctl_mode saved_pctl_mode;
bool full_cal = false;
if (lpphy->full_calib_chan != lpphy->channel) {
full_cal = true;
lpphy->full_calib_chan = lpphy->channel;
}
b43_mac_suspend(dev);
lpphy_btcoex_override(dev);
if (dev->phy.rev >= 2)
lpphy_save_dig_flt_state(dev);
lpphy_read_tx_pctl_mode_from_hardware(dev);
saved_pctl_mode = lpphy->txpctl_mode;
lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
//TODO Perform transmit power table I/Q LO calibration
if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF))
lpphy_pr41573_workaround(dev);
if ((dev->phy.rev >= 2) && full_cal) {
lpphy_papd_cal_txpwr(dev);
}
lpphy_set_tx_power_control(dev, saved_pctl_mode);
if (dev->phy.rev >= 2)
lpphy_restore_dig_flt_state(dev);
lpphy_rx_iq_cal(dev, true, true, false, false, NULL);
b43_mac_enable(dev);
}
static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
{
b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
@ -1539,12 +2081,6 @@ static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
}
static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
bool blocked)
{
//TODO
}
struct b206x_channel {
u8 channel;
u16 freq;
@ -2010,22 +2546,6 @@ static int lpphy_b2062_tune(struct b43_wldev *dev,
return err;
}
/* This was previously called lpphy_japan_filter */
static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
{
struct b43_phy_lp *lpphy = dev->phy.lp;
u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
if ((dev->phy.rev == 1) && (lpphy->rc_cap))
lpphy_set_rc_cap(dev);
} else {
b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
}
}
static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
{
u16 tmp;
@ -2210,18 +2730,6 @@ static int b43_lpphy_op_init(struct b43_wldev *dev)
return 0;
}
static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
{
if (dev->phy.rev >= 2)
return; // rev2+ doesn't support antenna diversity
if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
return;
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
}
static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
{
//TODO
@ -2244,6 +2752,11 @@ void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
}
}
static void b43_lpphy_op_pwork_15sec(struct b43_wldev *dev)
{
//TODO
}
const struct b43_phy_operations b43_phyops_lp = {
.allocate = b43_lpphy_op_allocate,
.free = b43_lpphy_op_free,
@ -2261,4 +2774,6 @@ const struct b43_phy_operations b43_phyops_lp = {
.set_rx_antenna = b43_lpphy_op_set_rx_antenna,
.recalc_txpower = b43_lpphy_op_recalc_txpower,
.adjust_txpower = b43_lpphy_op_adjust_txpower,
.pwork_15sec = b43_lpphy_op_pwork_15sec,
.pwork_60sec = lpphy_calibration,
};

View file

@ -286,6 +286,7 @@
#define B43_LPPHY_TR_LOOKUP_6 B43_PHY_OFDM(0xC8) /* TR Lookup 6 */
#define B43_LPPHY_TR_LOOKUP_7 B43_PHY_OFDM(0xC9) /* TR Lookup 7 */
#define B43_LPPHY_TR_LOOKUP_8 B43_PHY_OFDM(0xCA) /* TR Lookup 8 */
#define B43_LPPHY_RF_PWR_OVERRIDE B43_PHY_OFDM(0xD3) /* RF power override */
@ -871,12 +872,12 @@ struct b43_phy_lp {
u8 rssi_gs;
/* RC cap */
u8 rc_cap; /* FIXME initial value? */
u8 rc_cap;
/* BX arch */
u8 bx_arch;
/* Full calibration channel */
u8 full_calib_chan; /* FIXME initial value? */
u8 full_calib_chan;
/* Transmit iqlocal best coeffs */
bool tx_iqloc_best_coeffs_valid;
@ -891,6 +892,12 @@ struct b43_phy_lp {
/* The channel we are tuned to */
u8 channel;
/* The active antenna diversity mode */
int antenna;
/* Frequency of the active TX tone */
int tx_tone_freq;
};
enum tssi_mux_mode {

View file

@ -621,7 +621,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
(phystat0 & B43_RX_PHYST0_OFDM),
(phystat0 & B43_RX_PHYST0_GAINCTL),
(phystat3 & B43_RX_PHYST3_TRSTATE));
status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI;
}
if (phystat0 & B43_RX_PHYST0_OFDM)

View file

@ -1,6 +1,6 @@
config B43LEGACY
tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)"
depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
select SSB
select FW_LOADER
---help---

View file

@ -29,8 +29,6 @@
#define B43legacy_IRQWAIT_MAX_RETRIES 20
#define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */
/* MMIO offsets */
#define B43legacy_MMIO_DMA0_REASON 0x20
#define B43legacy_MMIO_DMA0_IRQ_MASK 0x24

View file

@ -1240,8 +1240,9 @@ struct b43legacy_dmaring *parse_cookie(struct b43legacy_wldev *dev,
}
static int dma_tx_fragment(struct b43legacy_dmaring *ring,
struct sk_buff *skb)
struct sk_buff **in_skb)
{
struct sk_buff *skb = *in_skb;
const struct b43legacy_dma_ops *ops = ring->ops;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *header;
@ -1305,8 +1306,14 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
}
memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
bounce_skb->dev = skb->dev;
skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
info = IEEE80211_SKB_CB(bounce_skb);
dev_kfree_skb_any(skb);
skb = bounce_skb;
*in_skb = bounce_skb;
meta->skb = skb;
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
@ -1360,8 +1367,10 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
struct sk_buff *skb)
{
struct b43legacy_dmaring *ring;
struct ieee80211_hdr *hdr;
int err = 0;
unsigned long flags;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
ring = priority_to_txring(dev, skb_get_queue_mapping(skb));
spin_lock_irqsave(&ring->lock, flags);
@ -1386,7 +1395,11 @@ int b43legacy_dma_tx(struct b43legacy_wldev *dev,
goto out_unlock;
}
err = dma_tx_fragment(ring, skb);
/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
* into the skb data or cb now. */
hdr = NULL;
info = NULL;
err = dma_tx_fragment(ring, &skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */

View file

@ -2676,7 +2676,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
if (conf->channel->hw_value != phy->channel)
b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {

View file

@ -549,7 +549,6 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
(phystat0 & B43legacy_RX_PHYST0_GAINCTL),
(phystat3 & B43legacy_RX_PHYST3_TRSTATE));
status.noise = dev->stats.link_noise;
status.qual = (jssi * 100) / B43legacy_RX_MAX_SSI;
/* change to support A PHY */
if (phystat0 & B43legacy_RX_PHYST0_OFDM)
status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);

View file

@ -1,6 +1,5 @@
config HOSTAP
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
depends on WLAN_80211
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV

View file

@ -4,7 +4,7 @@
config IPW2100
tristate "Intel PRO/Wireless 2100 Network Connection"
depends on PCI && WLAN_80211 && CFG80211
depends on PCI && CFG80211
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
@ -65,7 +65,7 @@ config IPW2100_DEBUG
config IPW2200
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
depends on PCI && WLAN_80211 && CFG80211 && CFG80211_WEXT
depends on PCI && CFG80211 && CFG80211_WEXT
select WIRELESS_EXT
select WEXT_SPY
select WEXT_PRIV
@ -154,7 +154,7 @@ config IPW2200_DEBUG
config LIBIPW
tristate
depends on PCI && WLAN_80211 && CFG80211
depends on PCI && CFG80211
select WIRELESS_EXT
select WEXT_SPY
select CRYPTO

View file

@ -1,6 +1,6 @@
config IWLWIFI
tristate "Intel Wireless Wifi"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
depends on PCI && MAC80211 && EXPERIMENTAL
select FW_LOADER
config IWLWIFI_SPECTRUM_MEASUREMENT

View file

@ -164,7 +164,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
.valid_tx_ant = ANT_A,
.valid_rx_ant = ANT_AB,
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
.shadow_ram_support = false,
@ -190,7 +190,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
.valid_tx_ant = ANT_A,
.valid_rx_ant = ANT_AB,
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
.shadow_ram_support = false,

View file

@ -42,38 +42,6 @@
#define RS_NAME "iwl-3945-rs"
struct iwl3945_rate_scale_data {
u64 data;
s32 success_counter;
s32 success_ratio;
s32 counter;
s32 average_tpt;
unsigned long stamp;
};
struct iwl3945_rs_sta {
spinlock_t lock;
struct iwl_priv *priv;
s32 *expected_tpt;
unsigned long last_partial_flush;
unsigned long last_flush;
u32 flush_time;
u32 last_tx_packets;
u32 tx_packets;
u8 tgg;
u8 flush_pending;
u8 start_rate;
u8 ibss_sta_added;
struct timer_list rate_scale_flush;
struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *rs_sta_dbgfs_stats_table_file;
#endif
/* used to be in sta_info */
int last_txrate_idx;
};
static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
};
@ -370,6 +338,28 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
IWL_DEBUG_RATE(priv, "enter\n");
spin_lock_init(&rs_sta->lock);
rs_sta->priv = priv;
rs_sta->start_rate = IWL_RATE_INVALID;
/* default to just 802.11b */
rs_sta->expected_tpt = iwl3945_expected_tpt_b;
rs_sta->last_partial_flush = jiffies;
rs_sta->last_flush = jiffies;
rs_sta->flush_time = IWL_RATE_FLUSH;
rs_sta->last_tx_packets = 0;
rs_sta->ibss_sta_added = 0;
init_timer(&rs_sta->rate_scale_flush);
rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush;
for (i = 0; i < IWL_RATE_COUNT_3945; i++)
iwl3945_clear_window(&rs_sta->win[i]);
/* TODO: what is a good starting rate for STA? About middle? Maybe not
* the lowest or the highest rate.. Could consider using RSSI from
* previous packets? Need to have IEEE 802.1X auth succeed immediately
@ -409,45 +399,11 @@ static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct iwl3945_rs_sta *rs_sta;
struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
struct iwl_priv *priv = iwl_priv;
int i;
/*
* XXX: If it's using sta->drv_priv anyway, it might
* as well just put all the information there.
*/
struct iwl_priv *priv __maybe_unused = iwl_priv;
IWL_DEBUG_RATE(priv, "enter\n");
rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
if (!rs_sta) {
IWL_DEBUG_RATE(priv, "leave: ENOMEM\n");
return NULL;
}
psta->rs_sta = rs_sta;
spin_lock_init(&rs_sta->lock);
rs_sta->priv = priv;
rs_sta->start_rate = IWL_RATE_INVALID;
/* default to just 802.11b */
rs_sta->expected_tpt = iwl3945_expected_tpt_b;
rs_sta->last_partial_flush = jiffies;
rs_sta->last_flush = jiffies;
rs_sta->flush_time = IWL_RATE_FLUSH;
rs_sta->last_tx_packets = 0;
rs_sta->ibss_sta_added = 0;
init_timer(&rs_sta->rate_scale_flush);
rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush;
for (i = 0; i < IWL_RATE_COUNT_3945; i++)
iwl3945_clear_window(&rs_sta->win[i]);
rs_sta = &psta->rs_sta;
IWL_DEBUG_RATE(priv, "leave\n");
@ -458,14 +414,11 @@ static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
void *priv_sta)
{
struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
struct iwl3945_rs_sta *rs_sta = priv_sta;
struct iwl3945_rs_sta *rs_sta = &psta->rs_sta;
struct iwl_priv *priv __maybe_unused = rs_sta->priv;
psta->rs_sta = NULL;
IWL_DEBUG_RATE(priv, "enter\n");
del_timer_sync(&rs_sta->rate_scale_flush);
kfree(rs_sta);
IWL_DEBUG_RATE(priv, "leave\n");
}
@ -960,14 +913,15 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
rcu_read_lock();
sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
sta = ieee80211_find_sta(priv->vif,
priv->stations[sta_id].sta.sta.addr);
if (!sta) {
rcu_read_unlock();
return;
}
psta = (void *) sta->drv_priv;
rs_sta = psta->rs_sta;
rs_sta = &psta->rs_sta;
spin_lock_irqsave(&rs_sta->lock, flags);

View file

@ -74,8 +74,41 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
/* Module parameters accessible from iwl-*.c */
extern struct iwl_mod_params iwl3945_mod_params;
struct iwl3945_rate_scale_data {
u64 data;
s32 success_counter;
s32 success_ratio;
s32 counter;
s32 average_tpt;
unsigned long stamp;
};
struct iwl3945_rs_sta {
spinlock_t lock;
struct iwl_priv *priv;
s32 *expected_tpt;
unsigned long last_partial_flush;
unsigned long last_flush;
u32 flush_time;
u32 last_tx_packets;
u32 tx_packets;
u8 tgg;
u8 flush_pending;
u8 start_rate;
u8 ibss_sta_added;
struct timer_list rate_scale_flush;
struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *rs_sta_dbgfs_stats_table_file;
#endif
/* used to be in sta_info */
int last_txrate_idx;
};
struct iwl3945_sta_priv {
struct iwl3945_rs_sta *rs_sta;
struct iwl3945_rs_sta rs_sta;
};
enum iwl3945_antenna {

View file

@ -591,16 +591,6 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
}
static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
{
struct iwl_wimax_coex_cmd coex_cmd;
memset(&coex_cmd, 0, sizeof(coex_cmd));
return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
sizeof(coex_cmd), &coex_cmd);
}
int iwl5000_alive_notify(struct iwl_priv *priv)
{
u32 a;
@ -681,7 +671,7 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
iwl5000_send_wimax_coex(priv);
iwl_send_wimax_coex(priv);
iwl5000_set_Xtal_calib(priv);
iwl_send_calib_results(priv);

View file

@ -299,7 +299,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_HYBRID,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
@ -329,7 +329,7 @@ struct iwl_cfg iwl6000h_2abg_cfg = {
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_HYBRID,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
@ -358,7 +358,7 @@ struct iwl_cfg iwl6000h_2bg_cfg = {
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_HYBRID,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
@ -390,7 +390,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
.valid_tx_ant = ANT_BC,
.valid_rx_ant = ANT_BC,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_INTERNAL,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
@ -420,7 +420,7 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
.valid_tx_ant = ANT_BC,
.valid_rx_ant = ANT_BC,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_INTERNAL,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
@ -449,7 +449,7 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
.valid_tx_ant = ANT_BC,
.valid_rx_ant = ANT_BC,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_INTERNAL,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
@ -478,7 +478,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_SYSTEM,
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
@ -490,6 +490,8 @@ struct iwl_cfg iwl6050_2agn_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.support_sm_ps = true,
.support_wimax_coexist = true,
};
struct iwl_cfg iwl6050_2abg_cfg = {
@ -508,7 +510,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_AB,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_SYSTEM,
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
@ -519,6 +521,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.support_wimax_coexist = true,
};
struct iwl_cfg iwl6000_3agn_cfg = {
@ -537,7 +540,7 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_SYSTEM,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
@ -567,7 +570,7 @@ struct iwl_cfg iwl6050_3agn_cfg = {
.valid_tx_ant = ANT_ABC,
.valid_rx_ant = ANT_ABC,
.pll_cfg_val = 0,
.set_l0s = false,
.set_l0s = true,
.use_bsm = false,
.pa_type = IWL_PA_SYSTEM,
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
@ -579,6 +582,8 @@ struct iwl_cfg iwl6050_3agn_cfg = {
.supports_idle = true,
.adv_thermal_throttle = true,
.support_ct_kill_exit = true,
.support_sm_ps = true,
.support_wimax_coexist = true,
};
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));

View file

@ -2477,19 +2477,12 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta;
struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv;
struct iwl_priv *priv;
int i, j;
priv = (struct iwl_priv *)priv_rate;
IWL_DEBUG_RATE(priv, "create station rate scale window\n");
lq_sta = &sta_priv->lq_sta;
lq_sta->lq.sta_id = 0xff;
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]);
return lq_sta;
}
@ -2502,6 +2495,12 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
struct iwl_lq_sta *lq_sta = priv_sta;
lq_sta->lq.sta_id = 0xff;
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]);
lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->supp_rates[sband->band];
for (j = 0; j < LQ_SIZE; j++)

View file

@ -190,11 +190,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
priv->start_calib = 0;
/* Add the broadcast address so we can send broadcast frames */
if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
IWL_INVALID_STATION) {
IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
return -EIO;
}
iwl_add_bcast_station(priv);
/* If we have set the ASSOC_MSK and we are in BSS mode then
* add the IWL_AP_ID to the station rate table */
@ -890,6 +886,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
u32 inta, handled = 0;
u32 inta_fh;
unsigned long flags;
u32 i;
#ifdef CONFIG_IWLWIFI_DEBUG
u32 inta_mask;
#endif
@ -1007,19 +1004,17 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
handled |= CSR_INT_BIT_SW_ERR;
}
/* uCode wakes up after power-down sleep */
/*
* uCode wakes up after power-down sleep.
* Tell device about any new tx or host commands enqueued,
* and about any Rx buffers made available while asleep.
*/
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
iwl_txq_update_write_ptr(priv, &priv->txq[0]);
iwl_txq_update_write_ptr(priv, &priv->txq[1]);
iwl_txq_update_write_ptr(priv, &priv->txq[2]);
iwl_txq_update_write_ptr(priv, &priv->txq[3]);
iwl_txq_update_write_ptr(priv, &priv->txq[4]);
iwl_txq_update_write_ptr(priv, &priv->txq[5]);
for (i = 0; i < priv->hw_params.max_txq_num; i++)
iwl_txq_update_write_ptr(priv, &priv->txq[i]);
priv->isr_stats.wakeup++;
handled |= CSR_INT_BIT_WAKEUP;
}
@ -1033,11 +1028,12 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
}
/* This "Tx" DMA channel is used only for loading uCode */
if (inta & CSR_INT_BIT_FH_TX) {
IWL_DEBUG_ISR(priv, "Tx interrupt\n");
IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
priv->isr_stats.tx++;
handled |= CSR_INT_BIT_FH_TX;
/* FH finished to write, send event */
/* Wake up uCode load routine, now that load is complete */
priv->ucode_write_complete = 1;
wake_up_interruptible(&priv->wait_command_queue);
}
@ -1234,12 +1230,13 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
iwl_leds_background(priv);
}
/* This "Tx" DMA channel is used only for loading uCode */
if (inta & CSR_INT_BIT_FH_TX) {
iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK);
IWL_DEBUG_ISR(priv, "Tx interrupt\n");
IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
priv->isr_stats.tx++;
handled |= CSR_INT_BIT_FH_TX;
/* FH finished to write, send event */
/* Wake up uCode load routine, now that load is complete */
priv->ucode_write_complete = 1;
wake_up_interruptible(&priv->wait_command_queue);
}
@ -1377,6 +1374,14 @@ static int iwl_read_ucode(struct iwl_priv *priv)
IWL_UCODE_API(priv->ucode_ver),
IWL_UCODE_SERIAL(priv->ucode_ver));
snprintf(priv->hw->wiphy->fw_version,
sizeof(priv->hw->wiphy->fw_version),
"%u.%u.%u.%u",
IWL_UCODE_MAJOR(priv->ucode_ver),
IWL_UCODE_MINOR(priv->ucode_ver),
IWL_UCODE_API(priv->ucode_ver),
IWL_UCODE_SERIAL(priv->ucode_ver));
if (build)
IWL_DEBUG_INFO(priv, "Build %u\n", build);
@ -2515,7 +2520,7 @@ void iwl_config_ap(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
iwl_activate_qos(priv, 1);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
iwl_add_bcast_station(priv);
}
iwl_send_beacon_cmd(priv);
@ -2963,6 +2968,100 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
del_timer_sync(&priv->statistics_periodic);
}
static void iwl_init_hw_rates(struct iwl_priv *priv,
struct ieee80211_rate *rates)
{
int i;
for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
rates[i].bitrate = iwl_rates[i].ieee * 5;
rates[i].hw_value = i; /* Rate scaling will work on indexes */
rates[i].hw_value_short = i;
rates[i].flags = 0;
if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
/*
* If CCK != 1M then set short preamble rate flag.
*/
rates[i].flags |=
(iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ?
0 : IEEE80211_RATE_SHORT_PREAMBLE;
}
}
}
static int iwl_init_drv(struct iwl_priv *priv)
{
int ret;
priv->ibss_beacon = NULL;
spin_lock_init(&priv->lock);
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
INIT_LIST_HEAD(&priv->free_frames);
mutex_init(&priv->mutex);
/* Clear the driver's (not device's) station table */
iwl_clear_stations_table(priv);
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ;
priv->iw_mode = NL80211_IFTYPE_STATION;
if (priv->cfg->support_sm_ps)
priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DYNAMIC;
else
priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv);
iwl_init_scan_params(priv);
iwl_reset_qos(priv);
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
priv->rates_mask = IWL_RATES_MASK;
/* Set the tx_power_user_lmt to the lowest power level
* this value will get overwritten by channel max power avg
* from eeprom */
priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN;
ret = iwl_init_channel_map(priv);
if (ret) {
IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
goto err;
}
ret = iwlcore_init_geos(priv);
if (ret) {
IWL_ERR(priv, "initializing geos failed: %d\n", ret);
goto err_free_channel_map;
}
iwl_init_hw_rates(priv, priv->ieee_rates);
return 0;
err_free_channel_map:
iwl_free_channel_map(priv);
err:
return ret;
}
static void iwl_uninit_drv(struct iwl_priv *priv)
{
iwl_calib_free_results(priv);
iwlcore_free_geos(priv);
iwl_free_channel_map(priv);
kfree(priv->scan);
}
static struct attribute *iwl_sysfs_entries[] = {
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
@ -3105,12 +3204,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto out_iounmap;
}
/* amp init */
err = priv->cfg->ops->lib->apm_ops.init(priv);
if (err < 0) {
IWL_ERR(priv, "Failed to init APMG\n");
goto out_iounmap;
}
/*****************
* 4. Read EEPROM
*****************/

View file

@ -132,6 +132,7 @@ void iwl_calib_free_results(struct iwl_priv *priv)
priv->calib_results[i].buf_len = 0;
}
}
EXPORT_SYMBOL(iwl_calib_free_results);
/*****************************************************************************
* RUNTIME calibrations framework

View file

@ -3503,30 +3503,134 @@ struct iwl_led_cmd {
} __attribute__ ((packed));
/*
* Coexistence WIFI/WIMAX Command
* COEX_PRIORITY_TABLE_CMD = 0x5a
*
* station priority table entries
* also used as potential "events" value for both
* COEX_MEDIUM_NOTIFICATION and COEX_EVENT_CMD
*/
/*
* COEX events entry flag masks
* RP - Requested Priority
* WP - Win Medium Priority: priority assigned when the contention has been won
*/
#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG (0x1)
#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG (0x2)
#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG (0x4)
#define COEX_CU_UNASSOC_IDLE_RP 4
#define COEX_CU_UNASSOC_MANUAL_SCAN_RP 4
#define COEX_CU_UNASSOC_AUTO_SCAN_RP 4
#define COEX_CU_CALIBRATION_RP 4
#define COEX_CU_PERIODIC_CALIBRATION_RP 4
#define COEX_CU_CONNECTION_ESTAB_RP 4
#define COEX_CU_ASSOCIATED_IDLE_RP 4
#define COEX_CU_ASSOC_MANUAL_SCAN_RP 4
#define COEX_CU_ASSOC_AUTO_SCAN_RP 4
#define COEX_CU_ASSOC_ACTIVE_LEVEL_RP 4
#define COEX_CU_RF_ON_RP 6
#define COEX_CU_RF_OFF_RP 4
#define COEX_CU_STAND_ALONE_DEBUG_RP 6
#define COEX_CU_IPAN_ASSOC_LEVEL_RP 4
#define COEX_CU_RSRVD1_RP 4
#define COEX_CU_RSRVD2_RP 4
#define COEX_CU_UNASSOC_IDLE_WP 3
#define COEX_CU_UNASSOC_MANUAL_SCAN_WP 3
#define COEX_CU_UNASSOC_AUTO_SCAN_WP 3
#define COEX_CU_CALIBRATION_WP 3
#define COEX_CU_PERIODIC_CALIBRATION_WP 3
#define COEX_CU_CONNECTION_ESTAB_WP 3
#define COEX_CU_ASSOCIATED_IDLE_WP 3
#define COEX_CU_ASSOC_MANUAL_SCAN_WP 3
#define COEX_CU_ASSOC_AUTO_SCAN_WP 3
#define COEX_CU_ASSOC_ACTIVE_LEVEL_WP 3
#define COEX_CU_RF_ON_WP 3
#define COEX_CU_RF_OFF_WP 3
#define COEX_CU_STAND_ALONE_DEBUG_WP 6
#define COEX_CU_IPAN_ASSOC_LEVEL_WP 3
#define COEX_CU_RSRVD1_WP 3
#define COEX_CU_RSRVD2_WP 3
#define COEX_UNASSOC_IDLE_FLAGS 0
#define COEX_UNASSOC_MANUAL_SCAN_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG)
#define COEX_UNASSOC_AUTO_SCAN_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG)
#define COEX_CALIBRATION_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG)
#define COEX_PERIODIC_CALIBRATION_FLAGS 0
/*
* COEX_CONNECTION_ESTAB:
* we need DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network.
*/
#define COEX_CONNECTION_ESTAB_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \
COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG)
#define COEX_ASSOCIATED_IDLE_FLAGS 0
#define COEX_ASSOC_MANUAL_SCAN_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG)
#define COEX_ASSOC_AUTO_SCAN_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG)
#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0
#define COEX_RF_ON_FLAGS 0
#define COEX_RF_OFF_FLAGS 0
#define COEX_STAND_ALONE_DEBUG_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG)
#define COEX_IPAN_ASSOC_LEVEL_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \
COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG)
#define COEX_RSRVD1_FLAGS 0
#define COEX_RSRVD2_FLAGS 0
/*
* COEX_CU_RF_ON is the event wrapping all radio ownership.
* We need DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network.
*/
#define COEX_CU_RF_ON_FLAGS \
(COEX_EVT_FLAG_MEDIUM_FREE_NTFY_FLG | \
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_FLG | \
COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_FLG)
enum {
/* un-association part */
COEX_UNASSOC_IDLE = 0,
COEX_UNASSOC_MANUAL_SCAN = 1,
COEX_UNASSOC_AUTO_SCAN = 2,
/* calibration */
COEX_CALIBRATION = 3,
COEX_PERIODIC_CALIBRATION = 4,
/* connection */
COEX_CONNECTION_ESTAB = 5,
/* association part */
COEX_ASSOCIATED_IDLE = 6,
COEX_ASSOC_MANUAL_SCAN = 7,
COEX_ASSOC_AUTO_SCAN = 8,
COEX_ASSOC_ACTIVE_LEVEL = 9,
/* RF ON/OFF */
COEX_RF_ON = 10,
COEX_RF_OFF = 11,
COEX_STAND_ALONE_DEBUG = 12,
/* IPAN */
COEX_IPAN_ASSOC_LEVEL = 13,
/* reserved */
COEX_RSRVD1 = 14,
COEX_RSRVD2 = 15,
COEX_NUM_OF_EVENTS = 16
};
/*
* Coexistence WIFI/WIMAX Command
* COEX_PRIORITY_TABLE_CMD = 0x5a
*
*/
struct iwl_wimax_coex_event_entry {
u8 request_prio;
u8 win_medium_prio;
@ -3551,6 +3655,55 @@ struct iwl_wimax_coex_cmd {
struct iwl_wimax_coex_event_entry sta_prio[COEX_NUM_OF_EVENTS];
} __attribute__ ((packed));
/*
* Coexistence MEDIUM NOTIFICATION
* COEX_MEDIUM_NOTIFICATION = 0x5b
*
* notification from uCode to host to indicate medium changes
*
*/
/*
* status field
* bit 0 - 2: medium status
* bit 3: medium change indication
* bit 4 - 31: reserved
*/
/* status option values, (0 - 2 bits) */
#define COEX_MEDIUM_BUSY (0x0) /* radio belongs to WiMAX */
#define COEX_MEDIUM_ACTIVE (0x1) /* radio belongs to WiFi */
#define COEX_MEDIUM_PRE_RELEASE (0x2) /* received radio release */
#define COEX_MEDIUM_MSK (0x7)
/* send notification status (1 bit) */
#define COEX_MEDIUM_CHANGED (0x8)
#define COEX_MEDIUM_CHANGED_MSK (0x8)
#define COEX_MEDIUM_SHIFT (3)
struct iwl_coex_medium_notification {
__le32 status;
__le32 events;
} __attribute__ ((packed));
/*
* Coexistence EVENT Command
* COEX_EVENT_CMD = 0x5c
*
* send from host to uCode for coex event request.
*/
/* flags options */
#define COEX_EVENT_REQUEST_MSK (0x1)
struct iwl_coex_event_cmd {
u8 flags;
u8 event;
__le16 reserved;
} __attribute__ ((packed));
struct iwl_coex_event_resp {
__le32 status;
} __attribute__ ((packed));
/******************************************************************************
* (13)
* Union of all expected notifications/responses:
@ -3587,6 +3740,8 @@ struct iwl_rx_packet {
struct iwl_notif_statistics stats;
struct iwl_compressed_ba_resp compressed_ba;
struct iwl_missed_beacon_notif missed_beacon;
struct iwl_coex_medium_notification coex_medium_notif;
struct iwl_coex_event_resp coex_event;
__le32 status;
u8 raw[0];
} u;

View file

@ -46,6 +46,37 @@ MODULE_VERSION(IWLWIFI_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
{COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
0, COEX_UNASSOC_IDLE_FLAGS},
{COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP,
0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
{COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP,
0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
{COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP,
0, COEX_CALIBRATION_FLAGS},
{COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP,
0, COEX_PERIODIC_CALIBRATION_FLAGS},
{COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP,
0, COEX_CONNECTION_ESTAB_FLAGS},
{COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP,
0, COEX_ASSOCIATED_IDLE_FLAGS},
{COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP,
0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
{COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP,
0, COEX_ASSOC_AUTO_SCAN_FLAGS},
{COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP,
0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
{COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS},
{COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS},
{COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP,
0, COEX_STAND_ALONE_DEBUG_FLAGS},
{COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP,
0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
{COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS},
{COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS}
};
#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
IWL_RATE_SISO_##s##M_PLCP, \
@ -414,8 +445,12 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
if (priv->cfg->ht_greenfield_support)
ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
(WLAN_HT_CAP_SM_PS_DISABLED << 2));
if (priv->cfg->support_sm_ps)
ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
(WLAN_HT_CAP_SM_PS_DYNAMIC << 2));
else
ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
(WLAN_HT_CAP_SM_PS_DISABLED << 2));
max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.ht40_channel & BIT(band)) {
@ -451,28 +486,6 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
}
}
static void iwlcore_init_hw_rates(struct iwl_priv *priv,
struct ieee80211_rate *rates)
{
int i;
for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
rates[i].bitrate = iwl_rates[i].ieee * 5;
rates[i].hw_value = i; /* Rate scaling will work on indexes */
rates[i].hw_value_short = i;
rates[i].flags = 0;
if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
/*
* If CCK != 1M then set short preamble rate flag.
*/
rates[i].flags |=
(iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ?
0 : IEEE80211_RATE_SHORT_PREAMBLE;
}
}
}
/**
* iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom
*/
@ -985,17 +998,35 @@ static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
}
/*
* When we are in power saving, there's no difference between
* using multiple chains or just a single chain, but due to the
* lack of SM PS we lose a lot of throughput if we use just a
* single chain.
*
* Therefore, use the active count here (which will use multiple
* chains unless connected to a legacy AP).
* When we are in power saving mode, unless device support spatial
* multiplexing power save, use the active count for rx chain count.
*/
static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
{
return active_cnt;
int idle_cnt = active_cnt;
bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
if (priv->cfg->support_sm_ps) {
/* # Rx chains when idling and maybe trying to save power */
switch (priv->current_ht_config.sm_ps) {
case WLAN_HT_CAP_SM_PS_STATIC:
case WLAN_HT_CAP_SM_PS_DYNAMIC:
idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL :
IWL_NUM_IDLE_CHAINS_SINGLE;
break;
case WLAN_HT_CAP_SM_PS_DISABLED:
idle_cnt = (is_cam) ? active_cnt :
IWL_NUM_IDLE_CHAINS_SINGLE;
break;
case WLAN_HT_CAP_SM_PS_INVALID:
default:
IWL_ERR(priv, "invalid sm_ps mode %d\n",
priv->current_ht_config.sm_ps);
WARN_ON(1);
break;
}
}
return idle_cnt;
}
/* up to 4 chains */
@ -1353,39 +1384,39 @@ EXPORT_SYMBOL(iwl_irq_handle_error);
int iwl_apm_stop_master(struct iwl_priv *priv)
{
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&priv->lock, flags);
/* set stop master bit */
/* stop device's busmaster DMA activity */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (ret)
IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_INFO(priv, "stop master\n");
return 0;
return ret;
}
EXPORT_SYMBOL(iwl_apm_stop_master);
void iwl_apm_stop(struct iwl_priv *priv)
{
unsigned long flags;
IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");
/* Stop device's DMA activity */
iwl_apm_stop_master(priv);
spin_lock_irqsave(&priv->lock, flags);
/* Reset the entire device */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
udelay(10);
/* clear "init complete" move adapter D0A* --> D0U state */
/*
* Clear "initialization complete" bit to move adapter from
* D0A* (powered-up Active) --> D0U* (Uninitialized) state.
*/
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
spin_unlock_irqrestore(&priv->lock, flags);
}
EXPORT_SYMBOL(iwl_apm_stop);
@ -1430,8 +1461,12 @@ int iwl_apm_init(struct iwl_priv *priv)
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
/*
* HW bug W/A - costs negligible power consumption ...
* Check if BIOS (or OS) enabled L1-ASPM on this device
* HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
* Check if BIOS (or OS) enabled L1-ASPM on this device.
* If so (likely), disable L0S, so device moves directly L0->L1;
* costs negligible amount of power savings.
* If not (unlikely), enable L0S, so there is at least some
* power savings, even without L1.
*/
if (priv->cfg->set_l0s) {
lctl = iwl_pcie_link_ctl(priv);
@ -1567,68 +1602,6 @@ int iwl_set_hw_params(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_set_hw_params);
int iwl_init_drv(struct iwl_priv *priv)
{
int ret;
priv->ibss_beacon = NULL;
spin_lock_init(&priv->lock);
spin_lock_init(&priv->sta_lock);
spin_lock_init(&priv->hcmd_lock);
INIT_LIST_HEAD(&priv->free_frames);
mutex_init(&priv->mutex);
/* Clear the driver's (not device's) station table */
iwl_clear_stations_table(priv);
priv->ieee_channels = NULL;
priv->ieee_rates = NULL;
priv->band = IEEE80211_BAND_2GHZ;
priv->iw_mode = NL80211_IFTYPE_STATION;
/* Choose which receivers/antennas to use */
if (priv->cfg->ops->hcmd->set_rxon_chain)
priv->cfg->ops->hcmd->set_rxon_chain(priv);
iwl_init_scan_params(priv);
iwl_reset_qos(priv);
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
priv->rates_mask = IWL_RATES_MASK;
/* Set the tx_power_user_lmt to the lowest power level
* this value will get overwritten by channel max power avg
* from eeprom */
priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN;
ret = iwl_init_channel_map(priv);
if (ret) {
IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
goto err;
}
ret = iwlcore_init_geos(priv);
if (ret) {
IWL_ERR(priv, "initializing geos failed: %d\n", ret);
goto err_free_channel_map;
}
iwlcore_init_hw_rates(priv, priv->ieee_rates);
return 0;
err_free_channel_map:
iwl_free_channel_map(priv);
err:
return ret;
}
EXPORT_SYMBOL(iwl_init_drv);
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
{
int ret = 0;
@ -1676,15 +1649,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
}
EXPORT_SYMBOL(iwl_set_tx_power);
void iwl_uninit_drv(struct iwl_priv *priv)
{
iwl_calib_free_results(priv);
iwlcore_free_geos(priv);
iwl_free_channel_map(priv);
kfree(priv->scan);
}
EXPORT_SYMBOL(iwl_uninit_drv);
#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
/* Free dram table */
@ -2336,7 +2300,7 @@ static void iwl_ht_conf(struct iwl_priv *priv,
switch (priv->iw_mode) {
case NL80211_IFTYPE_STATION:
rcu_read_lock();
sta = ieee80211_find_sta(priv->hw, priv->bssid);
sta = ieee80211_find_sta(priv->vif, priv->bssid);
if (sta) {
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
int maxstreams;
@ -2346,6 +2310,12 @@ static void iwl_ht_conf(struct iwl_priv *priv,
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
maxstreams += 1;
ht_conf->sm_ps =
(u8)((ht_cap->cap & IEEE80211_HT_CAP_SM_PS)
>> 2);
IWL_DEBUG_MAC80211(priv, "sm_ps: 0x%x\n",
ht_conf->sm_ps);
if ((ht_cap->mcs.rx_mask[1] == 0) &&
(ht_cap->mcs.rx_mask[2] == 0))
ht_conf->single_chain_sufficient = true;
@ -2926,6 +2896,34 @@ void iwl_free_txq_mem(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_free_txq_mem);
int iwl_send_wimax_coex(struct iwl_priv *priv)
{
struct iwl_wimax_coex_cmd uninitialized_var(coex_cmd);
if (priv->cfg->support_wimax_coexist) {
/* UnMask wake up src at associated sleep */
coex_cmd.flags |= COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
/* UnMask wake up src at unassociated sleep */
coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK;
memcpy(coex_cmd.sta_prio, cu_priorities,
sizeof(struct iwl_wimax_coex_event_entry) *
COEX_NUM_OF_EVENTS);
/* enabling the coexistence feature */
coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK;
/* enabling the priorities tables */
coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK;
} else {
/* coexistence is disabled */
memset(&coex_cmd, 0, sizeof(coex_cmd));
}
return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD,
sizeof(coex_cmd), &coex_cmd);
}
EXPORT_SYMBOL(iwl_send_wimax_coex);
#ifdef CONFIG_IWLWIFI_DEBUGFS
#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)

View file

@ -228,6 +228,8 @@ struct iwl_mod_params {
* @chain_noise_num_beacons: number of beacons used to compute chain noise
* @adv_thermal_throttle: support advance thermal throttle
* @support_ct_kill_exit: support ct kill exit condition
* @support_sm_ps: support spatial multiplexing power save
* @support_wimax_coexist: support wimax/wifi co-exist
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
@ -283,6 +285,8 @@ struct iwl_cfg {
const bool supports_idle;
bool adv_thermal_throttle;
bool support_ct_kill_exit;
bool support_sm_ps;
const bool support_wimax_coexist;
};
/***************************
@ -316,8 +320,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
unsigned int *total_flags, u64 multicast);
int iwl_hw_nic_init(struct iwl_priv *priv);
int iwl_set_hw_params(struct iwl_priv *priv);
int iwl_init_drv(struct iwl_priv *priv);
void iwl_uninit_drv(struct iwl_priv *priv);
bool iwl_is_monitor_mode(struct iwl_priv *priv);
void iwl_post_associate(struct iwl_priv *priv);
void iwl_bss_info_changed(struct ieee80211_hw *hw,
@ -340,6 +342,7 @@ int iwl_alloc_txq_mem(struct iwl_priv *priv);
void iwl_free_txq_mem(struct iwl_priv *priv);
void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags);
int iwl_send_wimax_coex(struct iwl_priv *priv);
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_alloc_traffic_mem(struct iwl_priv *priv);
void iwl_free_traffic_mem(struct iwl_priv *priv);

View file

@ -517,6 +517,7 @@ struct iwl_ht_config {
bool is_ht;
bool is_40mhz;
bool single_chain_sufficient;
u8 sm_ps;
/* BSS related data */
u8 extension_chan_offset;
u8 ht_protection;

View file

@ -533,6 +533,10 @@ int iwl_eeprom_init(struct iwl_priv *priv)
goto err;
}
if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
/* OTP reads require powered-up chip */
priv->cfg->ops->lib->apm_ops.init(priv);
ret = iwl_init_otp_access(priv);
if (ret) {
IWL_ERR(priv, "Failed to initialize OTP access.\n");
@ -563,6 +567,13 @@ int iwl_eeprom_init(struct iwl_priv *priv)
e[cache_addr / 2] = eeprom_data;
cache_addr += sizeof(u16);
}
/*
* Now that OTP reads are complete, reset chip to save
* power until we load uCode during "up".
*/
priv->cfg->ops->lib->apm_ops.stop(priv);
} else {
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {

View file

@ -55,6 +55,8 @@ const char *get_cmd_string(u8 cmd)
IWL_CMD(REPLY_LEDS_CMD);
IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
IWL_CMD(COEX_PRIORITY_TABLE_CMD);
IWL_CMD(COEX_MEDIUM_NOTIFICATION);
IWL_CMD(COEX_EVENT_CMD);
IWL_CMD(RADAR_NOTIFICATION);
IWL_CMD(REPLY_QUIET_CMD);
IWL_CMD(REPLY_CHANNEL_SWITCH);

View file

@ -401,6 +401,7 @@ void iwl_init_scan_params(struct iwl_priv *priv)
if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
}
EXPORT_SYMBOL(iwl_init_scan_params);
static int iwl_scan_initiate(struct iwl_priv *priv)
{

View file

@ -182,6 +182,11 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
goto done;
mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
"static" :
(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
"dynamic" : "disabled");
sta_flags = priv->stations[index].sta.station_flags;
@ -1012,7 +1017,7 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
*/
if (priv->current_ht_config.is_ht) {
rcu_read_lock();
sta = ieee80211_find_sta(priv->hw, addr);
sta = ieee80211_find_sta(priv->vif, addr);
if (sta) {
memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
cur_ht_config = &ht_config;
@ -1029,6 +1034,68 @@ int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap)
}
EXPORT_SYMBOL(iwl_rxon_add_station);
/**
* iwl_sta_init_bcast_lq - Initialize a bcast station's hardware rate table
*
* NOTE: Run REPLY_ADD_STA command to set up station table entry, before
* calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
* which requires station table entry to exist).
*/
static void iwl_sta_init_bcast_lq(struct iwl_priv *priv)
{
int i, r;
struct iwl_link_quality_cmd link_cmd = {
.reserved1 = 0,
};
u32 rate_flags;
/* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */
if (priv->band == IEEE80211_BAND_5GHZ)
r = IWL_RATE_6M_INDEX;
else
r = IWL_RATE_1M_INDEX;
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
rate_flags = 0;
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
RATE_MCS_ANT_POS;
link_cmd.rs_table[i].rate_n_flags =
iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
r = iwl_get_prev_ieee_rate(r);
}
link_cmd.general_params.single_stream_ant_msk =
first_antenna(priv->hw_params.valid_tx_ant);
link_cmd.general_params.dual_stream_ant_msk = 3;
link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
link_cmd.agg_params.agg_time_limit =
cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
/* Update the rate scaling for control frame Tx to AP */
link_cmd.sta_id = priv->hw_params.bcast_sta_id;
iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD,
sizeof(link_cmd), &link_cmd, NULL);
}
/**
* iwl_add_bcast_station - add broadcast station into station table.
*/
void iwl_add_bcast_station(struct iwl_priv *priv)
{
iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL);
/* Set up default rate scaling table in device's station table */
iwl_sta_init_bcast_lq(priv);
}
EXPORT_SYMBOL(iwl_add_bcast_station);
/**
* iwl_get_sta_id - Find station's index within station table
*

View file

@ -52,6 +52,7 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
const u8 *addr, u32 iv32, u16 *phase1key);
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
void iwl_add_bcast_station(struct iwl_priv *priv);
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap);
void iwl_clear_stations_table(struct iwl_priv *priv);
int iwl_get_free_ucode_key_index(struct iwl_priv *priv);

View file

@ -979,7 +979,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
!(cmd->flags & CMD_SIZE_HUGE));
if (iwl_is_rfkill(priv) || iwl_is_ctkill(priv)) {
IWL_DEBUG_INFO(priv, "Not sending command - RF/CT KILL\n");
IWL_WARN(priv, "Not sending command - %s KILL\n",
iwl_is_rfkill(priv) ? "RF" : "CT");
return -EIO;
}
@ -1121,11 +1122,6 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
return;
}
pci_unmap_single(priv->pci_dev,
pci_unmap_addr(&txq->meta[cmd_idx], mapping),
pci_unmap_len(&txq->meta[cmd_idx], len),
PCI_DMA_BIDIRECTIONAL);
for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
@ -1173,6 +1169,11 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index];
pci_unmap_single(priv->pci_dev,
pci_unmap_addr(meta, mapping),
pci_unmap_len(meta, len),
PCI_DMA_BIDIRECTIONAL);
/* Input error checking is done when commands are added to queue. */
if (meta->flags & CMD_WANT_SKB) {
meta->source->reply_page = (unsigned long)rxb_addr(rxb);

View file

@ -2160,6 +2160,14 @@ static int iwl3945_read_ucode(struct iwl_priv *priv)
IWL_UCODE_API(priv->ucode_ver),
IWL_UCODE_SERIAL(priv->ucode_ver));
snprintf(priv->hw->wiphy->fw_version,
sizeof(priv->hw->wiphy->fw_version),
"%u.%u.%u.%u",
IWL_UCODE_MAJOR(priv->ucode_ver),
IWL_UCODE_MINOR(priv->ucode_ver),
IWL_UCODE_API(priv->ucode_ver),
IWL_UCODE_SERIAL(priv->ucode_ver));
IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
priv->ucode_ver);
IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
@ -3992,13 +4000,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
*/
spin_lock_init(&priv->reg_lock);
/* amp init */
err = priv->cfg->ops->lib->apm_ops.init(priv);
if (err < 0) {
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
goto out_iounmap;
}
/***********************
* 4. Read EEPROM
* ********************/

View file

@ -1,6 +1,6 @@
config IWM
tristate "Intel Wireless Multicomm 3200 WiFi driver"
depends on MMC && WLAN_80211 && EXPERIMENTAL
depends on MMC && EXPERIMENTAL
depends on CFG80211
select FW_LOADER
select IWMC3200TOP

View file

@ -1,6 +1,6 @@
config LIBERTAS
tristate "Marvell 8xxx Libertas WLAN driver support"
depends on WLAN_80211 && CFG80211
depends on CFG80211
select WIRELESS_EXT
select WEXT_SPY
select LIB80211

View file

@ -32,12 +32,6 @@
#include "dev.h"
#include "if_spi.h"
struct if_spi_packet {
struct list_head list;
u16 blen;
u8 buffer[0] __attribute__((aligned(4)));
};
struct if_spi_card {
struct spi_device *spi;
struct lbs_private *priv;
@ -66,33 +60,10 @@ struct if_spi_card {
struct semaphore spi_thread_terminated;
u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE];
/* A buffer of incoming packets from libertas core.
* Since we can't sleep in hw_host_to_card, we have to buffer
* them. */
struct list_head cmd_packet_list;
struct list_head data_packet_list;
/* Protects cmd_packet_list and data_packet_list */
spinlock_t buffer_lock;
};
static void free_if_spi_card(struct if_spi_card *card)
{
struct list_head *cursor, *next;
struct if_spi_packet *packet;
BUG_ON(card->run_thread);
list_for_each_safe(cursor, next, &card->cmd_packet_list) {
packet = container_of(cursor, struct if_spi_packet, list);
list_del(&packet->list);
kfree(packet);
}
list_for_each_safe(cursor, next, &card->data_packet_list) {
packet = container_of(cursor, struct if_spi_packet, list);
list_del(&packet->list);
kfree(packet);
}
spi_set_drvdata(card->spi, NULL);
kfree(card);
}
@ -774,40 +745,6 @@ out:
return err;
}
/* Move data or a command from the host to the card. */
static void if_spi_h2c(struct if_spi_card *card,
struct if_spi_packet *packet, int type)
{
int err = 0;
u16 int_type, port_reg;
switch (type) {
case MVMS_DAT:
int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
port_reg = IF_SPI_DATA_RDWRPORT_REG;
break;
case MVMS_CMD:
int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
port_reg = IF_SPI_CMD_RDWRPORT_REG;
break;
default:
lbs_pr_err("can't transfer buffer of type %d\n", type);
err = -EINVAL;
goto out;
}
/* Write the data to the card */
err = spu_write(card, port_reg, packet->buffer, packet->blen);
if (err)
goto out;
out:
kfree(packet);
if (err)
lbs_pr_err("%s: error %d\n", __func__, err);
}
/* Inform the host about a card event */
static void if_spi_e2h(struct if_spi_card *card)
{
@ -837,8 +774,6 @@ static int lbs_spi_thread(void *data)
int err;
struct if_spi_card *card = data;
u16 hiStatus;
unsigned long flags;
struct if_spi_packet *packet;
while (1) {
/* Wait to be woken up by one of two things. First, our ISR
@ -877,43 +812,9 @@ static int lbs_spi_thread(void *data)
if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
(card->priv->psstate != PS_STATE_FULL_POWER &&
(hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
/* This means two things. First of all,
* if there was a previous command sent, the card has
* successfully received it.
* Secondly, it is now ready to download another
* command.
*/
lbs_host_to_card_done(card->priv);
/* Do we have any command packets from the host to
* send? */
packet = NULL;
spin_lock_irqsave(&card->buffer_lock, flags);
if (!list_empty(&card->cmd_packet_list)) {
packet = (struct if_spi_packet *)(card->
cmd_packet_list.next);
list_del(&packet->list);
}
spin_unlock_irqrestore(&card->buffer_lock, flags);
if (packet)
if_spi_h2c(card, packet, MVMS_CMD);
}
if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
/* Do we have any data packets from the host to
* send? */
packet = NULL;
spin_lock_irqsave(&card->buffer_lock, flags);
if (!list_empty(&card->data_packet_list)) {
packet = (struct if_spi_packet *)(card->
data_packet_list.next);
list_del(&packet->list);
}
spin_unlock_irqrestore(&card->buffer_lock, flags);
if (packet)
if_spi_h2c(card, packet, MVMS_DAT);
}
if (hiStatus & IF_SPI_HIST_CARD_EVENT)
if_spi_e2h(card);
@ -942,40 +843,18 @@ static int if_spi_host_to_card(struct lbs_private *priv,
u8 type, u8 *buf, u16 nb)
{
int err = 0;
unsigned long flags;
struct if_spi_card *card = priv->card;
struct if_spi_packet *packet;
u16 blen;
lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
if (nb == 0) {
lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
err = -EINVAL;
goto out;
}
blen = ALIGN(nb, 4);
packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
if (!packet) {
err = -ENOMEM;
goto out;
}
packet->blen = blen;
memcpy(packet->buffer, buf, nb);
memset(packet->buffer + nb, 0, blen - nb);
nb = ALIGN(nb, 4);
switch (type) {
case MVMS_CMD:
priv->dnld_sent = DNLD_CMD_SENT;
spin_lock_irqsave(&card->buffer_lock, flags);
list_add_tail(&packet->list, &card->cmd_packet_list);
spin_unlock_irqrestore(&card->buffer_lock, flags);
err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb);
break;
case MVMS_DAT:
priv->dnld_sent = DNLD_DATA_SENT;
spin_lock_irqsave(&card->buffer_lock, flags);
list_add_tail(&packet->list, &card->data_packet_list);
spin_unlock_irqrestore(&card->buffer_lock, flags);
err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb);
break;
default:
lbs_pr_err("can't transfer buffer of type %d", type);
@ -983,9 +862,6 @@ static int if_spi_host_to_card(struct lbs_private *priv,
break;
}
/* Wake up the spi thread */
up(&card->spi_ready);
out:
lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
return err;
}
@ -1062,9 +938,6 @@ static int __devinit if_spi_probe(struct spi_device *spi)
sema_init(&card->spi_ready, 0);
sema_init(&card->spi_thread_terminated, 0);
INIT_LIST_HEAD(&card->cmd_packet_list);
INIT_LIST_HEAD(&card->data_packet_list);
spin_lock_init(&card->buffer_lock);
/* Initialize the SPI Interface Unit */
err = spu_init(card, pdata->use_dummy_writes);
@ -1141,6 +1014,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
goto terminate_thread;
}
/* poke the IRQ handler so that we don't miss the first interrupt */
up(&card->spi_ready);
/* Start the card.
* This will call register_netdev, and we'll start
* getting interrupts... */

View file

@ -284,7 +284,7 @@ struct mac80211_hwsim_data {
struct ieee80211_channel *channel;
unsigned long beacon_int; /* in jiffies unit */
unsigned int rx_filter;
int started;
bool started, idle;
struct timer_list beacon_timer;
enum ps_mode {
PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
@ -365,6 +365,49 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
}
static void mac80211_hwsim_monitor_ack(struct ieee80211_hw *hw, const u8 *addr)
{
struct mac80211_hwsim_data *data = hw->priv;
struct sk_buff *skb;
struct hwsim_radiotap_hdr *hdr;
u16 flags;
struct ieee80211_hdr *hdr11;
if (!netif_running(hwsim_mon))
return;
skb = dev_alloc_skb(100);
if (skb == NULL)
return;
hdr = (struct hwsim_radiotap_hdr *) skb_put(skb, sizeof(*hdr));
hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION;
hdr->hdr.it_pad = 0;
hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr));
hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_CHANNEL));
hdr->rt_flags = 0;
hdr->rt_rate = 0;
hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
flags = IEEE80211_CHAN_2GHZ;
hdr->rt_chbitmask = cpu_to_le16(flags);
hdr11 = (struct ieee80211_hdr *) skb_put(skb, 10);
hdr11->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
IEEE80211_STYPE_ACK);
hdr11->duration_id = cpu_to_le16(0);
memcpy(hdr11->addr1, addr, ETH_ALEN);
skb->dev = hwsim_mon;
skb_set_mac_header(skb, 0);
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = htons(ETH_P_802_2);
memset(skb->cb, 0, sizeof(skb->cb));
netif_rx(skb);
}
static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
struct sk_buff *skb)
{
@ -402,6 +445,12 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_rx_status rx_status;
if (data->idle) {
printk(KERN_DEBUG "%s: Trying to TX when idle - reject\n",
wiphy_name(hw->wiphy));
return false;
}
memset(&rx_status, 0, sizeof(rx_status));
/* TODO: set mactime */
rx_status.freq = data->channel->center_freq;
@ -428,7 +477,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
if (data == data2)
continue;
if (!data2->started || !hwsim_ps_rx_ok(data2, skb) ||
if (data2->idle || !data2->started ||
!hwsim_ps_rx_ok(data2, skb) ||
!data->channel || !data2->channel ||
data->channel->center_freq != data2->channel->center_freq ||
!(data->group & data2->group))
@ -464,6 +514,10 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
}
ack = mac80211_hwsim_tx_frame(hw, skb);
if (ack && skb->len >= 16) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
mac80211_hwsim_monitor_ack(hw, hdr->addr2);
}
txi = IEEE80211_SKB_CB(skb);
@ -571,6 +625,8 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
!!(conf->flags & IEEE80211_CONF_IDLE),
!!(conf->flags & IEEE80211_CONF_PS));
data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
data->channel = conf->channel;
if (!data->started || !data->beacon_int)
del_timer(&data->beacon_timer);
@ -1045,19 +1101,20 @@ static int __init init_mac80211_hwsim(void)
sband->channels = data->channels_2ghz;
sband->n_channels =
ARRAY_SIZE(hwsim_channels_2ghz);
sband->bitrates = data->rates;
sband->n_bitrates = ARRAY_SIZE(hwsim_rates);
break;
case IEEE80211_BAND_5GHZ:
sband->channels = data->channels_5ghz;
sband->n_channels =
ARRAY_SIZE(hwsim_channels_5ghz);
sband->bitrates = data->rates + 4;
sband->n_bitrates = ARRAY_SIZE(hwsim_rates) - 4;
break;
default:
break;
}
sband->bitrates = data->rates;
sband->n_bitrates = ARRAY_SIZE(hwsim_rates);
sband->ht_cap.ht_supported = true;
sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD |

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
config HERMES
tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)"
depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211
depends on (PPC_PMAC || PCI || PCMCIA)
depends on CFG80211 && CFG80211_WEXT
select WIRELESS_EXT
select WEXT_SPY

View file

@ -1,6 +1,6 @@
config P54_COMMON
tristate "Softmac Prism54 support"
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
depends on MAC80211 && EXPERIMENTAL
select FW_LOADER
---help---
This is common code for isl38xx/stlc45xx based modules.

View file

@ -126,7 +126,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
int ret = -ENOMEM;
if ((!list->entries) || (!list->band_channel_num[band]))
return 0;
return -EINVAL;
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp)
@ -158,6 +158,7 @@ static int p54_generate_band(struct ieee80211_hw *dev,
(list->channels[i].data & CHAN_HAS_CURVE ? "" :
" [curve data]"),
list->channels[i].index, list->channels[i].freq);
continue;
}
tmp->channels[j].band = list->channels[i].band;
@ -165,7 +166,16 @@ static int p54_generate_band(struct ieee80211_hw *dev,
j++;
}
tmp->n_channels = list->band_channel_num[band];
if (j == 0) {
printk(KERN_ERR "%s: Disabling totally damaged %s band.\n",
wiphy_name(dev->wiphy), (band == IEEE80211_BAND_2GHZ) ?
"2 GHz" : "5 GHz");
ret = -ENODATA;
goto err_out;
}
tmp->n_channels = j;
old = priv->band_table[band];
priv->band_table[band] = tmp;
if (old) {
@ -228,13 +238,13 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
struct p54_common *priv = dev->priv;
struct p54_channel_list *list;
unsigned int i, j, max_channel_num;
int ret = -ENOMEM;
int ret = 0;
u16 freq;
if ((priv->iq_autocal_len != priv->curve_data->entries) ||
(priv->iq_autocal_len != priv->output_limit->entries))
printk(KERN_ERR "%s: EEPROM is damaged... you may not be able"
"to use all channels with this device.\n",
printk(KERN_ERR "%s: Unsupported or damaged EEPROM detected. "
"You may not be able to use all channels.\n",
wiphy_name(dev->wiphy));
max_channel_num = max_t(unsigned int, priv->output_limit->entries,
@ -243,8 +253,10 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
priv->curve_data->entries);
list = kzalloc(sizeof(*list), GFP_KERNEL);
if (!list)
if (!list) {
ret = -ENOMEM;
goto free;
}
list->max_entries = max_channel_num;
list->channels = kzalloc(sizeof(struct p54_channel_entry) *
@ -282,13 +294,8 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
p54_compare_channels, NULL);
for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) {
if (list->band_channel_num[i]) {
ret = p54_generate_band(dev, list, i);
if (ret)
goto free;
if (p54_generate_band(dev, list, i) == 0)
j++;
}
}
if (j == 0) {
/* no useable band available. */

View file

@ -1,6 +1,6 @@
menuconfig RT2X00
tristate "Ralink driver support"
depends on MAC80211 && WLAN_80211
depends on MAC80211
---help---
This will enable the support for the Ralink drivers,
developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
@ -64,8 +64,9 @@ config RT2800PCI_SOC
default y
config RT2800PCI
tristate "Ralink rt2800 (PCI/PCMCIA) support"
tristate "Ralink rt2800 (PCI/PCMCIA) support (VERY EXPERIMENTAL)"
depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL
select RT2800_LIB
select RT2X00_LIB_PCI if RT2800PCI_PCI
select RT2X00_LIB_SOC if RT2800PCI_SOC
select RT2X00_LIB_HT
@ -77,6 +78,9 @@ config RT2800PCI
This adds support for rt2800 wireless chipset family.
Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052
This driver is non-functional at the moment and is intended for
developers.
When compiled as a module, this driver will be called "rt2800pci.ko".
config RT2500USB
@ -104,8 +108,9 @@ config RT73USB
When compiled as a module, this driver will be called rt73usb.
config RT2800USB
tristate "Ralink rt2800 (USB) support"
tristate "Ralink rt2800 (USB) support (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
select RT2800_LIB
select RT2X00_LIB_USB
select RT2X00_LIB_HT
select RT2X00_LIB_FIRMWARE
@ -115,8 +120,15 @@ config RT2800USB
This adds experimental support for rt2800 wireless chipset family.
Supported chips: RT2770, RT2870 & RT3070.
Known issues:
- support for RT2870 chips doesn't work with 802.11n APs yet
- support for RT3070 chips is non-functional at the moment
When compiled as a module, this driver will be called "rt2800usb.ko".
config RT2800_LIB
tristate
config RT2X00_LIB_PCI
tristate
select RT2X00_LIB

View file

@ -13,6 +13,7 @@ obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o
obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
obj-$(CONFIG_RT2800_LIB) += rt2800lib.o
obj-$(CONFIG_RT2400PCI) += rt2400pci.o
obj-$(CONFIG_RT2500PCI) += rt2500pci.o
obj-$(CONFIG_RT61PCI) += rt61pci.o

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,134 @@
/*
Copyright (C) 2009 Bartlomiej Zolnierkiewicz
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the
Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef RT2800LIB_H
#define RT2800LIB_H
struct rt2800_ops {
void (*register_read)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 *value);
void (*register_write)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 value);
void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 value);
void (*register_multiread)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length);
void (*register_multiwrite)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const void *value, const u32 length);
int (*regbusy_read)(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const struct rt2x00_field32 field, u32 *reg);
};
static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 *value)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
rt2800ops->register_read(rt2x00dev, offset, value);
}
static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 value)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
rt2800ops->register_write(rt2x00dev, offset, value);
}
static inline void rt2800_register_write_lock(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 value)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
rt2800ops->register_write_lock(rt2x00dev, offset, value);
}
static inline void rt2800_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
rt2800ops->register_multiread(rt2x00dev, offset, value, length);
}
static inline void rt2800_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const void *value,
const u32 length)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
rt2800ops->register_multiwrite(rt2x00dev, offset, value, length);
}
static inline int rt2800_regbusy_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const struct rt2x00_field32 field,
u32 *reg)
{
const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
return rt2800ops->regbusy_read(rt2x00dev, offset, field, reg);
}
void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1);
extern const struct rt2x00debug rt2800_rt2x00debug;
int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev);
void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
struct rt2x00_led *led, enum led_type type);
int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags);
void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
struct rt2x00intf_conf *conf, const unsigned int flags);
void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp);
void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant);
void rt2800_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags);
void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
const u32 count);
int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev);
int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev);
extern const struct ieee80211_ops rt2800_mac80211_ops;
#endif /* RT2800LIB_H */

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -144,6 +144,11 @@ struct avg_val {
int avg_weight;
};
enum rt2x00_chip_intf {
RT2X00_CHIP_INTF_PCI,
RT2X00_CHIP_INTF_USB,
};
/*
* Chipset identification
* The chipset on the device is composed of a RT and RF chip.
@ -169,6 +174,8 @@ struct rt2x00_chip {
u16 rf;
u32 rev;
enum rt2x00_chip_intf intf;
};
/*
@ -842,8 +849,22 @@ struct rt2x00_dev {
* Firmware image.
*/
const struct firmware *fw;
/*
* Driver specific data.
*/
void *priv;
};
/*
* Register defines.
* Some registers require multiple attempts before success,
* in those cases REGISTER_BUSY_COUNT attempts should be
* taken with a REGISTER_BUSY_DELAY interval.
*/
#define REGISTER_BUSY_COUNT 5
#define REGISTER_BUSY_DELAY 100
/*
* Generic RF access.
* The RF is being accessed by word index.
@ -932,6 +953,28 @@ static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset,
return ((chipset->rev & mask) == rev);
}
static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
enum rt2x00_chip_intf intf)
{
rt2x00dev->chip.intf = intf;
}
static inline bool rt2x00_intf(const struct rt2x00_chip *chipset,
enum rt2x00_chip_intf intf)
{
return (chipset->intf == intf);
}
static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev)
{
return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI);
}
static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev)
{
return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB);
}
/**
* rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
* @rt2x00dev: Pointer to &struct rt2x00_dev.

View file

@ -33,8 +33,6 @@ enum led_type {
LED_TYPE_QUALITY,
};
#ifdef CONFIG_RT2X00_LIB_LEDS
struct rt2x00_led {
struct rt2x00_dev *rt2x00dev;
struct led_classdev led_dev;
@ -45,6 +43,4 @@ struct rt2x00_led {
#define LED_REGISTERED ( 1 << 1 )
};
#endif /* CONFIG_RT2X00_LIB_LEDS */
#endif /* RT2X00LEDS_H */

View file

@ -34,15 +34,6 @@
*/
#define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops)
/*
* Register defines.
* Some registers require multiple attempts before success,
* in those cases REGISTER_BUSY_COUNT attempts should be
* taken with a REGISTER_BUSY_DELAY interval.
*/
#define REGISTER_BUSY_COUNT 5
#define REGISTER_BUSY_DELAY 100
/*
* Register access.
*/
@ -53,10 +44,9 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
*value = readl(rt2x00dev->csr.base + offset);
}
static inline void
rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u16 length)
static inline void rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length)
{
memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
}
@ -68,10 +58,10 @@ static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
writel(value, rt2x00dev->csr.base + offset);
}
static inline void
rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const void *value, const u16 length)
static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
const void *value,
const u32 length)
{
memcpy_toio(rt2x00dev->csr.base + offset, value, length);
}

View file

@ -160,7 +160,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff);
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
struct rt2x00_field32 field,
const struct rt2x00_field32 field,
u32 *reg)
{
unsigned int i;

View file

@ -39,17 +39,11 @@
#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops)
/*
* Register defines.
* Some registers require multiple attempts before success,
* in those cases REGISTER_BUSY_COUNT attempts should be
* taken with a REGISTER_BUSY_DELAY interval.
* For USB vendor requests we need to pass a timeout
* time in ms, for this we use the REGISTER_TIMEOUT,
* however when loading firmware a higher value is
* required. In that case we use the REGISTER_TIMEOUT_FIRMWARE.
*/
#define REGISTER_BUSY_COUNT 5
#define REGISTER_BUSY_DELAY 100
#define REGISTER_TIMEOUT 500
#define REGISTER_TIMEOUT_FIRMWARE 1000
@ -232,7 +226,7 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
}
/**
* rt2x00usb_regbusy_read - Read 32bit register word
* rt2x00usb_register_read - Read 32bit register word
* @rt2x00dev: Device pointer, see &struct rt2x00_dev.
* @offset: Register offset
* @value: Pointer to where register contents should be stored
@ -340,12 +334,13 @@ static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
* through rt2x00usb_vendor_request_buff().
*/
static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length)
const unsigned int offset,
const void *value,
const u32 length)
{
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
value, length,
(void *)value, length,
REGISTER_TIMEOUT32(length));
}
@ -364,7 +359,7 @@ static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
*/
int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
struct rt2x00_field32 field,
const struct rt2x00_field32 field,
u32 *reg);
/*

View file

@ -119,7 +119,6 @@ struct rtl8187_priv {
} hw_rev;
struct sk_buff_head rx_queue;
u8 signal;
u8 quality;
u8 noise;
u8 slot_time;
u8 aifsn[4];

View file

@ -320,7 +320,6 @@ static void rtl8187_rx_cb(struct urb *urb)
struct ieee80211_rx_status rx_status = { 0 };
int rate, signal;
u32 flags;
u32 quality;
unsigned long f;
spin_lock_irqsave(&priv->rx_queue.lock, f);
@ -338,10 +337,9 @@ static void rtl8187_rx_cb(struct urb *urb)
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
flags = le32_to_cpu(hdr->flags);
/* As with the RTL8187B below, the AGC is used to calculate
* signal strength and quality. In this case, the scaling
* signal strength. In this case, the scaling
* constants are derived from the output of p54usb.
*/
quality = 130 - ((41 * hdr->agc) >> 6);
signal = -4 - ((27 * hdr->agc) >> 6);
rx_status.antenna = (hdr->signal >> 7) & 1;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
@ -354,23 +352,18 @@ static void rtl8187_rx_cb(struct urb *urb)
* In testing, none of these quantities show qualitative
* agreement with AP signal strength, except for the AGC,
* which is inversely proportional to the strength of the
* signal. In the following, the quality and signal strength
* are derived from the AGC. The arbitrary scaling constants
* signal. In the following, the signal strength
* is derived from the AGC. The arbitrary scaling constants
* are chosen to make the results close to the values obtained
* for a BCM4312 using b43 as the driver. The noise is ignored
* for now.
*/
flags = le32_to_cpu(hdr->flags);
quality = 170 - hdr->agc;
signal = 14 - hdr->agc / 2;
rx_status.antenna = (hdr->rssi >> 7) & 1;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
}
if (quality > 100)
quality = 100;
rx_status.qual = quality;
priv->quality = quality;
rx_status.signal = signal;
priv->signal = signal;
rate = (flags >> 20) & 0xF;

View file

@ -1,6 +1,6 @@
menuconfig WL12XX
tristate "TI wl12xx driver support"
depends on MAC80211 && WLAN_80211 && EXPERIMENTAL
depends on MAC80211 && EXPERIMENTAL
---help---
This will enable TI wl12xx driver support. The drivers make
use of the mac80211 stack.
@ -42,6 +42,7 @@ config WL1251_SDIO
config WL1271
tristate "TI wl1271 support"
depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS
depends on INET
select FW_LOADER
select CRC7
---help---

View file

@ -1311,7 +1311,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl)
wl->hw->channel_change_time = 10000;
wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
IEEE80211_HW_NOISE_DBM |
IEEE80211_HW_SUPPORTS_PS;
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
wl->hw->wiphy->max_scan_ssids = 1;

View file

@ -417,6 +417,9 @@ struct wl1271 {
/* PSM mode requested */
bool psm_requested;
/* retry counter for PSM entries */
u8 psm_entry_retry;
/* in dBm */
int power_level;

View file

@ -141,7 +141,7 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
* calibration, to avoid distortions
*/
/* acx->current_tx_power = power * 10; */
acx->current_tx_power = 70;
acx->current_tx_power = 120;
ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
if (ret < 0) {

View file

@ -380,7 +380,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
}
}
if (loop >= INIT_LOOP) {
if (loop > INIT_LOOP) {
wl1271_error("timeout waiting for the hardware to "
"complete initialization");
return -EIO;
@ -407,7 +407,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
/* unmask required mbox events */
wl->event_mask = BSS_LOSE_EVENT_ID |
SCAN_COMPLETE_EVENT_ID;
SCAN_COMPLETE_EVENT_ID |
PS_REPORT_EVENT_ID;
ret = wl1271_event_unmask(wl);
if (ret < 0) {

View file

@ -42,12 +42,14 @@
* @buf: buffer containing the command, must work with dma
* @len: length of the buffer
*/
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
size_t res_len)
{
struct wl1271_cmd_header *cmd;
unsigned long timeout;
u32 intr;
int ret = 0;
u16 status;
cmd = buf;
cmd->id = cpu_to_le16(id);
@ -74,6 +76,17 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
}
/* read back the status code of the command */
if (res_len == 0)
res_len = sizeof(struct wl1271_cmd_header);
wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false);
status = le16_to_cpu(cmd->status);
if (status != CMD_STATUS_SUCCESS) {
wl1271_error("command execute failure %d", status);
ret = -EIO;
}
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
WL1271_ACX_INTR_CMD_COMPLETE);
@ -262,7 +275,7 @@ int wl1271_cmd_join(struct wl1271 *wl)
wl->tx_security_seq_16 = 0;
wl->tx_security_seq_32 = 0;
ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
if (ret < 0) {
wl1271_error("failed to initiate cmd join");
goto out_free;
@ -294,35 +307,21 @@ out:
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
{
int ret;
size_t res_len = 0;
wl1271_debug(DEBUG_CMD, "cmd test");
ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len);
if (answer)
res_len = buf_len;
ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len, res_len);
if (ret < 0) {
wl1271_warning("TEST command failed");
return ret;
}
if (answer) {
struct wl1271_command *cmd_answer;
u16 status;
/*
* The test command got in, we can read the answer.
* The answer would be a wl1271_command, where the
* parameter array contains the actual answer.
*/
wl1271_spi_read(wl, wl->cmd_box_addr, buf, buf_len, false);
cmd_answer = buf;
status = le16_to_cpu(cmd_answer->header.status);
if (status != CMD_STATUS_SUCCESS)
wl1271_error("TEST command answer error: %d", status);
}
return 0;
return ret;
}
/**
@ -345,21 +344,10 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)
/* payload length, does not include any headers */
acx->len = cpu_to_le16(len - sizeof(*acx));
ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
if (ret < 0) {
ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx), len);
if (ret < 0)
wl1271_error("INTERROGATE command failed");
goto out;
}
/* the interrogate command got in, we can read the answer */
wl1271_spi_read(wl, wl->cmd_box_addr, buf, len, false);
acx = buf;
if (le16_to_cpu(acx->cmd.status) != CMD_STATUS_SUCCESS)
wl1271_error("INTERROGATE command error: %d",
le16_to_cpu(acx->cmd.status));
out:
return ret;
}
@ -383,7 +371,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
/* payload length, does not include any headers */
acx->len = cpu_to_le16(len - sizeof(*acx));
ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len);
ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len, 0);
if (ret < 0) {
wl1271_warning("CONFIGURE command NOK");
return ret;
@ -416,7 +404,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
cmd_tx = CMD_DISABLE_TX;
}
ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("rx %s cmd for channel %d failed",
enable ? "start" : "stop", channel);
@ -426,7 +414,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d",
enable ? "start" : "stop", channel);
ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("tx %s cmd for channel %d failed",
enable ? "start" : "stop", channel);
@ -468,7 +456,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
sizeof(*ps_params));
sizeof(*ps_params), 0);
if (ret < 0) {
wl1271_error("cmd set_ps_mode failed");
goto out;
@ -499,19 +487,14 @@ int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
cmd->addr = cpu_to_le32(addr);
cmd->size = cpu_to_le32(len);
ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd),
sizeof(*cmd));
if (ret < 0) {
wl1271_error("read memory command failed: %d", ret);
goto out;
}
/* the read command got in, we can now read the answer */
wl1271_spi_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd), false);
if (le16_to_cpu(cmd->header.status) != CMD_STATUS_SUCCESS)
wl1271_error("error in read command result: %d",
le16_to_cpu(cmd->header.status));
/* the read command got in */
memcpy(answer, cmd->value, len);
out:
@ -613,7 +596,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
trigger->timeout = 0;
ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
sizeof(*trigger));
sizeof(*trigger), 0);
if (ret < 0) {
wl1271_error("trigger scan to failed for hw scan");
goto out;
@ -636,20 +619,10 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
}
}
ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0);
if (ret < 0) {
wl1271_error("SCAN failed");
goto out;
}
wl1271_spi_read(wl, wl->cmd_box_addr, params, sizeof(*params),
false);
if (le16_to_cpu(params->header.status) != CMD_STATUS_SUCCESS) {
wl1271_error("Scan command error: %d",
le16_to_cpu(params->header.status));
wl->scanning = false;
ret = -EIO;
goto out;
}
@ -684,7 +657,7 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
if (buf)
memcpy(cmd->template_data, buf, buf_len);
ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_warning("cmd set_template failed: %d", ret);
goto out_free;
@ -863,7 +836,7 @@ int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
cmd->key_action = cpu_to_le16(KEY_SET_ID);
cmd->key_type = KEY_WEP;
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_warning("cmd set_default_wep_key failed: %d", ret);
goto out;
@ -920,7 +893,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_warning("could not set keys");
goto out;
@ -950,7 +923,7 @@ int wl1271_cmd_disconnect(struct wl1271 *wl)
/* disconnect reason is not used in immediate disconnections */
cmd->type = DISCONNECT_IMMEDIATE;
ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd));
ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0);
if (ret < 0) {
wl1271_error("failed to send disconnect command");
goto out_free;

View file

@ -29,7 +29,8 @@
struct acx_header;
int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len);
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
size_t res_len);
int wl1271_cmd_join(struct wl1271 *wl);
int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);

View file

@ -712,6 +712,14 @@ struct conf_conn_settings {
* Range 0 - 255
*/
u8 bet_max_consecutive;
/*
* Specifies the maximum number of times to try PSM entry if it fails
* (if sending the appropriate null-func message fails.)
*
* Range 0 - 255
*/
u8 psm_entry_retries;
};
#define CONF_SR_ERR_TBL_MAX_VALUES 14

View file

@ -68,6 +68,40 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
return 0;
}
static int wl1271_event_ps_report(struct wl1271 *wl,
struct event_mailbox *mbox,
bool *beacon_loss)
{
int ret = 0;
wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
switch (mbox->ps_status) {
case EVENT_ENTER_POWER_SAVE_FAIL:
if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
wl->psm_entry_retry++;
wl1271_error("PSM entry failed, retrying %d\n",
wl->psm_entry_retry);
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
} else {
wl->psm_entry_retry = 0;
*beacon_loss = true;
}
break;
case EVENT_ENTER_POWER_SAVE_SUCCESS:
wl->psm_entry_retry = 0;
break;
case EVENT_EXIT_POWER_SAVE_FAIL:
wl1271_info("PSM exit failed");
break;
case EVENT_EXIT_POWER_SAVE_SUCCESS:
default:
break;
}
return ret;
}
static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
{
wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
@ -79,6 +113,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
{
int ret;
u32 vector;
bool beacon_loss = false;
wl1271_event_mbox_dump(mbox);
@ -101,7 +136,25 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
/* indicate to the stack, that beacons have been lost */
beacon_loss = true;
}
if (vector & PS_REPORT_EVENT_ID) {
wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
ret = wl1271_event_ps_report(wl, mbox, &beacon_loss);
if (ret < 0)
return ret;
}
if (beacon_loss) {
/* Obviously, it's dangerous to release the mutex while
we are holding many of the variables in the wl struct.
That's why it's done last in the function, and care must
be taken that nothing more is done after this function
returns. */
mutex_unlock(&wl->mutex);
ieee80211_beacon_loss(wl->vif);
mutex_lock(&wl->mutex);
}
return 0;

View file

@ -63,6 +63,13 @@ enum {
EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
};
enum {
EVENT_ENTER_POWER_SAVE_FAIL = 0,
EVENT_ENTER_POWER_SAVE_SUCCESS,
EVENT_EXIT_POWER_SAVE_FAIL,
EVENT_EXIT_POWER_SAVE_SUCCESS,
};
struct event_debug_report {
u8 debug_event_id;
u8 num_params;

View file

@ -303,12 +303,15 @@ int wl1271_hw_init(struct wl1271 *wl)
{
int ret;
/* FIXME: the following parameter setting functions return error
* codes - the reason is so far unknown. The -EIO is therefore
* ignored for the time being. */
ret = wl1271_init_general_parms(wl);
if (ret < 0)
if (ret < 0 && ret != -EIO)
return ret;
ret = wl1271_init_radio_parms(wl);
if (ret < 0)
if (ret < 0 && ret != -EIO)
return ret;
/* Template settings */

View file

@ -222,7 +222,8 @@ static struct conf_drv_settings default_conf = {
.snr_pkt_avg_weight = 10
},
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 100
.bet_max_consecutive = 100,
.psm_entry_retries = 3
},
.init = {
.sr_err_tbl = {
@ -973,6 +974,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->rx_counter = 0;
wl->elp = false;
wl->psm = 0;
wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->tx_blocks_available = 0;
@ -1067,11 +1069,11 @@ static int wl1271_op_config_interface(struct ieee80211_hw *hw,
ret = wl1271_cmd_join(wl);
if (ret < 0)
goto out_sleep;
}
ret = wl1271_cmd_build_null_data(wl);
if (ret < 0)
goto out_sleep;
ret = wl1271_cmd_build_null_data(wl);
if (ret < 0)
goto out_sleep;
}
wl->ssid_len = conf->ssid_len;
if (wl->ssid_len)
@ -1137,10 +1139,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wl->channel = channel;
}
ret = wl1271_cmd_build_null_data(wl);
if (ret < 0)
goto out_sleep;
if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
wl1271_info("psm enabled");
@ -1165,7 +1163,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (conf->power_level != wl->power_level) {
ret = wl1271_acx_tx_power(wl, conf->power_level);
if (ret < 0)
goto out;
goto out_sleep;
wl->power_level = conf->power_level;
}
@ -1826,6 +1824,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
wl->elp = false;
wl->psm = 0;
wl->psm_requested = false;
wl->psm_entry_retry = 0;
wl->tx_queue_stopped = false;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET;

View file

@ -159,7 +159,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
u8 *buf;
u8 beacon = 0;
skb = dev_alloc_skb(length);
skb = __dev_alloc_skb(length, GFP_KERNEL);
if (!skb) {
wl1271_error("Couldn't allocate RX frame");
return;

View file

@ -1,6 +1,6 @@
config ZD1211RW
tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
depends on USB && MAC80211 && EXPERIMENTAL
select FW_LOADER
---help---
This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless

View file

@ -131,5 +131,13 @@ source "drivers/staging/iio/Kconfig"
source "drivers/staging/cowloop/Kconfig"
source "drivers/staging/strip/Kconfig"
source "drivers/staging/arlan/Kconfig"
source "drivers/staging/wavelan/Kconfig"
source "drivers/staging/netwave/Kconfig"
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING

View file

@ -47,3 +47,8 @@ obj-$(CONFIG_RAR_REGISTER) += rar/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_COWLOOP) += cowloop/
obj-$(CONFIG_STRIP) += strip/
obj-$(CONFIG_ARLAN) += arlan/
obj-$(CONFIG_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave/

View file

@ -0,0 +1,15 @@
config ARLAN
tristate "Aironet Arlan 655 & IC2200 DS support"
depends on ISA && !64BIT
select WIRELESS_EXT
---help---
Aironet makes Arlan, a class of wireless LAN adapters. These use the
www.Telxon.com chip, which is also used on several similar cards.
This driver is tested on the 655 and IC2200 series cards. Look at
<http://www.ylenurme.ee/~elmer/655/> for the latest information.
The driver is built as two modules, arlan and arlan-proc. The latter
is the /proc interface and is not needed most of time.
On some computers the card ends up in non-valid state after some
time. Use a ping-reset script to clear it.

View file

@ -0,0 +1,3 @@
obj-$(CONFIG_ARLAN) += arlan.o
arlan-objs := arlan-main.o arlan-proc.o

View file

@ -0,0 +1,7 @@
TODO:
- step up and maintain this driver to ensure that it continues
to work. Having the hardware for this is pretty much a
requirement. If this does not happen, the will be removed in
the 2.6.35 kernel release.
Please send patches to Greg Kroah-Hartman <greg@kroah.com>.

View file

@ -0,0 +1,11 @@
config PCMCIA_NETWAVE
tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
depends on PCMCIA
select WIRELESS_EXT
select WEXT_PRIV
help
Say Y here if you intend to attach this type of PCMCIA (PC-card)
wireless Ethernet networking card to your computer.
To compile this driver as a module, choose M here: the module will be
called netwave_cs. If unsure, say N.

Some files were not shown because too many files have changed in this diff Show more